push 6fe5edf8439c19d3885814583531c2f2b1495177
[wine/hacks.git] / dlls / advapi32 / service.c
blobf9115c23ac6d9f04f988d5f23d0c30b90ef1571e
1 /*
2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
5 * Copyright 2005 Mike McCormack
6 * Copyright 2007 Rolf Kalbermatter
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include <stdarg.h>
24 #include <string.h>
25 #include <time.h>
26 #include <assert.h>
28 #include "windef.h"
29 #include "winbase.h"
30 #include "winsvc.h"
31 #include "winerror.h"
32 #include "winreg.h"
33 #include "wine/unicode.h"
34 #include "wine/debug.h"
35 #include "winternl.h"
36 #include "lmcons.h"
37 #include "lmserver.h"
39 #include "svcctl.h"
41 #include "wine/exception.h"
43 WINE_DEFAULT_DEBUG_CHANNEL(service);
45 static const WCHAR szLocalSystem[] = {'L','o','c','a','l','S','y','s','t','e','m',0};
46 static const WCHAR szServiceManagerKey[] = { 'S','y','s','t','e','m','\\',
47 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
48 'S','e','r','v','i','c','e','s',0 };
49 static const WCHAR szSCMLock[] = {'A','D','V','A','P','I','_','S','C','M',
50 'L','O','C','K',0};
52 void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len)
54 return HeapAlloc(GetProcessHeap(), 0, len);
57 void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
59 HeapFree(GetProcessHeap(), 0, ptr);
62 static const GENERIC_MAPPING scm_generic = {
63 (STANDARD_RIGHTS_READ | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS),
64 (STANDARD_RIGHTS_WRITE | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_MODIFY_BOOT_CONFIG),
65 (STANDARD_RIGHTS_EXECUTE | SC_MANAGER_CONNECT | SC_MANAGER_LOCK),
66 SC_MANAGER_ALL_ACCESS
69 static const GENERIC_MAPPING svc_generic = {
70 (STANDARD_RIGHTS_READ | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS),
71 (STANDARD_RIGHTS_WRITE | SERVICE_CHANGE_CONFIG),
72 (STANDARD_RIGHTS_EXECUTE | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_USER_DEFINED_CONTROL),
73 SERVICE_ALL_ACCESS
76 typedef struct service_data_t
78 LPHANDLER_FUNCTION_EX handler;
79 LPVOID context;
80 HANDLE thread;
81 BOOL unicode : 1;
82 union {
83 LPSERVICE_MAIN_FUNCTIONA a;
84 LPSERVICE_MAIN_FUNCTIONW w;
85 } proc;
86 LPWSTR args;
87 WCHAR name[1];
88 } service_data;
90 static CRITICAL_SECTION service_cs;
91 static CRITICAL_SECTION_DEBUG service_cs_debug =
93 0, 0, &service_cs,
94 { &service_cs_debug.ProcessLocksList,
95 &service_cs_debug.ProcessLocksList },
96 0, 0, { (DWORD_PTR)(__FILE__ ": service_cs") }
98 static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 };
100 static service_data **services;
101 static unsigned int nb_services;
102 static HANDLE service_event;
104 extern HANDLE __wine_make_process_system(void);
106 /******************************************************************************
107 * SC_HANDLEs
110 #define MAX_SERVICE_NAME 256
112 typedef enum { SC_HTYPE_MANAGER, SC_HTYPE_SERVICE } SC_HANDLE_TYPE;
114 struct sc_handle;
115 typedef VOID (*sc_handle_destructor)(struct sc_handle *);
117 struct sc_handle
119 SC_HANDLE_TYPE htype;
120 DWORD ref_count;
121 sc_handle_destructor destroy;
122 SC_RPC_HANDLE server_handle; /* server-side handle */
125 struct sc_manager /* service control manager handle */
127 struct sc_handle hdr;
128 HKEY hkey; /* handle to services database in the registry */
129 DWORD dwAccess;
132 struct sc_service /* service handle */
134 struct sc_handle hdr;
135 HKEY hkey; /* handle to service entry in the registry (under hkey) */
136 DWORD dwAccess;
137 struct sc_manager *scm; /* pointer to SCM handle */
138 WCHAR name[1];
141 static void *sc_handle_alloc(SC_HANDLE_TYPE htype, DWORD size,
142 sc_handle_destructor destroy)
144 struct sc_handle *hdr;
146 hdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
147 if (hdr)
149 hdr->htype = htype;
150 hdr->ref_count = 1;
151 hdr->destroy = destroy;
153 TRACE("sc_handle type=%d -> %p\n", htype, hdr);
154 return hdr;
157 static void *sc_handle_get_handle_data(SC_HANDLE handle, DWORD htype)
159 struct sc_handle *hdr = (struct sc_handle *) handle;
161 if (!hdr)
162 return NULL;
163 if (hdr->htype != htype)
164 return NULL;
165 return hdr;
168 static void sc_handle_free(struct sc_handle* hdr)
170 if (!hdr)
171 return;
172 if (--hdr->ref_count)
173 return;
174 hdr->destroy(hdr);
175 HeapFree(GetProcessHeap(), 0, hdr);
178 static void sc_handle_destroy_manager(struct sc_handle *handle)
180 struct sc_manager *mgr = (struct sc_manager*) handle;
182 TRACE("destroying SC Manager %p\n", mgr);
183 if (mgr->hkey)
184 RegCloseKey(mgr->hkey);
187 static void sc_handle_destroy_service(struct sc_handle *handle)
189 struct sc_service *svc = (struct sc_service*) handle;
191 TRACE("destroying service %p\n", svc);
192 if (svc->hkey)
193 RegCloseKey(svc->hkey);
194 svc->hkey = NULL;
195 sc_handle_free(&svc->scm->hdr);
196 svc->scm = NULL;
199 /******************************************************************************
200 * String management functions (same behaviour as strdup)
201 * NOTE: the caller of those functions is responsible for calling HeapFree
202 * in order to release the memory allocated by those functions.
204 static inline LPWSTR SERV_dup( LPCSTR str )
206 UINT len;
207 LPWSTR wstr;
209 if( !str )
210 return NULL;
211 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
212 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
213 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
214 return wstr;
217 static inline LPWSTR SERV_dupmulti(LPCSTR str)
219 UINT len = 0, n = 0;
220 LPWSTR wstr;
222 if( !str )
223 return NULL;
224 do {
225 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
226 n += (strlen( &str[n] ) + 1);
227 } while (str[n]);
228 len++;
229 n++;
231 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
232 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
233 return wstr;
236 static inline DWORD multisz_cb(LPCWSTR wmultisz)
238 const WCHAR *wptr = wmultisz;
240 if (wmultisz == NULL)
241 return 0;
243 while (*wptr)
244 wptr += lstrlenW(wptr)+1;
245 return (wptr - wmultisz + 1)*sizeof(WCHAR);
248 /******************************************************************************
249 * RPC connection with services.exe
252 handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName)
254 WCHAR transport[] = SVCCTL_TRANSPORT;
255 WCHAR endpoint[] = SVCCTL_ENDPOINT;
256 RPC_WSTR binding_str;
257 RPC_STATUS status;
258 handle_t rpc_handle;
260 status = RpcStringBindingComposeW(NULL, transport, (RPC_WSTR)MachineName, endpoint, NULL, &binding_str);
261 if (status != RPC_S_OK)
263 ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status);
264 return NULL;
267 status = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
268 RpcStringFreeW(&binding_str);
270 if (status != RPC_S_OK)
272 ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status);
273 return NULL;
276 return rpc_handle;
279 void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t h)
281 RpcBindingFree(&h);
284 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr)
286 return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode);
289 static DWORD map_exception_code(DWORD exception_code)
291 switch (exception_code)
293 case RPC_X_NULL_REF_POINTER:
294 case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
295 case RPC_X_BYTE_COUNT_TOO_SMALL:
296 return ERROR_INVALID_PARAMETER;
297 default:
298 return exception_code;
302 /******************************************************************************
303 * Service IPC functions
305 static LPWSTR service_get_pipe_name(void)
307 static const WCHAR format[] = { '\\','\\','.','\\','p','i','p','e','\\',
308 'n','e','t','\\','N','t','C','o','n','t','r','o','l','P','i','p','e','%','u',0};
309 static const WCHAR service_current_key_str[] = { 'S','Y','S','T','E','M','\\',
310 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
311 'C','o','n','t','r','o','l','\\',
312 'S','e','r','v','i','c','e','C','u','r','r','e','n','t',0};
313 LPWSTR name;
314 DWORD len;
315 HKEY service_current_key;
316 DWORD service_current;
317 LONG ret;
318 DWORD type;
320 ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, service_current_key_str, 0,
321 KEY_QUERY_VALUE, &service_current_key);
322 if (ret != ERROR_SUCCESS)
323 return NULL;
324 len = sizeof(service_current);
325 ret = RegQueryValueExW(service_current_key, NULL, NULL, &type,
326 (BYTE *)&service_current, &len);
327 RegCloseKey(service_current_key);
328 if (ret != ERROR_SUCCESS || type != REG_DWORD)
329 return NULL;
330 len = sizeof(format)/sizeof(WCHAR) + 10 /* strlenW("4294967295") */;
331 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
332 if (!name)
333 return NULL;
334 snprintfW(name, len, format, service_current);
335 return name;
338 static HANDLE service_open_pipe(void)
340 LPWSTR szPipe = service_get_pipe_name();
341 HANDLE handle = INVALID_HANDLE_VALUE;
343 do {
344 handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE,
345 0, NULL, OPEN_ALWAYS, 0, NULL);
346 if (handle != INVALID_HANDLE_VALUE)
347 break;
348 if (GetLastError() != ERROR_PIPE_BUSY)
349 break;
350 } while (WaitNamedPipeW(szPipe, NMPWAIT_WAIT_FOREVER));
351 HeapFree(GetProcessHeap(), 0, szPipe);
353 return handle;
356 /******************************************************************************
357 * service_thread
359 * Call into the main service routine provided by StartServiceCtrlDispatcher.
361 static DWORD WINAPI service_thread(LPVOID arg)
363 service_data *info = arg;
364 LPWSTR str = info->args;
365 DWORD argc = 0, len = 0;
367 TRACE("%p\n", arg);
369 while (str[len])
371 len += strlenW(&str[len]) + 1;
372 argc++;
375 if (!argc)
377 if (info->unicode)
378 info->proc.w(0, NULL);
379 else
380 info->proc.a(0, NULL);
381 return 0;
384 if (info->unicode)
386 LPWSTR *argv, p;
388 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
389 for (argc=0, p=str; *p; p += strlenW(p) + 1)
390 argv[argc++] = p;
391 argv[argc] = NULL;
393 info->proc.w(argc, argv);
394 HeapFree(GetProcessHeap(), 0, argv);
396 else
398 LPSTR strA, *argv, p;
399 DWORD lenA;
401 lenA = WideCharToMultiByte(CP_ACP,0, str, len, NULL, 0, NULL, NULL);
402 strA = HeapAlloc(GetProcessHeap(), 0, lenA);
403 WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
405 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPSTR));
406 for (argc=0, p=strA; *p; p += strlen(p) + 1)
407 argv[argc++] = p;
408 argv[argc] = NULL;
410 info->proc.a(argc, argv);
411 HeapFree(GetProcessHeap(), 0, argv);
412 HeapFree(GetProcessHeap(), 0, strA);
414 return 0;
417 /******************************************************************************
418 * service_handle_start
420 static BOOL service_handle_start(HANDLE pipe, service_data *service, DWORD count)
422 DWORD read = 0, result = 0;
423 LPWSTR args;
424 BOOL r;
426 TRACE("%p %p %d\n", pipe, service, count);
428 args = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
429 r = ReadFile(pipe, args, count*sizeof(WCHAR), &read, NULL);
430 if (!r || count!=read/sizeof(WCHAR) || args[count-1])
432 ERR("pipe read failed r = %d count = %d read = %d args[n-1]=%s\n",
433 r, count, read, debugstr_wn(args, count));
434 goto end;
437 if (service->thread)
439 WARN("service is not stopped\n");
440 result = ERROR_SERVICE_ALREADY_RUNNING;
441 goto end;
444 HeapFree(GetProcessHeap(), 0, service->args);
445 service->args = args;
446 args = NULL;
447 service->thread = CreateThread( NULL, 0, service_thread,
448 service, 0, NULL );
449 SetEvent( service_event ); /* notify the main loop */
451 end:
452 HeapFree(GetProcessHeap(), 0, args);
453 WriteFile( pipe, &result, sizeof result, &read, NULL );
455 return TRUE;
458 /******************************************************************************
459 * service_handle_control
461 static BOOL service_handle_control(HANDLE pipe, service_data *service,
462 DWORD dwControl)
464 DWORD count, ret = ERROR_INVALID_SERVICE_CONTROL;
466 TRACE("received control %d\n", dwControl);
468 if (service->handler)
469 ret = service->handler(dwControl, 0, NULL, service->context);
470 return WriteFile(pipe, &ret, sizeof ret, &count, NULL);
473 /******************************************************************************
474 * service_control_dispatcher
476 static DWORD WINAPI service_control_dispatcher(LPVOID arg)
478 service_data *service = arg;
479 HANDLE pipe;
481 TRACE("%p %s\n", service, debugstr_w(service->name));
483 pipe = service_open_pipe();
485 if (pipe==INVALID_HANDLE_VALUE)
487 ERR("failed to create pipe for %s, error = %d\n",
488 debugstr_w(service->name), GetLastError());
489 return 0;
492 /* dispatcher loop */
493 while (1)
495 BOOL r;
496 DWORD count, req[2] = {0,0};
498 r = ReadFile( pipe, &req, sizeof req, &count, NULL );
499 if (!r)
501 if (GetLastError() != ERROR_BROKEN_PIPE)
502 ERR( "pipe read failed error %u\n", GetLastError() );
503 break;
505 if (count != sizeof(req))
507 ERR( "partial pipe read %u\n", count );
508 break;
511 /* handle the request */
512 switch (req[0])
514 case WINESERV_STARTINFO:
515 service_handle_start(pipe, service, req[1]);
516 break;
517 case WINESERV_SENDCONTROL:
518 service_handle_control(pipe, service, req[1]);
519 break;
520 default:
521 ERR("received invalid command %d length %d\n", req[0], req[1]);
525 CloseHandle(pipe);
526 return 1;
529 /******************************************************************************
530 * service_run_threads
532 static BOOL service_run_threads(void)
534 DWORD i, n, ret;
535 HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
536 UINT wait_services[MAXIMUM_WAIT_OBJECTS];
538 service_event = CreateEventW( NULL, FALSE, FALSE, NULL );
540 wait_handles[0] = __wine_make_process_system();
541 wait_handles[1] = service_event;
543 TRACE("Starting %d pipe listener threads. Services running as process %d\n",
544 nb_services, GetCurrentProcessId());
546 EnterCriticalSection( &service_cs );
547 for (i = 0; i < nb_services; i++)
548 CloseHandle( CreateThread( NULL, 0, service_control_dispatcher, services[i], 0, NULL ));
549 LeaveCriticalSection( &service_cs );
551 /* wait for all the threads to pack up and exit */
552 for (;;)
554 EnterCriticalSection( &service_cs );
555 for (i = 0, n = 2; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
557 if (!services[i]->thread) continue;
558 wait_services[n] = i;
559 wait_handles[n++] = services[i]->thread;
561 LeaveCriticalSection( &service_cs );
563 ret = WaitForMultipleObjects( n, wait_handles, FALSE, INFINITE );
564 if (!ret) /* system process event */
566 TRACE( "last user process exited, shutting down\n" );
567 /* FIXME: we should maybe send a shutdown control to running services */
568 ExitProcess(0);
570 else if (ret == 1)
572 continue; /* rebuild the list */
574 else if (ret < n)
576 services[wait_services[ret]]->thread = 0;
577 CloseHandle( wait_handles[ret] );
578 if (n == 3) return TRUE; /* it was the last running thread */
580 else return FALSE;
584 /******************************************************************************
585 * StartServiceCtrlDispatcherA [ADVAPI32.@]
587 * See StartServiceCtrlDispatcherW.
589 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
591 service_data *info;
592 unsigned int i;
593 BOOL ret = TRUE;
595 TRACE("%p\n", servent);
597 if (nb_services)
599 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
600 return FALSE;
602 while (servent[nb_services].lpServiceName) nb_services++;
603 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
605 for (i = 0; i < nb_services; i++)
607 DWORD len = MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, NULL, 0);
608 DWORD sz = FIELD_OFFSET( service_data, name[len] );
609 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
610 MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, info->name, len);
611 info->proc.a = servent[i].lpServiceProc;
612 info->unicode = FALSE;
613 services[i] = info;
616 service_run_threads();
618 return ret;
621 /******************************************************************************
622 * StartServiceCtrlDispatcherW [ADVAPI32.@]
624 * Connects a process containing one or more services to the service control
625 * manager.
627 * PARAMS
628 * servent [I] A list of the service names and service procedures
630 * RETURNS
631 * Success: TRUE.
632 * Failure: FALSE.
634 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
636 service_data *info;
637 unsigned int i;
638 BOOL ret = TRUE;
640 TRACE("%p\n", servent);
642 if (nb_services)
644 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
645 return FALSE;
647 while (servent[nb_services].lpServiceName) nb_services++;
648 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
650 for (i = 0; i < nb_services; i++)
652 DWORD len = strlenW(servent[i].lpServiceName) + 1;
653 DWORD sz = FIELD_OFFSET( service_data, name[len] );
654 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
655 strcpyW(info->name, servent[i].lpServiceName);
656 info->proc.w = servent[i].lpServiceProc;
657 info->unicode = TRUE;
658 services[i] = info;
661 service_run_threads();
663 return ret;
666 /******************************************************************************
667 * LockServiceDatabase [ADVAPI32.@]
669 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
671 struct sc_manager *hscm;
672 SC_RPC_LOCK hLock = NULL;
673 DWORD err;
675 TRACE("%p\n",hSCManager);
677 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
678 if (!hscm)
680 SetLastError( ERROR_INVALID_HANDLE );
681 return NULL;
684 __TRY
686 err = svcctl_LockServiceDatabase(hscm->hdr.server_handle, &hLock);
688 __EXCEPT(rpc_filter)
690 err = map_exception_code(GetExceptionCode());
692 __ENDTRY
693 if (err != ERROR_SUCCESS)
695 SetLastError(err);
696 return NULL;
698 return hLock;
701 /******************************************************************************
702 * UnlockServiceDatabase [ADVAPI32.@]
704 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
706 DWORD err;
707 SC_RPC_LOCK hRpcLock = ScLock;
709 TRACE("%p\n",ScLock);
711 __TRY
713 err = svcctl_UnlockServiceDatabase(&hRpcLock);
715 __EXCEPT(rpc_filter)
717 err = map_exception_code(GetExceptionCode());
719 __ENDTRY
720 if (err != ERROR_SUCCESS)
722 SetLastError(err);
723 return FALSE;
725 return TRUE;
728 /******************************************************************************
729 * SetServiceStatus [ADVAPI32.@]
731 * PARAMS
732 * hService []
733 * lpStatus []
735 BOOL WINAPI
736 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
738 struct sc_service *hsvc;
739 DWORD err;
741 TRACE("%p %x %x %x %x %x %x %x\n", hService,
742 lpStatus->dwServiceType, lpStatus->dwCurrentState,
743 lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode,
744 lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint,
745 lpStatus->dwWaitHint);
747 hsvc = sc_handle_get_handle_data((SC_HANDLE)hService, SC_HTYPE_SERVICE);
748 if (!hsvc)
750 SetLastError( ERROR_INVALID_HANDLE );
751 return FALSE;
754 __TRY
756 err = svcctl_SetServiceStatus( hsvc->hdr.server_handle, lpStatus );
758 __EXCEPT(rpc_filter)
760 err = map_exception_code(GetExceptionCode());
762 __ENDTRY
763 if (err != ERROR_SUCCESS)
765 SetLastError(err);
766 return FALSE;
769 if (lpStatus->dwCurrentState == SERVICE_STOPPED)
770 CloseServiceHandle((SC_HANDLE)hService);
772 return TRUE;
776 /******************************************************************************
777 * OpenSCManagerA [ADVAPI32.@]
779 * Establish a connection to the service control manager and open its database.
781 * PARAMS
782 * lpMachineName [I] Pointer to machine name string
783 * lpDatabaseName [I] Pointer to database name string
784 * dwDesiredAccess [I] Type of access
786 * RETURNS
787 * Success: A Handle to the service control manager database
788 * Failure: NULL
790 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
791 DWORD dwDesiredAccess )
793 LPWSTR lpMachineNameW, lpDatabaseNameW;
794 SC_HANDLE ret;
796 lpMachineNameW = SERV_dup(lpMachineName);
797 lpDatabaseNameW = SERV_dup(lpDatabaseName);
798 ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess);
799 HeapFree(GetProcessHeap(), 0, lpDatabaseNameW);
800 HeapFree(GetProcessHeap(), 0, lpMachineNameW);
801 return ret;
804 /******************************************************************************
805 * OpenSCManagerW [ADVAPI32.@]
807 * See OpenSCManagerA.
809 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
810 DWORD dwDesiredAccess )
812 struct sc_manager *manager;
813 HKEY hReg;
814 LONG r;
815 DWORD new_mask = dwDesiredAccess;
817 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
818 debugstr_w(lpDatabaseName), dwDesiredAccess);
820 manager = sc_handle_alloc( SC_HTYPE_MANAGER, sizeof (struct sc_manager),
821 sc_handle_destroy_manager );
822 if (!manager)
823 return NULL;
825 __TRY
827 r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, &manager->hdr.server_handle);
829 __EXCEPT(rpc_filter)
831 r = map_exception_code(GetExceptionCode());
833 __ENDTRY
834 if (r!=ERROR_SUCCESS)
835 goto error;
837 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
838 if (r!=ERROR_SUCCESS)
839 goto error;
841 r = RegCreateKeyW(hReg, szServiceManagerKey, &manager->hkey);
842 RegCloseKey( hReg );
843 if (r!=ERROR_SUCCESS)
844 goto error;
846 RtlMapGenericMask(&new_mask, &scm_generic);
847 manager->dwAccess = new_mask;
848 TRACE("returning %p (access : 0x%08x)\n", manager, manager->dwAccess);
850 return (SC_HANDLE) &manager->hdr;
852 error:
853 sc_handle_free( &manager->hdr );
854 SetLastError( r);
855 return NULL;
858 /******************************************************************************
859 * ControlService [ADVAPI32.@]
861 * Send a control code to a service.
863 * PARAMS
864 * hService [I] Handle of the service control manager database
865 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
866 * lpServiceStatus [O] Destination for the status of the service, if available
868 * RETURNS
869 * Success: TRUE.
870 * Failure: FALSE.
872 * BUGS
873 * Unlike M$' implementation, control requests are not serialized and may be
874 * processed asynchronously.
876 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
877 LPSERVICE_STATUS lpServiceStatus )
879 struct sc_service *hsvc;
880 DWORD err;
882 TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
884 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
885 if (!hsvc)
887 SetLastError( ERROR_INVALID_HANDLE );
888 return FALSE;
891 __TRY
893 err = svcctl_ControlService(hsvc->hdr.server_handle, dwControl, lpServiceStatus);
895 __EXCEPT(rpc_filter)
897 err = map_exception_code(GetExceptionCode());
899 __ENDTRY
900 if (err != ERROR_SUCCESS)
902 SetLastError(err);
903 return FALSE;
906 return TRUE;
909 /******************************************************************************
910 * CloseServiceHandle [ADVAPI32.@]
912 * Close a handle to a service or the service control manager database.
914 * PARAMS
915 * hSCObject [I] Handle to service or service control manager database
917 * RETURNS
918 * Success: TRUE
919 * Failure: FALSE
921 BOOL WINAPI
922 CloseServiceHandle( SC_HANDLE hSCObject )
924 struct sc_handle *obj;
925 DWORD err;
927 TRACE("%p\n", hSCObject);
928 if (hSCObject == NULL)
930 SetLastError(ERROR_INVALID_HANDLE);
931 return FALSE;
934 obj = (struct sc_handle *)hSCObject;
935 __TRY
937 err = svcctl_CloseServiceHandle(&obj->server_handle);
939 __EXCEPT(rpc_filter)
941 err = map_exception_code(GetExceptionCode());
943 __ENDTRY
944 sc_handle_free( obj );
946 if (err != ERROR_SUCCESS)
948 SetLastError(err);
949 return FALSE;
951 return TRUE;
955 /******************************************************************************
956 * OpenServiceA [ADVAPI32.@]
958 * Open a handle to a service.
960 * PARAMS
961 * hSCManager [I] Handle of the service control manager database
962 * lpServiceName [I] Name of the service to open
963 * dwDesiredAccess [I] Access required to the service
965 * RETURNS
966 * Success: Handle to the service
967 * Failure: NULL
969 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
970 DWORD dwDesiredAccess )
972 LPWSTR lpServiceNameW;
973 SC_HANDLE ret;
975 TRACE("%p %s %d\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
977 lpServiceNameW = SERV_dup(lpServiceName);
978 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
979 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
980 return ret;
984 /******************************************************************************
985 * OpenServiceW [ADVAPI32.@]
987 * See OpenServiceA.
989 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
990 DWORD dwDesiredAccess)
992 struct sc_manager *hscm;
993 struct sc_service *hsvc;
994 DWORD err;
995 DWORD len;
996 DWORD new_mask = dwDesiredAccess;
998 TRACE("%p %s %d\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
1000 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
1001 if (!hscm)
1003 SetLastError( ERROR_INVALID_HANDLE );
1004 return FALSE;
1007 if (!lpServiceName)
1009 SetLastError(ERROR_INVALID_ADDRESS);
1010 return NULL;
1013 len = strlenW(lpServiceName)+1;
1014 hsvc = sc_handle_alloc( SC_HTYPE_SERVICE,
1015 sizeof (struct sc_service) + len*sizeof(WCHAR),
1016 sc_handle_destroy_service );
1017 if (!hsvc)
1019 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1020 return NULL;
1022 strcpyW( hsvc->name, lpServiceName );
1024 /* add reference to SCM handle */
1025 hscm->hdr.ref_count++;
1026 hsvc->scm = hscm;
1028 __TRY
1030 err = svcctl_OpenServiceW(hscm->hdr.server_handle, lpServiceName, dwDesiredAccess, &hsvc->hdr.server_handle);
1032 __EXCEPT(rpc_filter)
1034 err = map_exception_code(GetExceptionCode());
1036 __ENDTRY
1038 if (err != ERROR_SUCCESS)
1040 sc_handle_free(&hsvc->hdr);
1041 SetLastError(err);
1042 return NULL;
1045 /* for parts of advapi32 not using services.exe yet */
1046 RtlMapGenericMask(&new_mask, &svc_generic);
1047 hsvc->dwAccess = new_mask;
1049 err = RegOpenKeyExW( hscm->hkey, lpServiceName, 0, KEY_ALL_ACCESS, &hsvc->hkey );
1050 if (err != ERROR_SUCCESS)
1051 ERR("Shouldn't hapen - service key for service validated by services.exe doesn't exist\n");
1053 TRACE("returning %p\n",hsvc);
1055 return (SC_HANDLE) &hsvc->hdr;
1058 /******************************************************************************
1059 * CreateServiceW [ADVAPI32.@]
1061 SC_HANDLE WINAPI
1062 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1063 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
1064 DWORD dwServiceType, DWORD dwStartType,
1065 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1066 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1067 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
1068 LPCWSTR lpPassword )
1070 struct sc_manager *hscm;
1071 struct sc_service *hsvc = NULL;
1072 DWORD new_mask = dwDesiredAccess;
1073 DWORD len, err;
1074 SIZE_T passwdlen;
1076 TRACE("%p %s %s\n", hSCManager,
1077 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
1079 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
1080 if (!hscm)
1082 SetLastError( ERROR_INVALID_HANDLE );
1083 return NULL;
1086 if (!lpServiceName || !lpBinaryPathName)
1088 SetLastError(ERROR_INVALID_ADDRESS);
1089 return NULL;
1092 if (lpPassword)
1093 passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
1094 else
1095 passwdlen = 0;
1097 len = strlenW(lpServiceName)+1;
1098 len = sizeof (struct sc_service) + len*sizeof(WCHAR);
1099 hsvc = sc_handle_alloc( SC_HTYPE_SERVICE, len, sc_handle_destroy_service );
1100 if( !hsvc )
1102 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1103 return NULL;
1105 lstrcpyW( hsvc->name, lpServiceName );
1107 hsvc->scm = hscm;
1108 hscm->hdr.ref_count++;
1110 __TRY
1112 err = svcctl_CreateServiceW(hscm->hdr.server_handle, lpServiceName,
1113 lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1114 lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (LPBYTE)lpDependencies,
1115 multisz_cb(lpDependencies), lpServiceStartName, (LPBYTE)lpPassword, passwdlen,
1116 &hsvc->hdr.server_handle);
1118 __EXCEPT(rpc_filter)
1120 err = map_exception_code(GetExceptionCode());
1122 __ENDTRY
1124 if (err != ERROR_SUCCESS)
1126 SetLastError(err);
1127 sc_handle_free(&hsvc->hdr);
1128 return NULL;
1131 /* for parts of advapi32 not using services.exe yet */
1132 err = RegOpenKeyW(hscm->hkey, lpServiceName, &hsvc->hkey);
1133 if (err != ERROR_SUCCESS)
1134 WINE_ERR("Couldn't open key that should have been created by services.exe\n");
1136 RtlMapGenericMask(&new_mask, &svc_generic);
1137 hsvc->dwAccess = new_mask;
1139 return (SC_HANDLE) &hsvc->hdr;
1143 /******************************************************************************
1144 * CreateServiceA [ADVAPI32.@]
1146 SC_HANDLE WINAPI
1147 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1148 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
1149 DWORD dwServiceType, DWORD dwStartType,
1150 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1151 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1152 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
1153 LPCSTR lpPassword )
1155 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
1156 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
1157 SC_HANDLE r;
1159 TRACE("%p %s %s\n", hSCManager,
1160 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
1162 lpServiceNameW = SERV_dup( lpServiceName );
1163 lpDisplayNameW = SERV_dup( lpDisplayName );
1164 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
1165 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
1166 lpDependenciesW = SERV_dupmulti( lpDependencies );
1167 lpServiceStartNameW = SERV_dup( lpServiceStartName );
1168 lpPasswordW = SERV_dup( lpPassword );
1170 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
1171 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1172 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
1173 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
1175 HeapFree( GetProcessHeap(), 0, lpServiceNameW );
1176 HeapFree( GetProcessHeap(), 0, lpDisplayNameW );
1177 HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW );
1178 HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW );
1179 HeapFree( GetProcessHeap(), 0, lpDependenciesW );
1180 HeapFree( GetProcessHeap(), 0, lpServiceStartNameW );
1181 HeapFree( GetProcessHeap(), 0, lpPasswordW );
1183 return r;
1187 /******************************************************************************
1188 * DeleteService [ADVAPI32.@]
1190 * Delete a service from the service control manager database.
1192 * PARAMS
1193 * hService [I] Handle of the service to delete
1195 * RETURNS
1196 * Success: TRUE
1197 * Failure: FALSE
1199 BOOL WINAPI DeleteService( SC_HANDLE hService )
1201 struct sc_service *hsvc;
1202 DWORD err;
1204 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1205 if (!hsvc)
1207 SetLastError( ERROR_INVALID_HANDLE );
1208 return FALSE;
1211 __TRY
1213 err = svcctl_DeleteService(hsvc->hdr.server_handle);
1215 __EXCEPT(rpc_filter)
1217 err = map_exception_code(GetExceptionCode());
1219 __ENDTRY
1220 if (err != 0)
1222 SetLastError(err);
1223 return FALSE;
1226 /* Close the key to the service */
1227 RegCloseKey(hsvc->hkey);
1228 hsvc->hkey = NULL;
1229 return TRUE;
1233 /******************************************************************************
1234 * StartServiceA [ADVAPI32.@]
1236 * Start a service
1238 * PARAMS
1239 * hService [I] Handle of service
1240 * dwNumServiceArgs [I] Number of arguments
1241 * lpServiceArgVectors [I] Address of array of argument strings
1243 * NOTES
1244 * - NT implements this function using an obscure RPC call.
1245 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1246 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1247 * - This will only work for shared address space. How should the service
1248 * args be transferred when address spaces are separated?
1249 * - Can only start one service at a time.
1250 * - Has no concept of privilege.
1252 * RETURNS
1253 * Success: TRUE.
1254 * Failure: FALSE
1256 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1257 LPCSTR *lpServiceArgVectors )
1259 LPWSTR *lpwstr=NULL;
1260 unsigned int i;
1261 BOOL r;
1263 TRACE("(%p,%d,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
1265 if (dwNumServiceArgs)
1266 lpwstr = HeapAlloc( GetProcessHeap(), 0,
1267 dwNumServiceArgs*sizeof(LPWSTR) );
1269 for(i=0; i<dwNumServiceArgs; i++)
1270 lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1272 r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1274 if (dwNumServiceArgs)
1276 for(i=0; i<dwNumServiceArgs; i++)
1277 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
1278 HeapFree(GetProcessHeap(), 0, lpwstr);
1281 return r;
1285 /******************************************************************************
1286 * StartServiceW [ADVAPI32.@]
1288 * See StartServiceA.
1290 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1291 LPCWSTR *lpServiceArgVectors)
1293 struct sc_service *hsvc;
1294 DWORD err;
1296 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1298 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1299 if (!hsvc)
1301 SetLastError(ERROR_INVALID_HANDLE);
1302 return FALSE;
1305 __TRY
1307 err = svcctl_StartServiceW(hsvc->hdr.server_handle, dwNumServiceArgs, lpServiceArgVectors);
1309 __EXCEPT(rpc_filter)
1311 err = map_exception_code(GetExceptionCode());
1313 __ENDTRY
1314 if (err != ERROR_SUCCESS)
1316 SetLastError(err);
1317 return FALSE;
1320 return TRUE;
1323 /******************************************************************************
1324 * QueryServiceStatus [ADVAPI32.@]
1326 * PARAMS
1327 * hService [I] Handle to service to get information about
1328 * lpservicestatus [O] buffer to receive the status information for the service
1331 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1332 LPSERVICE_STATUS lpservicestatus)
1334 SERVICE_STATUS_PROCESS SvcStatusData;
1335 BOOL ret;
1336 DWORD dummy;
1338 TRACE("%p %p\n", hService, lpservicestatus);
1340 ret = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&SvcStatusData,
1341 sizeof(SERVICE_STATUS_PROCESS), &dummy);
1342 if (ret) memcpy(lpservicestatus, &SvcStatusData, sizeof(SERVICE_STATUS)) ;
1343 return ret;
1347 /******************************************************************************
1348 * QueryServiceStatusEx [ADVAPI32.@]
1350 * Get information about a service.
1352 * PARAMS
1353 * hService [I] Handle to service to get information about
1354 * InfoLevel [I] Level of information to get
1355 * lpBuffer [O] Destination for requested information
1356 * cbBufSize [I] Size of lpBuffer in bytes
1357 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1359 * RETURNS
1360 * Success: TRUE
1361 * FAILURE: FALSE
1363 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1364 LPBYTE lpBuffer, DWORD cbBufSize,
1365 LPDWORD pcbBytesNeeded)
1367 struct sc_service *hsvc;
1368 DWORD err;
1370 TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1372 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1373 if (!hsvc)
1375 SetLastError( ERROR_INVALID_HANDLE );
1376 return FALSE;
1379 __TRY
1381 err = svcctl_QueryServiceStatusEx(hsvc->hdr.server_handle, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1383 __EXCEPT(rpc_filter)
1385 err = map_exception_code(GetExceptionCode());
1387 __ENDTRY
1388 if (err != ERROR_SUCCESS)
1390 SetLastError(err);
1391 return FALSE;
1394 return TRUE;
1397 /******************************************************************************
1398 * QueryServiceConfigA [ADVAPI32.@]
1400 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1401 DWORD size, LPDWORD needed )
1403 DWORD n;
1404 LPSTR p, buffer;
1405 BOOL ret;
1406 QUERY_SERVICE_CONFIGW *configW;
1408 TRACE("%p %p %d %p\n", hService, config, size, needed);
1410 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, 2 * size )))
1412 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1413 return FALSE;
1415 configW = (QUERY_SERVICE_CONFIGW *)buffer;
1416 ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1417 if (!ret) goto done;
1419 config->dwServiceType = configW->dwServiceType;
1420 config->dwStartType = configW->dwStartType;
1421 config->dwErrorControl = configW->dwErrorControl;
1422 config->lpBinaryPathName = NULL;
1423 config->lpLoadOrderGroup = NULL;
1424 config->dwTagId = configW->dwTagId;
1425 config->lpDependencies = NULL;
1426 config->lpServiceStartName = NULL;
1427 config->lpDisplayName = NULL;
1429 p = (LPSTR)(config + 1);
1430 n = size - sizeof(*config);
1431 ret = FALSE;
1433 #define MAP_STR(str) \
1434 do { \
1435 if (configW->str) \
1437 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1438 if (!sz) goto done; \
1439 config->str = p; \
1440 p += sz; \
1441 n -= sz; \
1443 } while (0)
1445 MAP_STR( lpBinaryPathName );
1446 MAP_STR( lpLoadOrderGroup );
1447 MAP_STR( lpDependencies );
1448 MAP_STR( lpServiceStartName );
1449 MAP_STR( lpDisplayName );
1450 #undef MAP_STR
1452 *needed = p - (LPSTR)config;
1453 ret = TRUE;
1455 done:
1456 HeapFree( GetProcessHeap(), 0, buffer );
1457 return ret;
1460 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1462 DWORD cb;
1464 if (!*string_ptr)
1466 cb = sizeof(WCHAR);
1467 memset(*buf, 0, cb);
1469 else
1471 cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
1472 memcpy(*buf, *string_ptr, cb);
1473 MIDL_user_free(*string_ptr);
1476 *string_ptr = (LPWSTR)*buf;
1477 *buf += cb;
1479 return cb;
1482 static DWORD size_string(LPWSTR string)
1484 return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1487 /******************************************************************************
1488 * QueryServiceConfigW [ADVAPI32.@]
1490 BOOL WINAPI
1491 QueryServiceConfigW( SC_HANDLE hService,
1492 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1493 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1495 QUERY_SERVICE_CONFIGW config;
1496 struct sc_service *hsvc;
1497 DWORD total;
1498 DWORD err;
1499 BYTE *bufpos;
1501 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1502 cbBufSize, pcbBytesNeeded);
1504 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1505 if (!hsvc)
1507 SetLastError( ERROR_INVALID_HANDLE );
1508 return FALSE;
1511 memset(&config, 0, sizeof(config));
1513 __TRY
1515 err = svcctl_QueryServiceConfigW(hsvc->hdr.server_handle, &config);
1517 __EXCEPT(rpc_filter)
1519 err = map_exception_code(GetExceptionCode());
1521 __ENDTRY
1523 if (err != ERROR_SUCCESS)
1525 TRACE("services.exe: error %u\n", err);
1526 SetLastError(err);
1527 return FALSE;
1530 /* calculate the size required first */
1531 total = sizeof (QUERY_SERVICE_CONFIGW);
1532 total += size_string(config.lpBinaryPathName);
1533 total += size_string(config.lpLoadOrderGroup);
1534 total += size_string(config.lpDependencies);
1535 total += size_string(config.lpServiceStartName);
1536 total += size_string(config.lpDisplayName);
1538 *pcbBytesNeeded = total;
1540 /* if there's not enough memory, return an error */
1541 if( total > cbBufSize )
1543 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1544 MIDL_user_free(config.lpBinaryPathName);
1545 MIDL_user_free(config.lpLoadOrderGroup);
1546 MIDL_user_free(config.lpDependencies);
1547 MIDL_user_free(config.lpServiceStartName);
1548 MIDL_user_free(config.lpDisplayName);
1549 return FALSE;
1552 *lpServiceConfig = config;
1553 bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
1554 move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
1555 move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
1556 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
1557 move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
1558 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
1560 if (bufpos - (LPBYTE)lpServiceConfig > cbBufSize)
1561 ERR("Buffer overflow!\n");
1563 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1564 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1565 TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig->lpDependencies) );
1566 TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) );
1567 TRACE("Display name = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) );
1569 return TRUE;
1572 /******************************************************************************
1573 * QueryServiceConfig2A [ADVAPI32.@]
1575 * Note
1576 * observed under win2k:
1577 * The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1578 * required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1580 BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1581 DWORD size, LPDWORD needed)
1583 BOOL ret;
1584 LPBYTE bufferW = NULL;
1586 if(buffer && size)
1587 bufferW = HeapAlloc( GetProcessHeap(), 0, size);
1589 ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1590 if(!ret) goto cleanup;
1592 switch(dwLevel) {
1593 case SERVICE_CONFIG_DESCRIPTION:
1594 { LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1595 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1596 if (configW->lpDescription) {
1597 DWORD sz;
1598 configA->lpDescription = (LPSTR)(configA + 1);
1599 sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1600 configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1601 if (!sz) {
1602 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1603 ret = FALSE;
1604 configA->lpDescription = NULL;
1607 else configA->lpDescription = NULL;
1609 break;
1610 default:
1611 FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1612 ret = FALSE;
1615 cleanup:
1616 HeapFree( GetProcessHeap(), 0, bufferW);
1617 return ret;
1620 /******************************************************************************
1621 * QueryServiceConfig2W [ADVAPI32.@]
1623 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1624 DWORD size, LPDWORD needed)
1626 DWORD sz, type;
1627 HKEY hKey;
1628 LONG r;
1629 struct sc_service *hsvc;
1631 if(dwLevel != SERVICE_CONFIG_DESCRIPTION) {
1632 if((dwLevel == SERVICE_CONFIG_DELAYED_AUTO_START_INFO) ||
1633 (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS) ||
1634 (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS_FLAG) ||
1635 (dwLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO) ||
1636 (dwLevel == SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO) ||
1637 (dwLevel == SERVICE_CONFIG_SERVICE_SID_INFO))
1638 FIXME("Level %d not implemented\n", dwLevel);
1639 SetLastError(ERROR_INVALID_LEVEL);
1640 return FALSE;
1642 if(!needed || (!buffer && size)) {
1643 SetLastError(ERROR_INVALID_ADDRESS);
1644 return FALSE;
1647 TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
1649 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1650 if (!hsvc)
1652 SetLastError(ERROR_INVALID_HANDLE);
1653 return FALSE;
1655 hKey = hsvc->hkey;
1657 switch(dwLevel) {
1658 case SERVICE_CONFIG_DESCRIPTION: {
1659 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1660 LPSERVICE_DESCRIPTIONW config = (LPSERVICE_DESCRIPTIONW) buffer;
1661 LPBYTE strbuf = NULL;
1662 *needed = sizeof (SERVICE_DESCRIPTIONW);
1663 sz = size - *needed;
1664 if(config && (*needed <= size))
1665 strbuf = (LPBYTE) (config + 1);
1666 r = RegQueryValueExW( hKey, szDescription, 0, &type, strbuf, &sz );
1667 if((r == ERROR_SUCCESS) && ( type != REG_SZ)) {
1668 FIXME("SERVICE_CONFIG_DESCRIPTION: don't know how to handle type %d\n", type);
1669 return FALSE;
1671 *needed += sz;
1672 if(config) {
1673 if(r == ERROR_SUCCESS)
1674 config->lpDescription = (LPWSTR) (config + 1);
1675 else
1676 config->lpDescription = NULL;
1679 break;
1681 if(*needed > size)
1682 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1684 return (*needed <= size);
1687 /******************************************************************************
1688 * EnumServicesStatusA [ADVAPI32.@]
1690 BOOL WINAPI
1691 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
1692 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
1693 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1694 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1696 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1697 dwServiceType, dwServiceState, lpServices, cbBufSize,
1698 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1699 SetLastError (ERROR_ACCESS_DENIED);
1700 return FALSE;
1703 /******************************************************************************
1704 * EnumServicesStatusW [ADVAPI32.@]
1706 BOOL WINAPI
1707 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
1708 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
1709 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1710 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1712 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1713 dwServiceType, dwServiceState, lpServices, cbBufSize,
1714 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1715 SetLastError (ERROR_ACCESS_DENIED);
1716 return FALSE;
1719 /******************************************************************************
1720 * EnumServicesStatusExA [ADVAPI32.@]
1722 BOOL WINAPI
1723 EnumServicesStatusExA(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType,
1724 DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1725 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCSTR pszGroupName)
1727 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager, InfoLevel,
1728 dwServiceType, dwServiceState, lpServices, cbBufSize,
1729 pcbBytesNeeded, lpServicesReturned, lpResumeHandle, debugstr_a(pszGroupName));
1730 *lpServicesReturned = 0;
1731 SetLastError (ERROR_ACCESS_DENIED);
1732 return FALSE;
1735 /******************************************************************************
1736 * EnumServicesStatusExW [ADVAPI32.@]
1738 BOOL WINAPI
1739 EnumServicesStatusExW(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType,
1740 DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1741 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCWSTR pszGroupName)
1743 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager, InfoLevel,
1744 dwServiceType, dwServiceState, lpServices, cbBufSize,
1745 pcbBytesNeeded, lpServicesReturned, lpResumeHandle, debugstr_w(pszGroupName));
1746 SetLastError (ERROR_ACCESS_DENIED);
1747 return FALSE;
1750 /******************************************************************************
1751 * GetServiceKeyNameA [ADVAPI32.@]
1753 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1754 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1756 LPWSTR lpDisplayNameW, lpServiceNameW;
1757 DWORD sizeW;
1758 BOOL ret = FALSE;
1760 TRACE("%p %s %p %p\n", hSCManager,
1761 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1763 lpDisplayNameW = SERV_dup(lpDisplayName);
1764 if (lpServiceName)
1765 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1766 else
1767 lpServiceNameW = NULL;
1769 sizeW = *lpcchBuffer;
1770 if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
1772 if (*lpcchBuffer && lpServiceName)
1773 lpServiceName[0] = 0;
1774 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1775 goto cleanup;
1778 if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
1779 *lpcchBuffer, NULL, NULL ))
1781 if (*lpcchBuffer && lpServiceName)
1782 lpServiceName[0] = 0;
1783 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
1784 goto cleanup;
1787 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1788 ret = TRUE;
1790 cleanup:
1791 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1792 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1793 return ret;
1796 /******************************************************************************
1797 * GetServiceKeyNameW [ADVAPI32.@]
1799 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1800 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1802 struct sc_manager *hscm;
1803 DWORD err;
1805 TRACE("%p %s %p %p\n", hSCManager,
1806 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1808 hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER);
1809 if (!hscm)
1811 SetLastError(ERROR_INVALID_HANDLE);
1812 return FALSE;
1815 if (!lpDisplayName)
1817 SetLastError(ERROR_INVALID_ADDRESS);
1818 return FALSE;
1821 __TRY
1823 err = svcctl_GetServiceKeyNameW(hscm->hdr.server_handle,
1824 lpDisplayName, lpServiceName, lpServiceName ? *lpcchBuffer : 0, lpcchBuffer);
1826 __EXCEPT(rpc_filter)
1828 err = map_exception_code(GetExceptionCode());
1830 __ENDTRY
1832 if (err)
1833 SetLastError(err);
1834 return err == ERROR_SUCCESS;
1837 /******************************************************************************
1838 * QueryServiceLockStatusA [ADVAPI32.@]
1840 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1841 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1842 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1844 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1846 return FALSE;
1849 /******************************************************************************
1850 * QueryServiceLockStatusW [ADVAPI32.@]
1852 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1853 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1854 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1856 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1858 return FALSE;
1861 /******************************************************************************
1862 * GetServiceDisplayNameA [ADVAPI32.@]
1864 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1865 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1867 LPWSTR lpServiceNameW, lpDisplayNameW;
1868 DWORD sizeW;
1869 BOOL ret = FALSE;
1871 TRACE("%p %s %p %p\n", hSCManager,
1872 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1874 lpServiceNameW = SERV_dup(lpServiceName);
1875 if (lpDisplayName)
1876 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1877 else
1878 lpDisplayNameW = NULL;
1880 sizeW = *lpcchBuffer;
1881 if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
1883 if (*lpcchBuffer && lpDisplayName)
1884 lpDisplayName[0] = 0;
1885 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1886 goto cleanup;
1889 if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
1890 *lpcchBuffer, NULL, NULL ))
1892 if (*lpcchBuffer && lpDisplayName)
1893 lpDisplayName[0] = 0;
1894 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
1895 goto cleanup;
1898 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1899 * (but if the function succeeded it means that is a good upper estimation of the size) */
1900 ret = TRUE;
1902 cleanup:
1903 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1904 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1905 return ret;
1908 /******************************************************************************
1909 * GetServiceDisplayNameW [ADVAPI32.@]
1911 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1912 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1914 struct sc_manager *hscm;
1915 DWORD err;
1917 TRACE("%p %s %p %p\n", hSCManager,
1918 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1920 hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER);
1921 if (!hscm)
1923 SetLastError(ERROR_INVALID_HANDLE);
1924 return FALSE;
1927 if (!lpServiceName)
1929 SetLastError(ERROR_INVALID_ADDRESS);
1930 return FALSE;
1933 __TRY
1935 err = svcctl_GetServiceDisplayNameW(hscm->hdr.server_handle,
1936 lpServiceName, lpDisplayName, lpDisplayName ? *lpcchBuffer : 0, lpcchBuffer);
1938 __EXCEPT(rpc_filter)
1940 err = map_exception_code(GetExceptionCode());
1942 __ENDTRY
1944 if (err)
1945 SetLastError(err);
1946 return err == ERROR_SUCCESS;
1949 /******************************************************************************
1950 * ChangeServiceConfigW [ADVAPI32.@]
1952 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1953 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1954 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1955 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1957 struct sc_service *hsvc;
1958 DWORD cb_pwd;
1959 DWORD err;
1961 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
1962 hService, dwServiceType, dwStartType, dwErrorControl,
1963 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1964 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1965 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1967 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1968 if (!hsvc)
1970 SetLastError( ERROR_INVALID_HANDLE );
1971 return FALSE;
1974 cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
1976 __TRY
1978 err = svcctl_ChangeServiceConfigW(hsvc->hdr.server_handle, dwServiceType,
1979 dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
1980 (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
1981 (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
1983 __EXCEPT(rpc_filter)
1985 err = map_exception_code(GetExceptionCode());
1987 __ENDTRY
1989 if (err != ERROR_SUCCESS)
1990 SetLastError(err);
1992 return err == ERROR_SUCCESS;
1995 /******************************************************************************
1996 * ChangeServiceConfigA [ADVAPI32.@]
1998 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
1999 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
2000 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
2001 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
2003 LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
2004 LPWSTR wServiceStartName, wPassword, wDisplayName;
2005 BOOL r;
2007 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2008 hService, dwServiceType, dwStartType, dwErrorControl,
2009 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
2010 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
2011 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
2013 wBinaryPathName = SERV_dup( lpBinaryPathName );
2014 wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
2015 wDependencies = SERV_dupmulti( lpDependencies );
2016 wServiceStartName = SERV_dup( lpServiceStartName );
2017 wPassword = SERV_dup( lpPassword );
2018 wDisplayName = SERV_dup( lpDisplayName );
2020 r = ChangeServiceConfigW( hService, dwServiceType,
2021 dwStartType, dwErrorControl, wBinaryPathName,
2022 wLoadOrderGroup, lpdwTagId, wDependencies,
2023 wServiceStartName, wPassword, wDisplayName);
2025 HeapFree( GetProcessHeap(), 0, wBinaryPathName );
2026 HeapFree( GetProcessHeap(), 0, wLoadOrderGroup );
2027 HeapFree( GetProcessHeap(), 0, wDependencies );
2028 HeapFree( GetProcessHeap(), 0, wServiceStartName );
2029 HeapFree( GetProcessHeap(), 0, wPassword );
2030 HeapFree( GetProcessHeap(), 0, wDisplayName );
2032 return r;
2035 /******************************************************************************
2036 * ChangeServiceConfig2A [ADVAPI32.@]
2038 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
2039 LPVOID lpInfo)
2041 BOOL r = FALSE;
2043 TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
2045 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2047 LPSERVICE_DESCRIPTIONA sd = (LPSERVICE_DESCRIPTIONA) lpInfo;
2048 SERVICE_DESCRIPTIONW sdw;
2050 sdw.lpDescription = SERV_dup( sd->lpDescription );
2052 r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
2054 HeapFree( GetProcessHeap(), 0, sdw.lpDescription );
2056 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
2058 LPSERVICE_FAILURE_ACTIONSA fa = (LPSERVICE_FAILURE_ACTIONSA) lpInfo;
2059 SERVICE_FAILURE_ACTIONSW faw;
2061 faw.dwResetPeriod = fa->dwResetPeriod;
2062 faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
2063 faw.lpCommand = SERV_dup( fa->lpCommand );
2064 faw.cActions = fa->cActions;
2065 faw.lpsaActions = fa->lpsaActions;
2067 r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
2069 HeapFree( GetProcessHeap(), 0, faw.lpRebootMsg );
2070 HeapFree( GetProcessHeap(), 0, faw.lpCommand );
2072 else
2073 SetLastError( ERROR_INVALID_PARAMETER );
2075 return r;
2078 /******************************************************************************
2079 * ChangeServiceConfig2W [ADVAPI32.@]
2081 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
2082 LPVOID lpInfo)
2084 HKEY hKey;
2085 struct sc_service *hsvc;
2087 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
2088 if (!hsvc)
2090 SetLastError( ERROR_INVALID_HANDLE );
2091 return FALSE;
2093 hKey = hsvc->hkey;
2095 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2097 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
2098 LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo;
2099 if (sd->lpDescription)
2101 TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
2102 if (sd->lpDescription[0] == 0)
2103 RegDeleteValueW(hKey,szDescription);
2104 else
2105 RegSetValueExW(hKey, szDescription, 0, REG_SZ,
2106 (LPVOID)sd->lpDescription,
2107 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
2110 else
2111 FIXME("STUB: %p %d %p\n",hService, dwInfoLevel, lpInfo);
2112 return TRUE;
2115 /******************************************************************************
2116 * QueryServiceObjectSecurity [ADVAPI32.@]
2118 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
2119 SECURITY_INFORMATION dwSecurityInformation,
2120 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2121 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2123 SECURITY_DESCRIPTOR descriptor;
2124 DWORD size;
2125 BOOL succ;
2126 ACL acl;
2128 FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
2129 lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
2131 if (dwSecurityInformation != DACL_SECURITY_INFORMATION)
2132 FIXME("information %d not supported\n", dwSecurityInformation);
2134 InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION);
2136 InitializeAcl(&acl, sizeof(ACL), ACL_REVISION);
2137 SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
2139 size = cbBufSize;
2140 succ = MakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
2141 *pcbBytesNeeded = size;
2142 return succ;
2145 /******************************************************************************
2146 * SetServiceObjectSecurity [ADVAPI32.@]
2148 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
2149 SECURITY_INFORMATION dwSecurityInformation,
2150 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2152 FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
2153 return TRUE;
2156 /******************************************************************************
2157 * SetServiceBits [ADVAPI32.@]
2159 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2160 DWORD dwServiceBits,
2161 BOOL bSetBitsOn,
2162 BOOL bUpdateImmediately)
2164 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2165 bSetBitsOn, bUpdateImmediately);
2166 return TRUE;
2169 /* thunk for calling the RegisterServiceCtrlHandler handler function */
2170 static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, void *context )
2172 LPHANDLER_FUNCTION func = context;
2174 func( control );
2175 return ERROR_SUCCESS;
2178 /******************************************************************************
2179 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
2181 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler )
2183 return RegisterServiceCtrlHandlerExA( name, ctrl_handler_thunk, handler );
2186 /******************************************************************************
2187 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
2189 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler )
2191 return RegisterServiceCtrlHandlerExW( name, ctrl_handler_thunk, handler );
2194 /******************************************************************************
2195 * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
2197 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context )
2199 LPWSTR nameW;
2200 SERVICE_STATUS_HANDLE ret;
2202 nameW = SERV_dup(name);
2203 ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
2204 HeapFree( GetProcessHeap(), 0, nameW );
2205 return ret;
2208 /******************************************************************************
2209 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2211 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2212 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2214 SC_HANDLE hService;
2215 SC_HANDLE hSCM;
2216 unsigned int i;
2217 BOOL found = FALSE;
2219 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2221 hSCM = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT );
2222 if (!hSCM)
2223 return NULL;
2224 hService = OpenServiceW( hSCM, lpServiceName, SERVICE_SET_STATUS );
2225 CloseServiceHandle(hSCM);
2226 if (!hService)
2227 return NULL;
2229 EnterCriticalSection( &service_cs );
2230 for (i = 0; i < nb_services; i++)
2232 if(!strcmpW(lpServiceName, services[i]->name))
2234 services[i]->handler = lpHandlerProc;
2235 services[i]->context = lpContext;
2236 found = TRUE;
2237 break;
2240 LeaveCriticalSection( &service_cs );
2242 if (!found)
2244 CloseServiceHandle(hService);
2245 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
2246 return NULL;
2249 return (SERVICE_STATUS_HANDLE)hService;
2252 /******************************************************************************
2253 * EnumDependentServicesA [ADVAPI32.@]
2255 BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
2256 LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
2257 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2259 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2260 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2262 *lpServicesReturned = 0;
2263 return TRUE;
2266 /******************************************************************************
2267 * EnumDependentServicesW [ADVAPI32.@]
2269 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
2270 LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
2271 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2273 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2274 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2276 *lpServicesReturned = 0;
2277 return TRUE;