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
24 #include "wine/port.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
44 #include "wine/exception.h"
46 WINE_DEFAULT_DEBUG_CHANNEL(service);
48 static const WCHAR szLocalSystem[] = {'L','o','c','a','l','S','y','s','t','e','m',0};
49 static const WCHAR szServiceManagerKey[] = { 'S','y','s','t','e','m','\\',
50 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
51 'S','e','r','v','i','c','e','s',0 };
52 static const WCHAR szSCMLock[] = {'A','D','V','A','P','I','_','S','C','M',
55 void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t len)
57 return HeapAlloc(GetProcessHeap(), 0, len);
60 void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
62 HeapFree(GetProcessHeap(), 0, ptr);
65 static const GENERIC_MAPPING scm_generic = {
66 (STANDARD_RIGHTS_READ | SC_MANAGER_ENUMERATE_SERVICE | SC_MANAGER_QUERY_LOCK_STATUS),
67 (STANDARD_RIGHTS_WRITE | SC_MANAGER_CREATE_SERVICE | SC_MANAGER_MODIFY_BOOT_CONFIG),
68 (STANDARD_RIGHTS_EXECUTE | SC_MANAGER_CONNECT | SC_MANAGER_LOCK),
72 static const GENERIC_MAPPING svc_generic = {
73 (STANDARD_RIGHTS_READ | SERVICE_QUERY_CONFIG | SERVICE_QUERY_STATUS | SERVICE_INTERROGATE | SERVICE_ENUMERATE_DEPENDENTS),
74 (STANDARD_RIGHTS_WRITE | SERVICE_CHANGE_CONFIG),
75 (STANDARD_RIGHTS_EXECUTE | SERVICE_START | SERVICE_STOP | SERVICE_PAUSE_CONTINUE | SERVICE_USER_DEFINED_CONTROL),
79 typedef struct service_data_t
81 LPHANDLER_FUNCTION_EX handler;
86 LPSERVICE_MAIN_FUNCTIONA a;
87 LPSERVICE_MAIN_FUNCTIONW w;
93 static CRITICAL_SECTION service_cs;
94 static CRITICAL_SECTION_DEBUG service_cs_debug =
97 { &service_cs_debug.ProcessLocksList,
98 &service_cs_debug.ProcessLocksList },
99 0, 0, { (DWORD_PTR)(__FILE__ ": service_cs") }
101 static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 };
103 static service_data **services;
104 static unsigned int nb_services;
105 static HANDLE service_event;
107 extern HANDLE __wine_make_process_system(void);
109 /******************************************************************************
113 #define MAX_SERVICE_NAME 256
115 typedef enum { SC_HTYPE_MANAGER, SC_HTYPE_SERVICE } SC_HANDLE_TYPE;
118 typedef VOID (*sc_handle_destructor)(struct sc_handle *);
122 SC_HANDLE_TYPE htype;
124 sc_handle_destructor destroy;
125 SC_RPC_HANDLE server_handle; /* server-side handle */
128 struct sc_manager /* service control manager handle */
130 struct sc_handle hdr;
131 HKEY hkey; /* handle to services database in the registry */
135 struct sc_service /* service handle */
137 struct sc_handle hdr;
138 HKEY hkey; /* handle to service entry in the registry (under hkey) */
140 struct sc_manager *scm; /* pointer to SCM handle */
144 static void *sc_handle_alloc(SC_HANDLE_TYPE htype, DWORD size,
145 sc_handle_destructor destroy)
147 struct sc_handle *hdr;
149 hdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
154 hdr->destroy = destroy;
156 TRACE("sc_handle type=%d -> %p\n", htype, hdr);
160 static void *sc_handle_get_handle_data(SC_HANDLE handle, DWORD htype)
162 struct sc_handle *hdr = (struct sc_handle *) handle;
166 if (hdr->htype != htype)
171 static void sc_handle_free(struct sc_handle* hdr)
175 if (--hdr->ref_count)
178 HeapFree(GetProcessHeap(), 0, hdr);
181 static void sc_handle_destroy_manager(struct sc_handle *handle)
183 struct sc_manager *mgr = (struct sc_manager*) handle;
185 TRACE("destroying SC Manager %p\n", mgr);
187 RegCloseKey(mgr->hkey);
190 static void sc_handle_destroy_service(struct sc_handle *handle)
192 struct sc_service *svc = (struct sc_service*) handle;
194 TRACE("destroying service %p\n", svc);
196 RegCloseKey(svc->hkey);
198 sc_handle_free(&svc->scm->hdr);
202 /******************************************************************************
203 * String management functions (same behaviour as strdup)
204 * NOTE: the caller of those functions is responsible for calling HeapFree
205 * in order to release the memory allocated by those functions.
207 static inline LPWSTR SERV_dup( LPCSTR str )
214 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
215 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
216 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
220 static inline LPWSTR SERV_dupmulti(LPCSTR str)
228 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
229 n += (strlen( &str[n] ) + 1);
234 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
235 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
239 static inline DWORD multisz_cb(LPCWSTR wmultisz)
241 const WCHAR *wptr = wmultisz;
243 if (wmultisz == NULL)
247 wptr += lstrlenW(wptr)+1;
248 return (wptr - wmultisz + 1)*sizeof(WCHAR);
251 /******************************************************************************
252 * RPC connection with services.exe
255 handle_t __RPC_USER MACHINE_HANDLEW_bind(MACHINE_HANDLEW MachineName)
257 WCHAR transport[] = SVCCTL_TRANSPORT;
258 WCHAR endpoint[] = SVCCTL_ENDPOINT;
259 RPC_WSTR binding_str;
263 status = RpcStringBindingComposeW(NULL, transport, (RPC_WSTR)MachineName, endpoint, NULL, &binding_str);
264 if (status != RPC_S_OK)
266 ERR("RpcStringBindingComposeW failed (%d)\n", (DWORD)status);
270 status = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
271 RpcStringFreeW(&binding_str);
273 if (status != RPC_S_OK)
275 ERR("Couldn't connect to services.exe: error code %u\n", (DWORD)status);
282 void __RPC_USER MACHINE_HANDLEW_unbind(MACHINE_HANDLEW MachineName, handle_t h)
287 static LONG WINAPI rpc_filter(EXCEPTION_POINTERS *eptr)
289 return I_RpcExceptionFilter(eptr->ExceptionRecord->ExceptionCode);
292 static DWORD map_exception_code(DWORD exception_code)
294 switch (exception_code)
296 case RPC_X_NULL_REF_POINTER:
297 case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
298 case RPC_X_BYTE_COUNT_TOO_SMALL:
299 return ERROR_INVALID_PARAMETER;
301 return exception_code;
305 /******************************************************************************
306 * Service IPC functions
308 static LPWSTR service_get_pipe_name(void)
310 static const WCHAR format[] = { '\\','\\','.','\\','p','i','p','e','\\',
311 'n','e','t','\\','N','t','C','o','n','t','r','o','l','P','i','p','e','%','u',0};
312 static const WCHAR service_current_key_str[] = { 'S','Y','S','T','E','M','\\',
313 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
314 'C','o','n','t','r','o','l','\\',
315 'S','e','r','v','i','c','e','C','u','r','r','e','n','t',0};
318 HKEY service_current_key;
319 DWORD service_current;
323 ret = RegOpenKeyExW(HKEY_LOCAL_MACHINE, service_current_key_str, 0,
324 KEY_QUERY_VALUE, &service_current_key);
325 if (ret != ERROR_SUCCESS)
327 len = sizeof(service_current);
328 ret = RegQueryValueExW(service_current_key, NULL, NULL, &type,
329 (BYTE *)&service_current, &len);
330 RegCloseKey(service_current_key);
331 if (ret != ERROR_SUCCESS || type != REG_DWORD)
333 len = sizeof(format)/sizeof(WCHAR) + 10 /* strlenW("4294967295") */;
334 name = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
337 snprintfW(name, len, format, service_current);
341 static HANDLE service_open_pipe(void)
343 LPWSTR szPipe = service_get_pipe_name();
344 HANDLE handle = INVALID_HANDLE_VALUE;
347 handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE,
348 0, NULL, OPEN_ALWAYS, 0, NULL);
349 if (handle != INVALID_HANDLE_VALUE)
351 if (GetLastError() != ERROR_PIPE_BUSY)
353 } while (WaitNamedPipeW(szPipe, NMPWAIT_WAIT_FOREVER));
354 HeapFree(GetProcessHeap(), 0, szPipe);
359 /******************************************************************************
362 * Call into the main service routine provided by StartServiceCtrlDispatcher.
364 static DWORD WINAPI service_thread(LPVOID arg)
366 service_data *info = arg;
367 LPWSTR str = info->args;
368 DWORD argc = 0, len = 0;
374 len += strlenW(&str[len]) + 1;
381 info->proc.w(0, NULL);
383 info->proc.a(0, NULL);
391 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
392 for (argc=0, p=str; *p; p += strlenW(p) + 1)
396 info->proc.w(argc, argv);
397 HeapFree(GetProcessHeap(), 0, argv);
401 LPSTR strA, *argv, p;
404 lenA = WideCharToMultiByte(CP_ACP,0, str, len, NULL, 0, NULL, NULL);
405 strA = HeapAlloc(GetProcessHeap(), 0, lenA);
406 WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
408 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPSTR));
409 for (argc=0, p=strA; *p; p += strlen(p) + 1)
413 info->proc.a(argc, argv);
414 HeapFree(GetProcessHeap(), 0, argv);
415 HeapFree(GetProcessHeap(), 0, strA);
420 /******************************************************************************
421 * service_handle_start
423 static BOOL service_handle_start(HANDLE pipe, service_data *service, DWORD count)
425 DWORD read = 0, result = 0;
429 TRACE("%p %p %d\n", pipe, service, count);
431 args = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
432 r = ReadFile(pipe, args, count*sizeof(WCHAR), &read, NULL);
433 if (!r || count!=read/sizeof(WCHAR) || args[count-1])
435 ERR("pipe read failed r = %d count = %d read = %d args[n-1]=%s\n",
436 r, count, read, debugstr_wn(args, count));
442 WARN("service is not stopped\n");
443 result = ERROR_SERVICE_ALREADY_RUNNING;
447 HeapFree(GetProcessHeap(), 0, service->args);
448 service->args = args;
450 service->thread = CreateThread( NULL, 0, service_thread,
452 SetEvent( service_event ); /* notify the main loop */
455 HeapFree(GetProcessHeap(), 0, args);
456 WriteFile( pipe, &result, sizeof result, &read, NULL );
461 /******************************************************************************
462 * service_handle_control
464 static BOOL service_handle_control(HANDLE pipe, service_data *service,
467 DWORD count, ret = ERROR_INVALID_SERVICE_CONTROL;
469 TRACE("received control %d\n", dwControl);
471 if (service->handler)
472 ret = service->handler(dwControl, 0, NULL, service->context);
473 return WriteFile(pipe, &ret, sizeof ret, &count, NULL);
476 /******************************************************************************
477 * service_control_dispatcher
479 static DWORD WINAPI service_control_dispatcher(LPVOID arg)
481 service_data *service = arg;
484 TRACE("%p %s\n", service, debugstr_w(service->name));
486 pipe = service_open_pipe();
488 if (pipe==INVALID_HANDLE_VALUE)
490 ERR("failed to create pipe for %s, error = %d\n",
491 debugstr_w(service->name), GetLastError());
495 /* dispatcher loop */
499 DWORD count, req[2] = {0,0};
501 r = ReadFile( pipe, &req, sizeof req, &count, NULL );
504 if (GetLastError() != ERROR_BROKEN_PIPE)
505 ERR( "pipe read failed error %u\n", GetLastError() );
508 if (count != sizeof(req))
510 ERR( "partial pipe read %u\n", count );
514 /* handle the request */
517 case WINESERV_STARTINFO:
518 service_handle_start(pipe, service, req[1]);
520 case WINESERV_SENDCONTROL:
521 service_handle_control(pipe, service, req[1]);
524 ERR("received invalid command %d length %d\n", req[0], req[1]);
532 /******************************************************************************
533 * service_run_threads
535 static BOOL service_run_threads(void)
538 HANDLE wait_handles[MAXIMUM_WAIT_OBJECTS];
539 UINT wait_services[MAXIMUM_WAIT_OBJECTS];
541 service_event = CreateEventW( NULL, FALSE, FALSE, NULL );
543 wait_handles[0] = __wine_make_process_system();
544 wait_handles[1] = service_event;
546 TRACE("Starting %d pipe listener threads. Services running as process %d\n",
547 nb_services, GetCurrentProcessId());
549 EnterCriticalSection( &service_cs );
550 for (i = 0; i < nb_services; i++)
551 CloseHandle( CreateThread( NULL, 0, service_control_dispatcher, services[i], 0, NULL ));
552 LeaveCriticalSection( &service_cs );
554 /* wait for all the threads to pack up and exit */
557 EnterCriticalSection( &service_cs );
558 for (i = 0, n = 2; i < nb_services && n < MAXIMUM_WAIT_OBJECTS; i++)
560 if (!services[i]->thread) continue;
561 wait_services[n] = i;
562 wait_handles[n++] = services[i]->thread;
564 LeaveCriticalSection( &service_cs );
566 ret = WaitForMultipleObjects( n, wait_handles, FALSE, INFINITE );
567 if (!ret) /* system process event */
569 TRACE( "last user process exited, shutting down\n" );
570 /* FIXME: we should maybe send a shutdown control to running services */
575 continue; /* rebuild the list */
579 services[wait_services[ret]]->thread = 0;
580 CloseHandle( wait_handles[ret] );
581 if (n == 3) return TRUE; /* it was the last running thread */
587 /******************************************************************************
588 * StartServiceCtrlDispatcherA [ADVAPI32.@]
590 * See StartServiceCtrlDispatcherW.
592 BOOL WINAPI StartServiceCtrlDispatcherA( const SERVICE_TABLE_ENTRYA *servent )
598 TRACE("%p\n", servent);
602 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
605 while (servent[nb_services].lpServiceName) nb_services++;
606 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
608 for (i = 0; i < nb_services; i++)
610 DWORD len = MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, NULL, 0);
611 DWORD sz = FIELD_OFFSET( service_data, name[len] );
612 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
613 MultiByteToWideChar(CP_ACP, 0, servent[i].lpServiceName, -1, info->name, len);
614 info->proc.a = servent[i].lpServiceProc;
615 info->unicode = FALSE;
619 service_run_threads();
624 /******************************************************************************
625 * StartServiceCtrlDispatcherW [ADVAPI32.@]
627 * Connects a process containing one or more services to the service control
631 * servent [I] A list of the service names and service procedures
637 BOOL WINAPI StartServiceCtrlDispatcherW( const SERVICE_TABLE_ENTRYW *servent )
643 TRACE("%p\n", servent);
647 SetLastError( ERROR_SERVICE_ALREADY_RUNNING );
650 while (servent[nb_services].lpServiceName) nb_services++;
651 services = HeapAlloc( GetProcessHeap(), 0, nb_services * sizeof(*services) );
653 for (i = 0; i < nb_services; i++)
655 DWORD len = strlenW(servent[i].lpServiceName) + 1;
656 DWORD sz = FIELD_OFFSET( service_data, name[len] );
657 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
658 strcpyW(info->name, servent[i].lpServiceName);
659 info->proc.w = servent[i].lpServiceProc;
660 info->unicode = TRUE;
664 service_run_threads();
669 /******************************************************************************
670 * LockServiceDatabase [ADVAPI32.@]
672 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
674 struct sc_manager *hscm;
675 SC_RPC_LOCK hLock = NULL;
678 TRACE("%p\n",hSCManager);
680 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
683 SetLastError( ERROR_INVALID_HANDLE );
689 err = svcctl_LockServiceDatabase(hscm->hdr.server_handle, &hLock);
693 err = map_exception_code(GetExceptionCode());
696 if (err != ERROR_SUCCESS)
704 /******************************************************************************
705 * UnlockServiceDatabase [ADVAPI32.@]
707 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
710 SC_RPC_LOCK hRpcLock = ScLock;
712 TRACE("%p\n",ScLock);
716 err = svcctl_UnlockServiceDatabase(&hRpcLock);
720 err = map_exception_code(GetExceptionCode());
723 if (err != ERROR_SUCCESS)
731 /******************************************************************************
732 * SetServiceStatus [ADVAPI32.@]
739 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
741 struct sc_service *hsvc;
744 TRACE("%p %x %x %x %x %x %x %x\n", hService,
745 lpStatus->dwServiceType, lpStatus->dwCurrentState,
746 lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode,
747 lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint,
748 lpStatus->dwWaitHint);
750 hsvc = sc_handle_get_handle_data((SC_HANDLE)hService, SC_HTYPE_SERVICE);
753 SetLastError( ERROR_INVALID_HANDLE );
759 err = svcctl_SetServiceStatus( hsvc->hdr.server_handle, lpStatus );
763 err = map_exception_code(GetExceptionCode());
766 if (err != ERROR_SUCCESS)
772 if (lpStatus->dwCurrentState == SERVICE_STOPPED)
773 CloseServiceHandle((SC_HANDLE)hService);
779 /******************************************************************************
780 * OpenSCManagerA [ADVAPI32.@]
782 * Establish a connection to the service control manager and open its database.
785 * lpMachineName [I] Pointer to machine name string
786 * lpDatabaseName [I] Pointer to database name string
787 * dwDesiredAccess [I] Type of access
790 * Success: A Handle to the service control manager database
793 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
794 DWORD dwDesiredAccess )
796 LPWSTR lpMachineNameW, lpDatabaseNameW;
799 lpMachineNameW = SERV_dup(lpMachineName);
800 lpDatabaseNameW = SERV_dup(lpDatabaseName);
801 ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess);
802 HeapFree(GetProcessHeap(), 0, lpDatabaseNameW);
803 HeapFree(GetProcessHeap(), 0, lpMachineNameW);
807 /******************************************************************************
808 * OpenSCManagerW [ADVAPI32.@]
810 * See OpenSCManagerA.
812 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
813 DWORD dwDesiredAccess )
815 struct sc_manager *manager;
818 DWORD new_mask = dwDesiredAccess;
820 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
821 debugstr_w(lpDatabaseName), dwDesiredAccess);
823 manager = sc_handle_alloc( SC_HTYPE_MANAGER, sizeof (struct sc_manager),
824 sc_handle_destroy_manager );
830 r = svcctl_OpenSCManagerW(lpMachineName, lpDatabaseName, dwDesiredAccess, &manager->hdr.server_handle);
834 r = map_exception_code(GetExceptionCode());
837 if (r!=ERROR_SUCCESS)
840 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
841 if (r!=ERROR_SUCCESS)
844 r = RegCreateKeyW(hReg, szServiceManagerKey, &manager->hkey);
846 if (r!=ERROR_SUCCESS)
849 RtlMapGenericMask(&new_mask, &scm_generic);
850 manager->dwAccess = new_mask;
851 TRACE("returning %p (access : 0x%08x)\n", manager, manager->dwAccess);
853 return (SC_HANDLE) &manager->hdr;
856 sc_handle_free( &manager->hdr );
861 /******************************************************************************
862 * ControlService [ADVAPI32.@]
864 * Send a control code to a service.
867 * hService [I] Handle of the service control manager database
868 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
869 * lpServiceStatus [O] Destination for the status of the service, if available
876 * Unlike M$' implementation, control requests are not serialized and may be
877 * processed asynchronously.
879 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
880 LPSERVICE_STATUS lpServiceStatus )
882 struct sc_service *hsvc;
885 TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
887 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
890 SetLastError( ERROR_INVALID_HANDLE );
896 err = svcctl_ControlService(hsvc->hdr.server_handle, dwControl, lpServiceStatus);
900 err = map_exception_code(GetExceptionCode());
903 if (err != ERROR_SUCCESS)
912 /******************************************************************************
913 * CloseServiceHandle [ADVAPI32.@]
915 * Close a handle to a service or the service control manager database.
918 * hSCObject [I] Handle to service or service control manager database
925 CloseServiceHandle( SC_HANDLE hSCObject )
927 struct sc_handle *obj;
930 TRACE("%p\n", hSCObject);
931 if (hSCObject == NULL)
933 SetLastError(ERROR_INVALID_HANDLE);
937 obj = (struct sc_handle *)hSCObject;
940 err = svcctl_CloseServiceHandle(&obj->server_handle);
944 err = map_exception_code(GetExceptionCode());
947 sc_handle_free( obj );
949 if (err != ERROR_SUCCESS)
958 /******************************************************************************
959 * OpenServiceA [ADVAPI32.@]
961 * Open a handle to a service.
964 * hSCManager [I] Handle of the service control manager database
965 * lpServiceName [I] Name of the service to open
966 * dwDesiredAccess [I] Access required to the service
969 * Success: Handle to the service
972 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
973 DWORD dwDesiredAccess )
975 LPWSTR lpServiceNameW;
978 TRACE("%p %s %d\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
980 lpServiceNameW = SERV_dup(lpServiceName);
981 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
982 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
987 /******************************************************************************
988 * OpenServiceW [ADVAPI32.@]
992 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
993 DWORD dwDesiredAccess)
995 struct sc_manager *hscm;
996 struct sc_service *hsvc;
999 DWORD new_mask = dwDesiredAccess;
1001 TRACE("%p %s %d\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
1003 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
1006 SetLastError( ERROR_INVALID_HANDLE );
1012 SetLastError(ERROR_INVALID_ADDRESS);
1016 len = strlenW(lpServiceName)+1;
1017 hsvc = sc_handle_alloc( SC_HTYPE_SERVICE,
1018 sizeof (struct sc_service) + len*sizeof(WCHAR),
1019 sc_handle_destroy_service );
1022 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1025 strcpyW( hsvc->name, lpServiceName );
1027 /* add reference to SCM handle */
1028 hscm->hdr.ref_count++;
1033 err = svcctl_OpenServiceW(hscm->hdr.server_handle, lpServiceName, dwDesiredAccess, &hsvc->hdr.server_handle);
1035 __EXCEPT(rpc_filter)
1037 err = map_exception_code(GetExceptionCode());
1041 if (err != ERROR_SUCCESS)
1043 sc_handle_free(&hsvc->hdr);
1048 /* for parts of advapi32 not using services.exe yet */
1049 RtlMapGenericMask(&new_mask, &svc_generic);
1050 hsvc->dwAccess = new_mask;
1052 err = RegOpenKeyExW( hscm->hkey, lpServiceName, 0, KEY_ALL_ACCESS, &hsvc->hkey );
1053 if (err != ERROR_SUCCESS)
1054 ERR("Shouldn't hapen - service key for service validated by services.exe doesn't exist\n");
1056 TRACE("returning %p\n",hsvc);
1058 return (SC_HANDLE) &hsvc->hdr;
1061 /******************************************************************************
1062 * CreateServiceW [ADVAPI32.@]
1065 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1066 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
1067 DWORD dwServiceType, DWORD dwStartType,
1068 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1069 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1070 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
1071 LPCWSTR lpPassword )
1073 struct sc_manager *hscm;
1074 struct sc_service *hsvc = NULL;
1075 DWORD new_mask = dwDesiredAccess;
1079 TRACE("%p %s %s\n", hSCManager,
1080 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
1082 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
1085 SetLastError( ERROR_INVALID_HANDLE );
1089 if (!lpServiceName || !lpBinaryPathName)
1091 SetLastError(ERROR_INVALID_ADDRESS);
1096 passwdlen = (strlenW(lpPassword) + 1) * sizeof(WCHAR);
1100 len = strlenW(lpServiceName)+1;
1101 len = sizeof (struct sc_service) + len*sizeof(WCHAR);
1102 hsvc = sc_handle_alloc( SC_HTYPE_SERVICE, len, sc_handle_destroy_service );
1105 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1108 lstrcpyW( hsvc->name, lpServiceName );
1111 hscm->hdr.ref_count++;
1115 err = svcctl_CreateServiceW(hscm->hdr.server_handle, lpServiceName,
1116 lpDisplayName, dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1117 lpBinaryPathName, lpLoadOrderGroup, lpdwTagId, (LPBYTE)lpDependencies,
1118 multisz_cb(lpDependencies), lpServiceStartName, (LPBYTE)lpPassword, passwdlen,
1119 &hsvc->hdr.server_handle);
1121 __EXCEPT(rpc_filter)
1123 err = map_exception_code(GetExceptionCode());
1127 if (err != ERROR_SUCCESS)
1130 sc_handle_free(&hsvc->hdr);
1134 /* for parts of advapi32 not using services.exe yet */
1135 err = RegOpenKeyW(hscm->hkey, lpServiceName, &hsvc->hkey);
1136 if (err != ERROR_SUCCESS)
1137 WINE_ERR("Couldn't open key that should have been created by services.exe\n");
1139 RtlMapGenericMask(&new_mask, &svc_generic);
1140 hsvc->dwAccess = new_mask;
1142 return (SC_HANDLE) &hsvc->hdr;
1146 /******************************************************************************
1147 * CreateServiceA [ADVAPI32.@]
1150 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1151 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
1152 DWORD dwServiceType, DWORD dwStartType,
1153 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1154 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1155 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
1158 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
1159 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
1162 TRACE("%p %s %s\n", hSCManager,
1163 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
1165 lpServiceNameW = SERV_dup( lpServiceName );
1166 lpDisplayNameW = SERV_dup( lpDisplayName );
1167 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
1168 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
1169 lpDependenciesW = SERV_dupmulti( lpDependencies );
1170 lpServiceStartNameW = SERV_dup( lpServiceStartName );
1171 lpPasswordW = SERV_dup( lpPassword );
1173 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
1174 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1175 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
1176 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
1178 HeapFree( GetProcessHeap(), 0, lpServiceNameW );
1179 HeapFree( GetProcessHeap(), 0, lpDisplayNameW );
1180 HeapFree( GetProcessHeap(), 0, lpBinaryPathNameW );
1181 HeapFree( GetProcessHeap(), 0, lpLoadOrderGroupW );
1182 HeapFree( GetProcessHeap(), 0, lpDependenciesW );
1183 HeapFree( GetProcessHeap(), 0, lpServiceStartNameW );
1184 HeapFree( GetProcessHeap(), 0, lpPasswordW );
1190 /******************************************************************************
1191 * DeleteService [ADVAPI32.@]
1193 * Delete a service from the service control manager database.
1196 * hService [I] Handle of the service to delete
1202 BOOL WINAPI DeleteService( SC_HANDLE hService )
1204 struct sc_service *hsvc;
1207 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1210 SetLastError( ERROR_INVALID_HANDLE );
1216 err = svcctl_DeleteService(hsvc->hdr.server_handle);
1218 __EXCEPT(rpc_filter)
1220 err = map_exception_code(GetExceptionCode());
1229 /* Close the key to the service */
1230 RegCloseKey(hsvc->hkey);
1236 /******************************************************************************
1237 * StartServiceA [ADVAPI32.@]
1242 * hService [I] Handle of service
1243 * dwNumServiceArgs [I] Number of arguments
1244 * lpServiceArgVectors [I] Address of array of argument strings
1247 * - NT implements this function using an obscure RPC call.
1248 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1249 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1250 * - This will only work for shared address space. How should the service
1251 * args be transferred when address spaces are separated?
1252 * - Can only start one service at a time.
1253 * - Has no concept of privilege.
1259 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1260 LPCSTR *lpServiceArgVectors )
1262 LPWSTR *lpwstr=NULL;
1266 TRACE("(%p,%d,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
1268 if (dwNumServiceArgs)
1269 lpwstr = HeapAlloc( GetProcessHeap(), 0,
1270 dwNumServiceArgs*sizeof(LPWSTR) );
1272 for(i=0; i<dwNumServiceArgs; i++)
1273 lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1275 r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1277 if (dwNumServiceArgs)
1279 for(i=0; i<dwNumServiceArgs; i++)
1280 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
1281 HeapFree(GetProcessHeap(), 0, lpwstr);
1288 /******************************************************************************
1289 * StartServiceW [ADVAPI32.@]
1291 * See StartServiceA.
1293 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1294 LPCWSTR *lpServiceArgVectors)
1296 struct sc_service *hsvc;
1299 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1301 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1304 SetLastError(ERROR_INVALID_HANDLE);
1310 err = svcctl_StartServiceW(hsvc->hdr.server_handle, dwNumServiceArgs, lpServiceArgVectors);
1312 __EXCEPT(rpc_filter)
1314 err = map_exception_code(GetExceptionCode());
1317 if (err != ERROR_SUCCESS)
1326 /******************************************************************************
1327 * QueryServiceStatus [ADVAPI32.@]
1330 * hService [I] Handle to service to get information about
1331 * lpservicestatus [O] buffer to receive the status information for the service
1334 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1335 LPSERVICE_STATUS lpservicestatus)
1337 SERVICE_STATUS_PROCESS SvcStatusData;
1341 TRACE("%p %p\n", hService, lpservicestatus);
1343 ret = QueryServiceStatusEx(hService, SC_STATUS_PROCESS_INFO, (LPBYTE)&SvcStatusData,
1344 sizeof(SERVICE_STATUS_PROCESS), &dummy);
1345 if (ret) memcpy(lpservicestatus, &SvcStatusData, sizeof(SERVICE_STATUS)) ;
1350 /******************************************************************************
1351 * QueryServiceStatusEx [ADVAPI32.@]
1353 * Get information about a service.
1356 * hService [I] Handle to service to get information about
1357 * InfoLevel [I] Level of information to get
1358 * lpBuffer [O] Destination for requested information
1359 * cbBufSize [I] Size of lpBuffer in bytes
1360 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1366 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1367 LPBYTE lpBuffer, DWORD cbBufSize,
1368 LPDWORD pcbBytesNeeded)
1370 struct sc_service *hsvc;
1373 TRACE("%p %d %p %d %p\n", hService, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1375 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1378 SetLastError( ERROR_INVALID_HANDLE );
1384 err = svcctl_QueryServiceStatusEx(hsvc->hdr.server_handle, InfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1386 __EXCEPT(rpc_filter)
1388 err = map_exception_code(GetExceptionCode());
1391 if (err != ERROR_SUCCESS)
1400 /******************************************************************************
1401 * QueryServiceConfigA [ADVAPI32.@]
1403 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1404 DWORD size, LPDWORD needed )
1409 QUERY_SERVICE_CONFIGW *configW;
1411 TRACE("%p %p %d %p\n", hService, config, size, needed);
1413 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, 2 * size )))
1415 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1418 configW = (QUERY_SERVICE_CONFIGW *)buffer;
1419 ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1420 if (!ret) goto done;
1422 config->dwServiceType = configW->dwServiceType;
1423 config->dwStartType = configW->dwStartType;
1424 config->dwErrorControl = configW->dwErrorControl;
1425 config->lpBinaryPathName = NULL;
1426 config->lpLoadOrderGroup = NULL;
1427 config->dwTagId = configW->dwTagId;
1428 config->lpDependencies = NULL;
1429 config->lpServiceStartName = NULL;
1430 config->lpDisplayName = NULL;
1432 p = (LPSTR)(config + 1);
1433 n = size - sizeof(*config);
1436 #define MAP_STR(str) \
1440 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1441 if (!sz) goto done; \
1448 MAP_STR( lpBinaryPathName );
1449 MAP_STR( lpLoadOrderGroup );
1450 MAP_STR( lpDependencies );
1451 MAP_STR( lpServiceStartName );
1452 MAP_STR( lpDisplayName );
1455 *needed = p - (LPSTR)config;
1459 HeapFree( GetProcessHeap(), 0, buffer );
1463 static DWORD move_string_to_buffer(BYTE **buf, LPWSTR *string_ptr)
1470 memset(*buf, 0, cb);
1474 cb = (strlenW(*string_ptr) + 1)*sizeof(WCHAR);
1475 memcpy(*buf, *string_ptr, cb);
1476 MIDL_user_free(*string_ptr);
1479 *string_ptr = (LPWSTR)*buf;
1485 static DWORD size_string(LPWSTR string)
1487 return (string ? (strlenW(string) + 1)*sizeof(WCHAR) : sizeof(WCHAR));
1490 /******************************************************************************
1491 * QueryServiceConfigW [ADVAPI32.@]
1494 QueryServiceConfigW( SC_HANDLE hService,
1495 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1496 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1498 QUERY_SERVICE_CONFIGW config;
1499 struct sc_service *hsvc;
1504 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1505 cbBufSize, pcbBytesNeeded);
1507 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1510 SetLastError( ERROR_INVALID_HANDLE );
1514 memset(&config, 0, sizeof(config));
1518 err = svcctl_QueryServiceConfigW(hsvc->hdr.server_handle, &config);
1520 __EXCEPT(rpc_filter)
1522 err = map_exception_code(GetExceptionCode());
1526 if (err != ERROR_SUCCESS)
1528 TRACE("services.exe: error %u\n", err);
1533 /* calculate the size required first */
1534 total = sizeof (QUERY_SERVICE_CONFIGW);
1535 total += size_string(config.lpBinaryPathName);
1536 total += size_string(config.lpLoadOrderGroup);
1537 total += size_string(config.lpDependencies);
1538 total += size_string(config.lpServiceStartName);
1539 total += size_string(config.lpDisplayName);
1541 *pcbBytesNeeded = total;
1543 /* if there's not enough memory, return an error */
1544 if( total > cbBufSize )
1546 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1547 MIDL_user_free(config.lpBinaryPathName);
1548 MIDL_user_free(config.lpLoadOrderGroup);
1549 MIDL_user_free(config.lpDependencies);
1550 MIDL_user_free(config.lpServiceStartName);
1551 MIDL_user_free(config.lpDisplayName);
1555 *lpServiceConfig = config;
1556 bufpos = ((BYTE *)lpServiceConfig) + sizeof(QUERY_SERVICE_CONFIGW);
1557 move_string_to_buffer(&bufpos, &lpServiceConfig->lpBinaryPathName);
1558 move_string_to_buffer(&bufpos, &lpServiceConfig->lpLoadOrderGroup);
1559 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDependencies);
1560 move_string_to_buffer(&bufpos, &lpServiceConfig->lpServiceStartName);
1561 move_string_to_buffer(&bufpos, &lpServiceConfig->lpDisplayName);
1563 if (bufpos - (LPBYTE)lpServiceConfig > cbBufSize)
1564 ERR("Buffer overflow!\n");
1566 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1567 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1568 TRACE("Dependencies = %s\n", debugstr_w(lpServiceConfig->lpDependencies) );
1569 TRACE("Service account name = %s\n", debugstr_w(lpServiceConfig->lpServiceStartName) );
1570 TRACE("Display name = %s\n", debugstr_w(lpServiceConfig->lpDisplayName) );
1575 /******************************************************************************
1576 * QueryServiceConfig2A [ADVAPI32.@]
1579 * observed under win2k:
1580 * The functions QueryServiceConfig2A and QueryServiceConfig2W return the same
1581 * required buffer size (in byte) at least for dwLevel SERVICE_CONFIG_DESCRIPTION
1583 BOOL WINAPI QueryServiceConfig2A(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1584 DWORD size, LPDWORD needed)
1587 LPBYTE bufferW = NULL;
1590 bufferW = HeapAlloc( GetProcessHeap(), 0, size);
1592 ret = QueryServiceConfig2W(hService, dwLevel, bufferW, size, needed);
1593 if(!ret) goto cleanup;
1596 case SERVICE_CONFIG_DESCRIPTION:
1597 { LPSERVICE_DESCRIPTIONA configA = (LPSERVICE_DESCRIPTIONA) buffer;
1598 LPSERVICE_DESCRIPTIONW configW = (LPSERVICE_DESCRIPTIONW) bufferW;
1599 if (configW->lpDescription) {
1601 configA->lpDescription = (LPSTR)(configA + 1);
1602 sz = WideCharToMultiByte( CP_ACP, 0, configW->lpDescription, -1,
1603 configA->lpDescription, size - sizeof(SERVICE_DESCRIPTIONA), NULL, NULL );
1605 FIXME("WideCharToMultiByte failed for configW->lpDescription\n");
1607 configA->lpDescription = NULL;
1610 else configA->lpDescription = NULL;
1614 FIXME("conversation W->A not implemented for level %d\n", dwLevel);
1619 HeapFree( GetProcessHeap(), 0, bufferW);
1623 /******************************************************************************
1624 * QueryServiceConfig2W [ADVAPI32.@]
1626 BOOL WINAPI QueryServiceConfig2W(SC_HANDLE hService, DWORD dwLevel, LPBYTE buffer,
1627 DWORD size, LPDWORD needed)
1632 struct sc_service *hsvc;
1634 if(dwLevel != SERVICE_CONFIG_DESCRIPTION) {
1635 if((dwLevel == SERVICE_CONFIG_DELAYED_AUTO_START_INFO) ||
1636 (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS) ||
1637 (dwLevel == SERVICE_CONFIG_FAILURE_ACTIONS_FLAG) ||
1638 (dwLevel == SERVICE_CONFIG_PRESHUTDOWN_INFO) ||
1639 (dwLevel == SERVICE_CONFIG_REQUIRED_PRIVILEGES_INFO) ||
1640 (dwLevel == SERVICE_CONFIG_SERVICE_SID_INFO))
1641 FIXME("Level %d not implemented\n", dwLevel);
1642 SetLastError(ERROR_INVALID_LEVEL);
1645 if(!needed || (!buffer && size)) {
1646 SetLastError(ERROR_INVALID_ADDRESS);
1650 TRACE("%p 0x%d %p 0x%d %p\n", hService, dwLevel, buffer, size, needed);
1652 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1655 SetLastError(ERROR_INVALID_HANDLE);
1661 case SERVICE_CONFIG_DESCRIPTION: {
1662 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1663 LPSERVICE_DESCRIPTIONW config = (LPSERVICE_DESCRIPTIONW) buffer;
1664 LPBYTE strbuf = NULL;
1665 *needed = sizeof (SERVICE_DESCRIPTIONW);
1666 sz = size - *needed;
1667 if(config && (*needed <= size))
1668 strbuf = (LPBYTE) (config + 1);
1669 r = RegQueryValueExW( hKey, szDescription, 0, &type, strbuf, &sz );
1670 if((r == ERROR_SUCCESS) && ( type != REG_SZ)) {
1671 FIXME("SERVICE_CONFIG_DESCRIPTION: don't know how to handle type %d\n", type);
1676 if(r == ERROR_SUCCESS)
1677 config->lpDescription = (LPWSTR) (config + 1);
1679 config->lpDescription = NULL;
1685 SetLastError(ERROR_INSUFFICIENT_BUFFER);
1687 return (*needed <= size);
1690 /******************************************************************************
1691 * EnumServicesStatusA [ADVAPI32.@]
1694 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
1695 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
1696 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1697 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1699 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1700 dwServiceType, dwServiceState, lpServices, cbBufSize,
1701 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1702 SetLastError (ERROR_ACCESS_DENIED);
1706 /******************************************************************************
1707 * EnumServicesStatusW [ADVAPI32.@]
1710 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
1711 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
1712 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1713 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1715 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1716 dwServiceType, dwServiceState, lpServices, cbBufSize,
1717 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1718 SetLastError (ERROR_ACCESS_DENIED);
1722 /******************************************************************************
1723 * EnumServicesStatusExA [ADVAPI32.@]
1726 EnumServicesStatusExA(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType,
1727 DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1728 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCSTR pszGroupName)
1730 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager, InfoLevel,
1731 dwServiceType, dwServiceState, lpServices, cbBufSize,
1732 pcbBytesNeeded, lpServicesReturned, lpResumeHandle, debugstr_a(pszGroupName));
1733 *lpServicesReturned = 0;
1734 SetLastError (ERROR_ACCESS_DENIED);
1738 /******************************************************************************
1739 * EnumServicesStatusExW [ADVAPI32.@]
1742 EnumServicesStatusExW(SC_HANDLE hSCManager, SC_ENUM_TYPE InfoLevel, DWORD dwServiceType,
1743 DWORD dwServiceState, LPBYTE lpServices, DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1744 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle, LPCWSTR pszGroupName)
1746 FIXME("%p level=%d type=%x state=%x %p %x %p %p %p %s\n", hSCManager, InfoLevel,
1747 dwServiceType, dwServiceState, lpServices, cbBufSize,
1748 pcbBytesNeeded, lpServicesReturned, lpResumeHandle, debugstr_w(pszGroupName));
1749 SetLastError (ERROR_ACCESS_DENIED);
1753 /******************************************************************************
1754 * GetServiceKeyNameA [ADVAPI32.@]
1756 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1757 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1759 LPWSTR lpDisplayNameW, lpServiceNameW;
1763 TRACE("%p %s %p %p\n", hSCManager,
1764 debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1766 lpDisplayNameW = SERV_dup(lpDisplayName);
1768 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1770 lpServiceNameW = NULL;
1772 sizeW = *lpcchBuffer;
1773 if (!GetServiceKeyNameW(hSCManager, lpDisplayNameW, lpServiceNameW, &sizeW))
1775 if (*lpcchBuffer && lpServiceName)
1776 lpServiceName[0] = 0;
1777 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1781 if (!WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, (sizeW + 1), lpServiceName,
1782 *lpcchBuffer, NULL, NULL ))
1784 if (*lpcchBuffer && lpServiceName)
1785 lpServiceName[0] = 0;
1786 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpServiceNameW, -1, NULL, 0, NULL, NULL);
1790 /* lpcchBuffer not updated - same as in GetServiceDisplayNameA */
1794 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1795 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1799 /******************************************************************************
1800 * GetServiceKeyNameW [ADVAPI32.@]
1802 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1803 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1805 struct sc_manager *hscm;
1808 TRACE("%p %s %p %p\n", hSCManager,
1809 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1811 hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER);
1814 SetLastError(ERROR_INVALID_HANDLE);
1820 SetLastError(ERROR_INVALID_ADDRESS);
1826 err = svcctl_GetServiceKeyNameW(hscm->hdr.server_handle,
1827 lpDisplayName, lpServiceName, lpServiceName ? *lpcchBuffer : 0, lpcchBuffer);
1829 __EXCEPT(rpc_filter)
1831 err = map_exception_code(GetExceptionCode());
1837 return err == ERROR_SUCCESS;
1840 /******************************************************************************
1841 * QueryServiceLockStatusA [ADVAPI32.@]
1843 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1844 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1845 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1847 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1852 /******************************************************************************
1853 * QueryServiceLockStatusW [ADVAPI32.@]
1855 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1856 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1857 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1859 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1864 /******************************************************************************
1865 * GetServiceDisplayNameA [ADVAPI32.@]
1867 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1868 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1870 LPWSTR lpServiceNameW, lpDisplayNameW;
1874 TRACE("%p %s %p %p\n", hSCManager,
1875 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1877 lpServiceNameW = SERV_dup(lpServiceName);
1879 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, *lpcchBuffer * sizeof(WCHAR));
1881 lpDisplayNameW = NULL;
1883 sizeW = *lpcchBuffer;
1884 if (!GetServiceDisplayNameW(hSCManager, lpServiceNameW, lpDisplayNameW, &sizeW))
1886 if (*lpcchBuffer && lpDisplayName)
1887 lpDisplayName[0] = 0;
1888 *lpcchBuffer = sizeW*2; /* we can only provide an upper estimation of string length */
1892 if (!WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, (sizeW + 1), lpDisplayName,
1893 *lpcchBuffer, NULL, NULL ))
1895 if (*lpcchBuffer && lpDisplayName)
1896 lpDisplayName[0] = 0;
1897 *lpcchBuffer = WideCharToMultiByte(CP_ACP, 0, lpDisplayNameW, -1, NULL, 0, NULL, NULL);
1901 /* probably due to a bug GetServiceDisplayNameA doesn't modify lpcchBuffer on success.
1902 * (but if the function succeeded it means that is a good upper estimation of the size) */
1906 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
1907 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
1911 /******************************************************************************
1912 * GetServiceDisplayNameW [ADVAPI32.@]
1914 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1915 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1917 struct sc_manager *hscm;
1920 TRACE("%p %s %p %p\n", hSCManager,
1921 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1923 hscm = sc_handle_get_handle_data(hSCManager, SC_HTYPE_MANAGER);
1926 SetLastError(ERROR_INVALID_HANDLE);
1932 SetLastError(ERROR_INVALID_ADDRESS);
1938 err = svcctl_GetServiceDisplayNameW(hscm->hdr.server_handle,
1939 lpServiceName, lpDisplayName, lpDisplayName ? *lpcchBuffer : 0, lpcchBuffer);
1941 __EXCEPT(rpc_filter)
1943 err = map_exception_code(GetExceptionCode());
1949 return err == ERROR_SUCCESS;
1952 /******************************************************************************
1953 * ChangeServiceConfigW [ADVAPI32.@]
1955 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1956 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1957 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1958 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1960 struct sc_service *hsvc;
1964 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
1965 hService, dwServiceType, dwStartType, dwErrorControl,
1966 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1967 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1968 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1970 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1973 SetLastError( ERROR_INVALID_HANDLE );
1977 cb_pwd = lpPassword ? (strlenW(lpPassword) + 1)*sizeof(WCHAR) : 0;
1981 err = svcctl_ChangeServiceConfigW(hsvc->hdr.server_handle, dwServiceType,
1982 dwStartType, dwErrorControl, lpBinaryPathName, lpLoadOrderGroup, lpdwTagId,
1983 (const BYTE *)lpDependencies, multisz_cb(lpDependencies), lpServiceStartName,
1984 (const BYTE *)lpPassword, cb_pwd, lpDisplayName);
1986 __EXCEPT(rpc_filter)
1988 err = map_exception_code(GetExceptionCode());
1992 if (err != ERROR_SUCCESS)
1995 return err == ERROR_SUCCESS;
1998 /******************************************************************************
1999 * ChangeServiceConfigA [ADVAPI32.@]
2001 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
2002 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
2003 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
2004 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
2006 LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
2007 LPWSTR wServiceStartName, wPassword, wDisplayName;
2010 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2011 hService, dwServiceType, dwStartType, dwErrorControl,
2012 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
2013 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
2014 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
2016 wBinaryPathName = SERV_dup( lpBinaryPathName );
2017 wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
2018 wDependencies = SERV_dupmulti( lpDependencies );
2019 wServiceStartName = SERV_dup( lpServiceStartName );
2020 wPassword = SERV_dup( lpPassword );
2021 wDisplayName = SERV_dup( lpDisplayName );
2023 r = ChangeServiceConfigW( hService, dwServiceType,
2024 dwStartType, dwErrorControl, wBinaryPathName,
2025 wLoadOrderGroup, lpdwTagId, wDependencies,
2026 wServiceStartName, wPassword, wDisplayName);
2028 HeapFree( GetProcessHeap(), 0, wBinaryPathName );
2029 HeapFree( GetProcessHeap(), 0, wLoadOrderGroup );
2030 HeapFree( GetProcessHeap(), 0, wDependencies );
2031 HeapFree( GetProcessHeap(), 0, wServiceStartName );
2032 HeapFree( GetProcessHeap(), 0, wPassword );
2033 HeapFree( GetProcessHeap(), 0, wDisplayName );
2038 /******************************************************************************
2039 * ChangeServiceConfig2A [ADVAPI32.@]
2041 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
2046 TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
2048 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2050 LPSERVICE_DESCRIPTIONA sd = (LPSERVICE_DESCRIPTIONA) lpInfo;
2051 SERVICE_DESCRIPTIONW sdw;
2053 sdw.lpDescription = SERV_dup( sd->lpDescription );
2055 r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
2057 HeapFree( GetProcessHeap(), 0, sdw.lpDescription );
2059 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
2061 LPSERVICE_FAILURE_ACTIONSA fa = (LPSERVICE_FAILURE_ACTIONSA) lpInfo;
2062 SERVICE_FAILURE_ACTIONSW faw;
2064 faw.dwResetPeriod = fa->dwResetPeriod;
2065 faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
2066 faw.lpCommand = SERV_dup( fa->lpCommand );
2067 faw.cActions = fa->cActions;
2068 faw.lpsaActions = fa->lpsaActions;
2070 r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
2072 HeapFree( GetProcessHeap(), 0, faw.lpRebootMsg );
2073 HeapFree( GetProcessHeap(), 0, faw.lpCommand );
2076 SetLastError( ERROR_INVALID_PARAMETER );
2081 /******************************************************************************
2082 * ChangeServiceConfig2W [ADVAPI32.@]
2084 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
2088 struct sc_service *hsvc;
2090 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
2093 SetLastError( ERROR_INVALID_HANDLE );
2098 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2100 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
2101 LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo;
2102 if (sd->lpDescription)
2104 TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
2105 if (sd->lpDescription[0] == 0)
2106 RegDeleteValueW(hKey,szDescription);
2108 RegSetValueExW(hKey, szDescription, 0, REG_SZ,
2109 (LPVOID)sd->lpDescription,
2110 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
2114 FIXME("STUB: %p %d %p\n",hService, dwInfoLevel, lpInfo);
2118 /******************************************************************************
2119 * QueryServiceObjectSecurity [ADVAPI32.@]
2121 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
2122 SECURITY_INFORMATION dwSecurityInformation,
2123 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2124 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2126 SECURITY_DESCRIPTOR descriptor;
2131 FIXME("%p %d %p %u %p - semi-stub\n", hService, dwSecurityInformation,
2132 lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
2134 if (dwSecurityInformation != DACL_SECURITY_INFORMATION)
2135 FIXME("information %d not supported\n", dwSecurityInformation);
2137 InitializeSecurityDescriptor(&descriptor, SECURITY_DESCRIPTOR_REVISION);
2139 InitializeAcl(&acl, sizeof(ACL), ACL_REVISION);
2140 SetSecurityDescriptorDacl(&descriptor, TRUE, &acl, TRUE);
2143 succ = MakeSelfRelativeSD(&descriptor, lpSecurityDescriptor, &size);
2144 *pcbBytesNeeded = size;
2148 /******************************************************************************
2149 * SetServiceObjectSecurity [ADVAPI32.@]
2151 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
2152 SECURITY_INFORMATION dwSecurityInformation,
2153 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2155 FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
2159 /******************************************************************************
2160 * SetServiceBits [ADVAPI32.@]
2162 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2163 DWORD dwServiceBits,
2165 BOOL bUpdateImmediately)
2167 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2168 bSetBitsOn, bUpdateImmediately);
2172 /* thunk for calling the RegisterServiceCtrlHandler handler function */
2173 static DWORD WINAPI ctrl_handler_thunk( DWORD control, DWORD type, void *data, void *context )
2175 LPHANDLER_FUNCTION func = context;
2178 return ERROR_SUCCESS;
2181 /******************************************************************************
2182 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
2184 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerA( LPCSTR name, LPHANDLER_FUNCTION handler )
2186 return RegisterServiceCtrlHandlerExA( name, ctrl_handler_thunk, handler );
2189 /******************************************************************************
2190 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
2192 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR name, LPHANDLER_FUNCTION handler )
2194 return RegisterServiceCtrlHandlerExW( name, ctrl_handler_thunk, handler );
2197 /******************************************************************************
2198 * RegisterServiceCtrlHandlerExA [ADVAPI32.@]
2200 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR name, LPHANDLER_FUNCTION_EX handler, LPVOID context )
2203 SERVICE_STATUS_HANDLE ret;
2205 nameW = SERV_dup(name);
2206 ret = RegisterServiceCtrlHandlerExW( nameW, handler, context );
2207 HeapFree( GetProcessHeap(), 0, nameW );
2211 /******************************************************************************
2212 * RegisterServiceCtrlHandlerExW [ADVAPI32.@]
2214 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2215 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2222 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2224 hSCM = OpenSCManagerW( NULL, NULL, SC_MANAGER_CONNECT );
2227 hService = OpenServiceW( hSCM, lpServiceName, SERVICE_SET_STATUS );
2228 CloseServiceHandle(hSCM);
2232 EnterCriticalSection( &service_cs );
2233 for (i = 0; i < nb_services; i++)
2235 if(!strcmpW(lpServiceName, services[i]->name))
2237 services[i]->handler = lpHandlerProc;
2238 services[i]->context = lpContext;
2243 LeaveCriticalSection( &service_cs );
2247 CloseServiceHandle(hService);
2248 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
2252 return (SERVICE_STATUS_HANDLE)hService;
2255 /******************************************************************************
2256 * EnumDependentServicesA [ADVAPI32.@]
2258 BOOL WINAPI EnumDependentServicesA( SC_HANDLE hService, DWORD dwServiceState,
2259 LPENUM_SERVICE_STATUSA lpServices, DWORD cbBufSize,
2260 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2262 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2263 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2265 *lpServicesReturned = 0;
2269 /******************************************************************************
2270 * EnumDependentServicesW [ADVAPI32.@]
2272 BOOL WINAPI EnumDependentServicesW( SC_HANDLE hService, DWORD dwServiceState,
2273 LPENUM_SERVICE_STATUSW lpServices, DWORD cbBufSize,
2274 LPDWORD pcbBytesNeeded, LPDWORD lpServicesReturned )
2276 FIXME("%p 0x%08x %p 0x%08x %p %p - stub\n", hService, dwServiceState,
2277 lpServices, cbBufSize, pcbBytesNeeded, lpServicesReturned);
2279 *lpServicesReturned = 0;