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
33 #include "wine/unicode.h"
34 #include "wine/debug.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',
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),
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),
76 typedef struct service_data_t
78 LPHANDLER_FUNCTION_EX handler;
83 LPSERVICE_MAIN_FUNCTIONA a;
84 LPSERVICE_MAIN_FUNCTIONW w;
90 static CRITICAL_SECTION service_cs;
91 static CRITICAL_SECTION_DEBUG service_cs_debug =
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 /******************************************************************************
110 #define MAX_SERVICE_NAME 256
112 typedef enum { SC_HTYPE_MANAGER, SC_HTYPE_SERVICE } SC_HANDLE_TYPE;
115 typedef VOID (*sc_handle_destructor)(struct sc_handle *);
119 SC_HANDLE_TYPE htype;
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 */
132 struct sc_service /* service handle */
134 struct sc_handle hdr;
135 HKEY hkey; /* handle to service entry in the registry (under hkey) */
137 struct sc_manager *scm; /* pointer to SCM handle */
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 );
151 hdr->destroy = destroy;
153 TRACE("sc_handle type=%d -> %p\n", htype, hdr);
157 static void *sc_handle_get_handle_data(SC_HANDLE handle, DWORD htype)
159 struct sc_handle *hdr = (struct sc_handle *) handle;
163 if (hdr->htype != htype)
168 static void sc_handle_free(struct sc_handle* hdr)
172 if (--hdr->ref_count)
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);
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);
193 RegCloseKey(svc->hkey);
195 sc_handle_free(&svc->scm->hdr);
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 )
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 );
217 static inline LPWSTR SERV_dupmulti(LPCSTR str)
225 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
226 n += (strlen( &str[n] ) + 1);
231 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
232 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
236 static inline DWORD multisz_cb(LPCWSTR wmultisz)
238 const WCHAR *wptr = wmultisz;
240 if (wmultisz == NULL)
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;
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);
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);
279 void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t 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;
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};
315 HKEY service_current_key;
316 DWORD service_current;
320 ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, service_current_key_str, 0,
321 KEY_QUERY_VALUE, &service_current_key);
322 if (ret != ERROR_SUCCESS)
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)
330 len = sizeof(format)/sizeof(WCHAR) + 10 /* strlenW("4294967295") */;
331 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
334 snprintfW(name, len, format, service_current);
338 static HANDLE service_open_pipe(void)
340 LPWSTR szPipe = service_get_pipe_name();
341 HANDLE handle = INVALID_HANDLE_VALUE;
344 handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE,
345 0, NULL, OPEN_ALWAYS, 0, NULL);
346 if (handle != INVALID_HANDLE_VALUE)
348 if (GetLastError() != ERROR_PIPE_BUSY)
350 } while (WaitNamedPipeW(szPipe, NMPWAIT_WAIT_FOREVER));
351 HeapFree(GetProcessHeap(), 0, szPipe);
356 /******************************************************************************
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;
371 len += strlenW(&str[len]) + 1;
378 info->proc.w(0, NULL);
380 info->proc.a(0, NULL);
388 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
389 for (argc=0, p=str; *p; p += strlenW(p) + 1)
393 info->proc.w(argc, argv);
394 HeapFree(GetProcessHeap(), 0, argv);
398 LPSTR strA, *argv, p;
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)
410 info->proc.a(argc, argv);
411 HeapFree(GetProcessHeap(), 0, argv);
412 HeapFree(GetProcessHeap(), 0, strA);
417 /******************************************************************************
418 * service_handle_start
420 static BOOL service_handle_start(HANDLE pipe, service_data *service, DWORD count)
422 DWORD read = 0, result = 0;
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));
439 WARN("service is not stopped\n");
440 result = ERROR_SERVICE_ALREADY_RUNNING;
444 HeapFree(GetProcessHeap(), 0, service->args);
445 service->args = args;
447 service->thread = CreateThread( NULL, 0, service_thread,
449 SetEvent( service_event ); /* notify the main loop */
452 HeapFree(GetProcessHeap(), 0, args);
453 WriteFile( pipe, &result, sizeof result, &read, NULL );
458 /******************************************************************************
459 * service_handle_control
461 static BOOL service_handle_control(HANDLE pipe, service_data *service,
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;
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());
492 /* dispatcher loop */
496 DWORD count, req[2] = {0,0};
498 r = ReadFile( pipe, &req, sizeof req, &count, NULL );
501 if (GetLastError() != ERROR_BROKEN_PIPE)
502 ERR( "pipe read failed error %u\n", GetLastError() );
505 if (count != sizeof(req))
507 ERR( "partial pipe read %u\n", count );
511 /* handle the request */
514 case WINESERV_STARTINFO:
515 service_handle_start(pipe, service, req[1]);
517 case WINESERV_SENDCONTROL:
518 service_handle_control(pipe, service, req[1]);
521 ERR("received invalid command %d length %d\n", req[0], req[1]);
529 /******************************************************************************
530 * service_run_threads
532 static BOOL service_run_threads(void)
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 */
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 */
572 continue; /* rebuild the list */
576 services[wait_services[ret]]->thread = 0;
577 CloseHandle( wait_handles[ret] );
578 if (n == 3) return TRUE; /* it was the last running thread */
584 /******************************************************************************
585 * StartServiceCtrlDispatcherA [ADVAPI32.@]
587 * See StartServiceCtrlDispatcherW.
589 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
595 TRACE("%p\n", servent);
599 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
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;
616 service_run_threads();
621 /******************************************************************************
622 * StartServiceCtrlDispatcherW [ADVAPI32.@]
624 * Connects a process containing one or more services to the service control
628 * servent [I] A list of the service names and service procedures
634 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
640 TRACE("%p\n", servent);
644 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
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;
661 service_run_threads();
666 /******************************************************************************
667 * LockServiceDatabase [ADVAPI32.@]
669 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
671 struct sc_manager *hscm;
672 SC_RPC_LOCK hLock = NULL;
675 TRACE("%p\n",hSCManager);
677 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
680 SetLastError( ERROR_INVALID_HANDLE );
686 err = svcctl_LockServiceDatabase(hscm->hdr.server_handle, &hLock);
690 err = map_exception_code(GetExceptionCode());
693 if (err != ERROR_SUCCESS)
701 /******************************************************************************
702 * UnlockServiceDatabase [ADVAPI32.@]
704 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
707 SC_RPC_LOCK hRpcLock = ScLock;
709 TRACE("%p\n",ScLock);
713 err = svcctl_UnlockServiceDatabase(&hRpcLock);
717 err = map_exception_code(GetExceptionCode());
720 if (err != ERROR_SUCCESS)
728 /******************************************************************************
729 * SetServiceStatus [ADVAPI32.@]
736 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
738 struct sc_service *hsvc;
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);
750 SetLastError( ERROR_INVALID_HANDLE );
756 err = svcctl_SetServiceStatus( hsvc->hdr.server_handle, lpStatus );
760 err = map_exception_code(GetExceptionCode());
763 if (err != ERROR_SUCCESS)
769 if (lpStatus->dwCurrentState == SERVICE_STOPPED)
770 CloseServiceHandle((SC_HANDLE)hService);
776 /******************************************************************************
777 * OpenSCManagerA [ADVAPI32.@]
779 * Establish a connection to the service control manager and open its database.
782 * lpMachineName [I] Pointer to machine name string
783 * lpDatabaseName [I] Pointer to database name string
784 * dwDesiredAccess [I] Type of access
787 * Success: A Handle to the service control manager database
790 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
791 DWORD dwDesiredAccess )
793 LPWSTR lpMachineNameW, lpDatabaseNameW;
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);
804 /******************************************************************************
805 * OpenSCManagerW [ADVAPI32.@]
807 * See OpenSCManagerA.
809 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
810 DWORD dwDesiredAccess )
812 struct sc_manager *manager;
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 );
827 r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, &manager->hdr.server_handle);
831 r = map_exception_code(GetExceptionCode());
834 if (r!=ERROR_SUCCESS)
837 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
838 if (r!=ERROR_SUCCESS)
841 r = RegCreateKeyW(hReg, szServiceManagerKey, &manager->hkey);
843 if (r!=ERROR_SUCCESS)
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;
853 sc_handle_free( &manager->hdr );
858 /******************************************************************************
859 * ControlService [ADVAPI32.@]
861 * Send a control code to a service.
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
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;
882 TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
884 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
887 SetLastError( ERROR_INVALID_HANDLE );
893 err = svcctl_ControlService(hsvc->hdr.server_handle, dwControl, lpServiceStatus);
897 err = map_exception_code(GetExceptionCode());
900 if (err != ERROR_SUCCESS)
909 /******************************************************************************
910 * CloseServiceHandle [ADVAPI32.@]
912 * Close a handle to a service or the service control manager database.
915 * hSCObject [I] Handle to service or service control manager database
922 CloseServiceHandle( SC_HANDLE hSCObject )
924 struct sc_handle *obj;
927 TRACE("%p\n", hSCObject);
928 if (hSCObject == NULL)
930 SetLastError(ERROR_INVALID_HANDLE);
934 obj = (struct sc_handle *)hSCObject;
937 err = svcctl_CloseServiceHandle(&obj->server_handle);
941 err = map_exception_code(GetExceptionCode());
944 sc_handle_free( obj );
946 if (err != ERROR_SUCCESS)
955 /******************************************************************************
956 * OpenServiceA [ADVAPI32.@]
958 * Open a handle to a service.
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
966 * Success: Handle to the service
969 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
970 DWORD dwDesiredAccess )
972 LPWSTR lpServiceNameW;
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);
984 /******************************************************************************
985 * OpenServiceW [ADVAPI32.@]
989 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
990 DWORD dwDesiredAccess)
992 struct sc_manager *hscm;
993 struct sc_service *hsvc;
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 );
1003 SetLastError( ERROR_INVALID_HANDLE );
1009 SetLastError(ERROR_INVALID_ADDRESS);
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 );
1019 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1022 strcpyW( hsvc->name, lpServiceName );
1024 /* add reference to SCM handle */
1025 hscm->hdr.ref_count++;
1030 err = svcctl_OpenServiceW(hscm->hdr.server_handle, lpServiceName, dwDesiredAccess, &hsvc->hdr.server_handle);
1032 __EXCEPT(rpc_filter)
1034 err = map_exception_code(GetExceptionCode());
1038 if (err != ERROR_SUCCESS)
1040 sc_handle_free(&hsvc->hdr);
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.@]
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;
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 );
1082 SetLastError( ERROR_INVALID_HANDLE );
1086 if (!lpServiceName || !lpBinaryPathName)
1088 SetLastError(ERROR_INVALID_ADDRESS);
1093 passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
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 );
1102 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1105 lstrcpyW( hsvc->name, lpServiceName );
1108 hscm->hdr.ref_count++;
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());
1124 if (err != ERROR_SUCCESS)
1127 sc_handle_free(&hsvc->hdr);
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.@]
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,
1155 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
1156 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
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 );
1187 /******************************************************************************
1188 * DeleteService [ADVAPI32.@]
1190 * Delete a service from the service control manager database.
1193 * hService [I] Handle of the service to delete
1199 BOOL WINAPI DeleteService( SC_HANDLE hService )
1201 struct sc_service *hsvc;
1204 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1207 SetLastError( ERROR_INVALID_HANDLE );
1213 err = svcctl_DeleteService(hsvc->hdr.server_handle);
1215 __EXCEPT(rpc_filter)
1217 err = map_exception_code(GetExceptionCode());
1226 /* Close the key to the service */
1227 RegCloseKey(hsvc->hkey);
1233 /******************************************************************************
1234 * StartServiceA [ADVAPI32.@]
1239 * hService [I] Handle of service
1240 * dwNumServiceArgs [I] Number of arguments
1241 * lpServiceArgVectors [I] Address of array of argument strings
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.
1256 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1257 LPCSTR *lpServiceArgVectors )
1259 LPWSTR *lpwstr=NULL;
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);
1285 /******************************************************************************
1286 * StartServiceW [ADVAPI32.@]
1288 * See StartServiceA.
1290 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1291 LPCWSTR *lpServiceArgVectors)
1293 struct sc_service *hsvc;
1296 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1298 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1301 SetLastError(ERROR_INVALID_HANDLE);
1307 err = svcctl_StartServiceW(hsvc->hdr.server_handle, dwNumServiceArgs, lpServiceArgVectors);
1309 __EXCEPT(rpc_filter)
1311 err = map_exception_code(GetExceptionCode());
1314 if (err != ERROR_SUCCESS)
1323 /******************************************************************************
1324 * QueryServiceStatus [ADVAPI32.@]
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;
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)) ;
1347 /******************************************************************************
1348 * QueryServiceStatusEx [ADVAPI32.@]
1350 * Get information about a service.
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
1363 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1364 LPBYTE lpBuffer, DWORD cbBufSize,
1365 LPDWORD pcbBytesNeeded)
1367 struct sc_service *hsvc;
1370 TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1372 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1375 SetLastError( ERROR_INVALID_HANDLE );
1381 err = svcctl_QueryServiceStatusEx(hsvc->hdr.server_handle, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1383 __EXCEPT(rpc_filter)
1385 err = map_exception_code(GetExceptionCode());
1388 if (err != ERROR_SUCCESS)
1397 /******************************************************************************
1398 * QueryServiceConfigA [ADVAPI32.@]
1400 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1401 DWORD size, LPDWORD needed )
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 );
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);
1433 #define MAP_STR(str) \
1437 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1438 if (!sz) goto done; \
1445 MAP_STR( lpBinaryPathName );
1446 MAP_STR( lpLoadOrderGroup );
1447 MAP_STR( lpDependencies );
1448 MAP_STR( lpServiceStartName );
1449 MAP_STR( lpDisplayName );
1452 *needed = p - (LPSTR)config;
1456 HeapFree( GetProcessHeap(), 0, buffer );
1460 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1467 memset(*buf, 0, cb);
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;
1482 static DWORD size_string(LPWSTR string)
1484 return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1487 /******************************************************************************
1488 * QueryServiceConfigW [ADVAPI32.@]
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;
1501 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1502 cbBufSize, pcbBytesNeeded);
1504 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1507 SetLastError( ERROR_INVALID_HANDLE );
1511 memset(&config, 0, sizeof(config));
1515 err = svcctl_QueryServiceConfigW(hsvc->hdr.server_handle, &config);
1517 __EXCEPT(rpc_filter)
1519 err = map_exception_code(GetExceptionCode());
1523 if (err != ERROR_SUCCESS)
1525 TRACE("services.exe: error %u\n", err);
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);
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) );
1572 /******************************************************************************
1573 * QueryServiceConfig2A [ADVAPI32.@]
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)
1584 LPBYTE bufferW = NULL;
1587 bufferW = HeapAlloc( GetProcessHeap(), 0, size);
1589 ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1590 if(!ret) goto cleanup;
1593 case SERVICE_CONFIG_DESCRIPTION:
1594 { LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1595 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1596 if (configW->lpDescription) {
1598 configA->lpDescription = (LPSTR)(configA + 1);
1599 sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1600 configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1602 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1604 configA->lpDescription = NULL;
1607 else configA->lpDescription = NULL;
1611 FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1616 HeapFree( GetProcessHeap(), 0, bufferW);
1620 /******************************************************************************
1621 * QueryServiceConfig2W [ADVAPI32.@]
1623 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1624 DWORD size, LPDWORD needed)
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);
1642 if(!needed || (!buffer && size)) {
1643 SetLastError(ERROR_INVALID_ADDRESS);
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);
1652 SetLastError(ERROR_INVALID_HANDLE);
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);
1673 if(r == ERROR_SUCCESS)
1674 config->lpDescription = (LPWSTR) (config + 1);
1676 config->lpDescription = NULL;
1682 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1684 return (*needed <= size);
1687 /******************************************************************************
1688 * EnumServicesStatusA [ADVAPI32.@]
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);
1703 /******************************************************************************
1704 * EnumServicesStatusW [ADVAPI32.@]
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);
1719 /******************************************************************************
1720 * EnumServicesStatusExA [ADVAPI32.@]
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);
1735 /******************************************************************************
1736 * EnumServicesStatusExW [ADVAPI32.@]
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);
1750 /******************************************************************************
1751 * GetServiceKeyNameA [ADVAPI32.@]
1753 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1754 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1756 LPWSTR lpDisplayNameW, lpServiceNameW;
1760 TRACE("%p %s %p %p\n", hSCManager,
1761 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1763 lpDisplayNameW = SERV_dup(lpDisplayName);
1765 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
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 */
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);
1787 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1791 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1792 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1796 /******************************************************************************
1797 * GetServiceKeyNameW [ADVAPI32.@]
1799 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1800 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1802 struct sc_manager *hscm;
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);
1811 SetLastError(ERROR_INVALID_HANDLE);
1817 SetLastError(ERROR_INVALID_ADDRESS);
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());
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);
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);
1861 /******************************************************************************
1862 * GetServiceDisplayNameA [ADVAPI32.@]
1864 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1865 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1867 LPWSTR lpServiceNameW, lpDisplayNameW;
1871 TRACE("%p %s %p %p\n", hSCManager,
1872 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1874 lpServiceNameW = SERV_dup(lpServiceName);
1876 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
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 */
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);
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) */
1903 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1904 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1908 /******************************************************************************
1909 * GetServiceDisplayNameW [ADVAPI32.@]
1911 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1912 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1914 struct sc_manager *hscm;
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);
1923 SetLastError(ERROR_INVALID_HANDLE);
1929 SetLastError(ERROR_INVALID_ADDRESS);
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());
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;
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);
1970 SetLastError( ERROR_INVALID_HANDLE );
1974 cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
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());
1989 if (err != ERROR_SUCCESS)
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;
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 );
2035 /******************************************************************************
2036 * ChangeServiceConfig2A [ADVAPI32.@]
2038 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
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 );
2073 SetLastError( ERROR_INVALID_PARAMETER );
2078 /******************************************************************************
2079 * ChangeServiceConfig2W [ADVAPI32.@]
2081 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
2085 struct sc_service *hsvc;
2087 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
2090 SetLastError( ERROR_INVALID_HANDLE );
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);
2105 RegSetValueExW(hKey, szDescription, 0, REG_SZ,
2106 (LPVOID)sd->lpDescription,
2107 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
2111 FIXME("STUB: %p %d %p\n",hService, dwInfoLevel, lpInfo);
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;
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);
2140 succ = MakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
2141 *pcbBytesNeeded = size;
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);
2156 /******************************************************************************
2157 * SetServiceBits [ADVAPI32.@]
2159 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2160 DWORD dwServiceBits,
2162 BOOL bUpdateImmediately)
2164 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2165 bSetBitsOn, bUpdateImmediately);
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;
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 )
2200 SERVICE_STATUS_HANDLE ret;
2202 nameW = SERV_dup(name);
2203 ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
2204 HeapFree( GetProcessHeap(), 0, nameW );
2208 /******************************************************************************
2209 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2211 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2212 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2219 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2221 hSCM = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT );
2224 hService = OpenServiceW( hSCM, lpServiceName, SERVICE_SET_STATUS );
2225 CloseServiceHandle(hSCM);
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;
2240 LeaveCriticalSection( &service_cs );
2244 CloseServiceHandle(hService);
2245 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
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;
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;