2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
5 * Copyright 2005 Mike McCormack
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
32 #include "wine/unicode.h"
33 #include "wine/debug.h"
38 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
40 static const WCHAR szServiceManagerKey[] = { 'S','y','s','t','e','m','\\',
41 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
42 'S','e','r','v','i','c','e','s',0 };
43 static const WCHAR szSCMLock[] = {'A','D','V','A','P','I','_','S','C','M',
46 typedef struct service_start_info_t
53 #define WINESERV_STARTINFO 1
54 #define WINESERV_GETSTATUS 2
55 #define WINESERV_SENDCONTROL 3
57 typedef struct service_data_t
59 struct service_data_t *next;
61 LPHANDLER_FUNCTION handler;
62 LPHANDLER_FUNCTION_EX handler_ex;
65 SERVICE_STATUS status;
68 BOOL extended : 1; /* uses handler_ex instead of handler? */
70 LPSERVICE_MAIN_FUNCTIONA a;
71 LPSERVICE_MAIN_FUNCTIONW w;
77 static CRITICAL_SECTION service_cs;
78 static CRITICAL_SECTION_DEBUG service_cs_debug =
81 { &service_cs_debug.ProcessLocksList,
82 &service_cs_debug.ProcessLocksList },
83 0, 0, { (DWORD_PTR)(__FILE__ ": service_cs") }
85 static CRITICAL_SECTION service_cs = { &service_cs_debug, -1, 0, 0, 0, 0 };
87 static service_data *service_list;
89 /******************************************************************************
93 #define MAX_SERVICE_NAME 256
95 typedef enum { SC_HTYPE_MANAGER, SC_HTYPE_SERVICE } SC_HANDLE_TYPE;
98 typedef VOID (*sc_handle_destructor)(struct sc_handle *);
102 SC_HANDLE_TYPE htype;
104 sc_handle_destructor destroy;
107 struct sc_manager /* service control manager handle */
109 struct sc_handle hdr;
110 HKEY hkey; /* handle to services database in the registry */
113 struct sc_service /* service handle */
115 struct sc_handle hdr;
116 HKEY hkey; /* handle to service entry in the registry (under hkey) */
117 struct sc_manager *scm; /* pointer to SCM handle */
121 static void *sc_handle_alloc(SC_HANDLE_TYPE htype, DWORD size,
122 sc_handle_destructor destroy)
124 struct sc_handle *hdr;
126 hdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
131 hdr->destroy = destroy;
133 TRACE("sc_handle type=%d -> %p\n", htype, hdr);
137 static void *sc_handle_get_handle_data(SC_HANDLE handle, DWORD htype)
139 struct sc_handle *hdr = (struct sc_handle *) handle;
143 if (hdr->htype != htype)
148 static void sc_handle_free(struct sc_handle* hdr)
152 if (--hdr->ref_count)
155 HeapFree(GetProcessHeap(), 0, hdr);
158 static void sc_handle_destroy_manager(struct sc_handle *handle)
160 struct sc_manager *mgr = (struct sc_manager*) handle;
162 TRACE("destroying SC Manager %p\n", mgr);
164 RegCloseKey(mgr->hkey);
167 static void sc_handle_destroy_service(struct sc_handle *handle)
169 struct sc_service *svc = (struct sc_service*) handle;
171 TRACE("destroying service %p\n", svc);
173 RegCloseKey(svc->hkey);
175 sc_handle_free(&svc->scm->hdr);
179 /******************************************************************************
180 * String management functions
182 static inline LPWSTR SERV_dup( LPCSTR str )
189 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
190 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
191 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
195 static inline LPWSTR SERV_dupmulti(LPCSTR str)
203 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
204 n += (strlen( &str[n] ) + 1);
209 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
210 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
214 static inline VOID SERV_free( LPWSTR wstr )
216 HeapFree( GetProcessHeap(), 0, wstr );
219 /******************************************************************************
220 * registry access functions and data
222 static const WCHAR szDisplayName[] = {
223 'D','i','s','p','l','a','y','N','a','m','e', 0 };
224 static const WCHAR szType[] = {'T','y','p','e',0};
225 static const WCHAR szStart[] = {'S','t','a','r','t',0};
226 static const WCHAR szError[] = {
227 'E','r','r','o','r','C','o','n','t','r','o','l', 0};
228 static const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
229 static const WCHAR szGroup[] = {'G','r','o','u','p',0};
230 static const WCHAR szDependencies[] = {
231 'D','e','p','e','n','d','e','n','c','i','e','s',0};
232 static const WCHAR szDependOnService[] = {
233 'D','e','p','e','n','d','O','n','S','e','r','v','i','c','e',0};
242 static inline void service_set_value( struct reg_value *val,
243 DWORD type, LPCWSTR name, LPCVOID data, DWORD size )
251 static inline void service_set_dword( struct reg_value *val,
252 LPCWSTR name, DWORD *data )
254 service_set_value( val, REG_DWORD, name, data, sizeof (DWORD));
257 static inline void service_set_string( struct reg_value *val,
258 LPCWSTR name, LPCWSTR string )
260 DWORD len = (lstrlenW(string)+1) * sizeof (WCHAR);
261 service_set_value( val, REG_SZ, name, string, len );
264 static inline void service_set_multi_string( struct reg_value *val,
265 LPCWSTR name, LPCWSTR string )
269 /* determine the length of a double null terminated multi string */
271 len += (lstrlenW( &string[ len ] )+1);
272 } while ( string[ len++ ] );
274 len *= sizeof (WCHAR);
275 service_set_value( val, REG_MULTI_SZ, name, string, len );
278 static inline LONG service_write_values( HKEY hKey,
279 struct reg_value *val, int n )
281 LONG r = ERROR_SUCCESS;
286 r = RegSetValueExW(hKey, val[i].name, 0, val[i].type,
287 (const BYTE*)val[i].data, val[i].size );
288 if( r != ERROR_SUCCESS )
294 /******************************************************************************
295 * Service IPC functions
297 static LPWSTR service_get_pipe_name(LPWSTR service)
299 static const WCHAR prefix[] = { '\\','\\','.','\\','p','i','p','e','\\',
300 '_','_','w','i','n','e','s','e','r','v','i','c','e','_',0};
304 len = sizeof prefix + strlenW(service)*sizeof(WCHAR);
305 name = HeapAlloc(GetProcessHeap(), 0, len);
306 strcpyW(name, prefix);
307 strcatW(name, service);
311 static HANDLE service_open_pipe(LPWSTR service)
313 LPWSTR szPipe = service_get_pipe_name( service );
314 HANDLE handle = INVALID_HANDLE_VALUE;
317 handle = CreateFileW(szPipe, GENERIC_READ|GENERIC_WRITE,
318 0, NULL, OPEN_ALWAYS, 0, NULL);
319 if (handle != INVALID_HANDLE_VALUE)
321 if (GetLastError() != ERROR_PIPE_BUSY)
323 } while (WaitNamedPipeW(szPipe, NMPWAIT_WAIT_FOREVER));
329 /******************************************************************************
330 * service_get_event_handle
332 static HANDLE service_get_event_handle(LPWSTR service)
334 static const WCHAR prefix[] = {
335 '_','_','w','i','n','e','s','e','r','v','i','c','e','_',0};
340 len = sizeof prefix + strlenW(service)*sizeof(WCHAR);
341 name = HeapAlloc(GetProcessHeap(), 0, len);
342 strcpyW(name, prefix);
343 strcatW(name, service);
344 handle = CreateEventW(NULL, TRUE, FALSE, name);
349 /******************************************************************************
352 * Call into the main service routine provided by StartServiceCtrlDispatcher.
354 static DWORD WINAPI service_thread(LPVOID arg)
356 service_data *info = arg;
357 LPWSTR str = info->args;
358 DWORD argc = 0, len = 0;
364 len += strlenW(&str[len]) + 1;
371 info->proc.w(0, NULL);
373 info->proc.a(0, NULL);
381 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPWSTR));
382 for (argc=0, p=str; *p; p += strlenW(p) + 1)
386 info->proc.w(argc, argv);
387 HeapFree(GetProcessHeap(), 0, argv);
391 LPSTR strA, *argv, p;
394 lenA = WideCharToMultiByte(CP_ACP,0, str, len, NULL, 0, NULL, NULL);
395 strA = HeapAlloc(GetProcessHeap(), 0, lenA);
396 WideCharToMultiByte(CP_ACP,0, str, len, strA, lenA, NULL, NULL);
398 argv = HeapAlloc(GetProcessHeap(), 0, (argc+1)*sizeof(LPSTR));
399 for (argc=0, p=strA; *p; p += strlen(p) + 1)
403 info->proc.a(argc, argv);
404 HeapFree(GetProcessHeap(), 0, argv);
405 HeapFree(GetProcessHeap(), 0, strA);
410 /******************************************************************************
411 * service_handle_start
413 static BOOL service_handle_start(HANDLE pipe, service_data *service, DWORD count)
415 DWORD read = 0, result = 0;
419 TRACE("%p %p %d\n", pipe, service, count);
421 args = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
422 r = ReadFile(pipe, args, count*sizeof(WCHAR), &read, NULL);
423 if (!r || count!=read/sizeof(WCHAR) || args[count-1])
425 ERR("pipe read failed r = %d count = %d read = %d args[n-1]=%s\n",
426 r, count, read, debugstr_wn(args, count));
432 ERR("service is not stopped\n");
436 SERV_free(service->args);
437 service->args = args;
439 service->thread = CreateThread( NULL, 0, service_thread,
443 HeapFree(GetProcessHeap(), 0, args);
444 WriteFile( pipe, &result, sizeof result, &read, NULL );
449 /******************************************************************************
450 * service_send_start_message
452 static BOOL service_send_start_message(HANDLE pipe, LPCWSTR *argv, DWORD argc)
454 DWORD i, len, count, result;
455 service_start_info *ssi;
459 TRACE("%p %p %d\n", pipe, argv, argc);
461 /* calculate how much space do we need to send the startup info */
463 for (i=0; i<argc; i++)
464 len += strlenW(argv[i])+1;
466 ssi = HeapAlloc(GetProcessHeap(),0,sizeof *ssi + (len-1)*sizeof(WCHAR));
467 ssi->cmd = WINESERV_STARTINFO;
470 /* copy service args into a single buffer*/
472 for (i=0; i<argc; i++)
479 r = WriteFile(pipe, ssi, sizeof *ssi + len*sizeof(WCHAR), &count, NULL);
481 r = ReadFile(pipe, &result, sizeof result, &count, NULL);
483 HeapFree(GetProcessHeap(),0,ssi);
488 /******************************************************************************
489 * service_handle_get_status
491 static BOOL service_handle_get_status(HANDLE pipe, service_data *service)
495 return WriteFile(pipe, &service->status,
496 sizeof service->status, &count, NULL);
499 /******************************************************************************
502 static BOOL service_get_status(HANDLE pipe, LPSERVICE_STATUS status)
504 DWORD cmd[2], count = 0;
507 cmd[0] = WINESERV_GETSTATUS;
509 r = WriteFile( pipe, cmd, sizeof cmd, &count, NULL );
510 if (!r || count != sizeof cmd)
512 ERR("service protocol error - failed to write pipe!\n");
515 r = ReadFile( pipe, status, sizeof *status, &count, NULL );
516 if (!r || count != sizeof *status)
517 ERR("service protocol error - failed to read pipe "
518 "r = %d count = %d!\n", r, count);
522 /******************************************************************************
523 * service_send_control
525 static BOOL service_send_control(HANDLE pipe, DWORD dwControl, DWORD *result)
527 DWORD cmd[2], count = 0;
530 cmd[0] = WINESERV_SENDCONTROL;
532 r = WriteFile(pipe, cmd, sizeof cmd, &count, NULL);
533 if (!r || count != sizeof cmd)
535 ERR("service protocol error - failed to write pipe!\n");
538 r = ReadFile(pipe, result, sizeof *result, &count, NULL);
539 if (!r || count != sizeof *result)
540 ERR("service protocol error - failed to read pipe "
541 "r = %d count = %d!\n", r, count);
545 /******************************************************************************
546 * service_accepts_control
548 static BOOL service_accepts_control(service_data *service, DWORD dwControl)
550 DWORD a = service->status.dwControlsAccepted;
554 case SERVICE_CONTROL_INTERROGATE:
556 case SERVICE_CONTROL_STOP:
557 if (a&SERVICE_ACCEPT_STOP)
560 case SERVICE_CONTROL_SHUTDOWN:
561 if (a&SERVICE_ACCEPT_SHUTDOWN)
564 case SERVICE_CONTROL_PAUSE:
565 case SERVICE_CONTROL_CONTINUE:
566 if (a&SERVICE_ACCEPT_PAUSE_CONTINUE)
569 case SERVICE_CONTROL_PARAMCHANGE:
570 if (a&SERVICE_ACCEPT_PARAMCHANGE)
573 case SERVICE_CONTROL_NETBINDADD:
574 case SERVICE_CONTROL_NETBINDREMOVE:
575 case SERVICE_CONTROL_NETBINDENABLE:
576 case SERVICE_CONTROL_NETBINDDISABLE:
577 if (a&SERVICE_ACCEPT_NETBINDCHANGE)
580 if (!service->extended)
584 case SERVICE_CONTROL_HARDWAREPROFILECHANGE:
585 if (a&SERVICE_ACCEPT_HARDWAREPROFILECHANGE)
588 case SERVICE_CONTROL_POWEREVENT:
589 if (a&SERVICE_ACCEPT_POWEREVENT)
592 case SERVICE_CONTROL_SESSIONCHANGE:
593 if (a&SERVICE_ACCEPT_SESSIONCHANGE)
600 /******************************************************************************
601 * service_handle_control
603 static BOOL service_handle_control(HANDLE pipe, service_data *service,
606 DWORD count, ret = ERROR_INVALID_SERVICE_CONTROL;
608 TRACE("received control %d\n", dwControl);
610 if (service_accepts_control(service, dwControl))
612 if (service->extended && service->handler.handler_ex)
614 service->handler.handler_ex(dwControl, 0, NULL, service->context);
617 else if (service->handler.handler)
619 service->handler.handler(dwControl);
623 return WriteFile(pipe, &ret, sizeof ret, &count, NULL);
626 /******************************************************************************
627 * service_reap_thread
629 static DWORD service_reap_thread(service_data *service)
633 if (!service->thread)
635 GetExitCodeThread(service->thread, &exitcode);
636 if (exitcode!=STILL_ACTIVE)
638 CloseHandle(service->thread);
644 /******************************************************************************
645 * service_control_dispatcher
647 static DWORD WINAPI service_control_dispatcher(LPVOID arg)
649 service_data *service = arg;
653 TRACE("%p %s\n", service, debugstr_w(service->name));
655 /* create a pipe to talk to the rest of the world with */
656 name = service_get_pipe_name(service->name);
657 pipe = CreateNamedPipeW(name, PIPE_ACCESS_DUPLEX,
658 PIPE_TYPE_BYTE|PIPE_WAIT, 1, 256, 256, 10000, NULL );
661 /* let the process who started us know we've tried to create a pipe */
662 event = service_get_event_handle(service->name);
666 if (pipe==INVALID_HANDLE_VALUE)
668 ERR("failed to create pipe for %s, error = %d\n",
669 debugstr_w(service->name), GetLastError());
673 /* dispatcher loop */
677 DWORD count, req[2] = {0,0};
679 r = ConnectNamedPipe(pipe, NULL);
680 if (!r && GetLastError() != ERROR_PIPE_CONNECTED)
682 ERR("pipe connect failed\n");
686 r = ReadFile( pipe, &req, sizeof req, &count, NULL );
687 if (!r || count!=sizeof req)
689 ERR("pipe read failed\n");
693 service_reap_thread(service);
695 /* handle the request */
698 case WINESERV_STARTINFO:
699 service_handle_start(pipe, service, req[1]);
701 case WINESERV_GETSTATUS:
702 service_handle_get_status(pipe, service);
704 case WINESERV_SENDCONTROL:
705 service_handle_control(pipe, service, req[1]);
708 ERR("received invalid command %d length %d\n", req[0], req[1]);
711 FlushFileBuffers(pipe);
712 DisconnectNamedPipe(pipe);
719 /******************************************************************************
720 * service_run_threads
722 static BOOL service_run_threads(void)
724 service_data *service;
725 DWORD count = 0, n = 0;
728 EnterCriticalSection( &service_cs );
730 /* count how many services there are */
731 for (service = service_list; service; service = service->next)
734 TRACE("starting %d pipe listener threads\n", count);
736 handles = HeapAlloc(GetProcessHeap(), 0, sizeof(HANDLE)*count);
738 for (n=0, service = service_list; service; service = service->next, n++)
739 handles[n] = CreateThread( NULL, 0, service_control_dispatcher,
743 LeaveCriticalSection( &service_cs );
745 /* wait for all the threads to pack up and exit */
746 WaitForMultipleObjectsEx(count, handles, TRUE, INFINITE, FALSE);
748 HeapFree(GetProcessHeap(), 0, handles);
753 /******************************************************************************
754 * StartServiceCtrlDispatcherA [ADVAPI32.@]
756 * See StartServiceCtrlDispatcherW.
758 BOOL WINAPI StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
764 TRACE("%p\n", servent);
766 EnterCriticalSection( &service_cs );
767 while (servent->lpServiceName)
769 LPSTR name = servent->lpServiceName;
771 len = MultiByteToWideChar(CP_ACP, 0, name, -1, NULL, 0);
772 sz = len*sizeof(WCHAR) + sizeof *info;
773 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
774 MultiByteToWideChar(CP_ACP, 0, name, -1, info->name, len);
775 info->proc.a = servent->lpServiceProc;
776 info->unicode = FALSE;
778 /* insert into the list */
779 info->next = service_list;
784 LeaveCriticalSection( &service_cs );
786 service_run_threads();
791 /******************************************************************************
792 * StartServiceCtrlDispatcherW [ADVAPI32.@]
794 * Connects a process containing one or more services to the service control
798 * servent [I] A list of the service names and service procedures
804 BOOL WINAPI StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
810 TRACE("%p\n", servent);
812 EnterCriticalSection( &service_cs );
813 while (servent->lpServiceName)
815 LPWSTR name = servent->lpServiceName;
818 sz = len*sizeof(WCHAR) + sizeof *info;
819 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz );
820 strcpyW(info->name, name);
821 info->proc.w = servent->lpServiceProc;
822 info->unicode = TRUE;
824 /* insert into the list */
825 info->next = service_list;
830 LeaveCriticalSection( &service_cs );
832 service_run_threads();
837 /******************************************************************************
838 * LockServiceDatabase [ADVAPI32.@]
840 SC_LOCK WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
844 TRACE("%p\n",hSCManager);
846 ret = CreateSemaphoreW( NULL, 1, 1, szSCMLock );
847 if( ret && GetLastError() == ERROR_ALREADY_EXISTS )
851 SetLastError( ERROR_SERVICE_DATABASE_LOCKED );
854 TRACE("returning %p\n", ret);
859 /******************************************************************************
860 * UnlockServiceDatabase [ADVAPI32.@]
862 BOOL WINAPI UnlockServiceDatabase (SC_LOCK ScLock)
864 TRACE("%p\n",ScLock);
866 return CloseHandle( ScLock );
869 /******************************************************************************
870 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
872 SERVICE_STATUS_HANDLE WINAPI
873 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName, LPHANDLER_FUNCTION lpfHandler )
875 LPWSTR lpServiceNameW;
876 SERVICE_STATUS_HANDLE ret;
878 lpServiceNameW = SERV_dup(lpServiceName);
879 ret = RegisterServiceCtrlHandlerW( lpServiceNameW, lpfHandler );
880 SERV_free(lpServiceNameW);
884 /******************************************************************************
885 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
891 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
892 LPHANDLER_FUNCTION lpfHandler )
894 service_data *service;
896 EnterCriticalSection( &service_cs );
897 for(service = service_list; service; service = service->next)
898 if(!strcmpW(lpServiceName, service->name))
901 service->handler.handler = lpfHandler;
902 LeaveCriticalSection( &service_cs );
904 return (SERVICE_STATUS_HANDLE)service;
907 /******************************************************************************
908 * SetServiceStatus [ADVAPI32.@]
915 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
917 service_data *service;
920 TRACE("%p %x %x %x %x %x %x %x\n", hService,
921 lpStatus->dwServiceType, lpStatus->dwCurrentState,
922 lpStatus->dwControlsAccepted, lpStatus->dwWin32ExitCode,
923 lpStatus->dwServiceSpecificExitCode, lpStatus->dwCheckPoint,
924 lpStatus->dwWaitHint);
926 EnterCriticalSection( &service_cs );
927 for (service = service_list; service; service = service->next)
928 if(service == (service_data*)hService)
932 memcpy( &service->status, lpStatus, sizeof(SERVICE_STATUS) );
933 TRACE("Set service status to %d\n",service->status.dwCurrentState);
937 LeaveCriticalSection( &service_cs );
943 /******************************************************************************
944 * OpenSCManagerA [ADVAPI32.@]
946 * Establish a connection to the service control manager and open its database.
949 * lpMachineName [I] Pointer to machine name string
950 * lpDatabaseName [I] Pointer to database name string
951 * dwDesiredAccess [I] Type of access
954 * Success: A Handle to the service control manager database
957 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
958 DWORD dwDesiredAccess )
960 LPWSTR lpMachineNameW, lpDatabaseNameW;
963 lpMachineNameW = SERV_dup(lpMachineName);
964 lpDatabaseNameW = SERV_dup(lpDatabaseName);
965 ret = OpenSCManagerW(lpMachineNameW, lpDatabaseNameW, dwDesiredAccess);
966 SERV_free(lpDatabaseNameW);
967 SERV_free(lpMachineNameW);
971 /******************************************************************************
972 * OpenSCManagerW [ADVAPI32.@]
974 * See OpenSCManagerA.
976 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
977 DWORD dwDesiredAccess )
979 struct sc_manager *manager;
983 TRACE("(%s,%s,0x%08x)\n", debugstr_w(lpMachineName),
984 debugstr_w(lpDatabaseName), dwDesiredAccess);
986 if( lpDatabaseName && lpDatabaseName[0] )
988 if( strcmpiW( lpDatabaseName, SERVICES_ACTIVE_DATABASEW ) == 0 )
990 /* noop, all right */
992 else if( strcmpiW( lpDatabaseName, SERVICES_FAILED_DATABASEW ) == 0 )
994 SetLastError( ERROR_DATABASE_DOES_NOT_EXIST );
999 SetLastError( ERROR_INVALID_NAME );
1004 manager = sc_handle_alloc( SC_HTYPE_MANAGER, sizeof (struct sc_manager),
1005 sc_handle_destroy_manager );
1009 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
1010 if (r!=ERROR_SUCCESS)
1013 r = RegCreateKeyW(hReg, szServiceManagerKey, &manager->hkey);
1014 RegCloseKey( hReg );
1015 if (r!=ERROR_SUCCESS)
1018 TRACE("returning %p\n", manager);
1020 return (SC_HANDLE) &manager->hdr;
1023 sc_handle_free( &manager->hdr );
1028 /******************************************************************************
1029 * ControlService [ADVAPI32.@]
1031 * Send a control code to a service.
1034 * hService [I] Handle of the service control manager database
1035 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
1036 * lpServiceStatus [O] Destination for the status of the service, if available
1043 * Unlike M$' implementation, control requests are not serialized and may be
1044 * processed asynchronously.
1046 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
1047 LPSERVICE_STATUS lpServiceStatus )
1049 struct sc_service *hsvc;
1053 TRACE("%p %d %p\n", hService, dwControl, lpServiceStatus);
1055 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1058 SetLastError( ERROR_INVALID_HANDLE );
1062 ret = QueryServiceStatus(hService, lpServiceStatus);
1065 ERR("failed to query service status\n");
1066 SetLastError(ERROR_SERVICE_NOT_ACTIVE);
1070 switch (lpServiceStatus->dwCurrentState)
1072 case SERVICE_STOPPED:
1073 SetLastError(ERROR_SERVICE_NOT_ACTIVE);
1075 case SERVICE_START_PENDING:
1076 if (dwControl==SERVICE_CONTROL_STOP)
1079 case SERVICE_STOP_PENDING:
1080 SetLastError(ERROR_SERVICE_CANNOT_ACCEPT_CTRL);
1084 handle = service_open_pipe(hsvc->name);
1085 if (handle!=INVALID_HANDLE_VALUE)
1087 DWORD result = ERROR_SUCCESS;
1088 ret = service_send_control(handle, dwControl, &result);
1089 CloseHandle(handle);
1090 if (result!=ERROR_SUCCESS)
1092 SetLastError(result);
1100 /******************************************************************************
1101 * CloseServiceHandle [ADVAPI32.@]
1103 * Close a handle to a service or the service control manager database.
1106 * hSCObject [I] Handle to service or service control manager database
1113 CloseServiceHandle( SC_HANDLE hSCObject )
1115 TRACE("%p\n", hSCObject);
1117 sc_handle_free( (struct sc_handle*) hSCObject );
1123 /******************************************************************************
1124 * OpenServiceA [ADVAPI32.@]
1126 * Open a handle to a service.
1129 * hSCManager [I] Handle of the service control manager database
1130 * lpServiceName [I] Name of the service to open
1131 * dwDesiredAccess [I] Access required to the service
1134 * Success: Handle to the service
1137 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1138 DWORD dwDesiredAccess )
1140 LPWSTR lpServiceNameW;
1143 TRACE("%p %s %d\n", hSCManager, debugstr_a(lpServiceName), dwDesiredAccess);
1145 lpServiceNameW = SERV_dup(lpServiceName);
1146 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
1147 SERV_free(lpServiceNameW);
1152 /******************************************************************************
1153 * OpenServiceW [ADVAPI32.@]
1157 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1158 DWORD dwDesiredAccess)
1160 struct sc_manager *hscm;
1161 struct sc_service *hsvc;
1166 TRACE("%p %s %d\n", hSCManager, debugstr_w(lpServiceName), dwDesiredAccess);
1170 SetLastError(ERROR_INVALID_ADDRESS);
1174 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
1177 SetLastError( ERROR_INVALID_HANDLE );
1181 r = RegOpenKeyExW( hscm->hkey, lpServiceName, 0, KEY_ALL_ACCESS, &hKey );
1182 if (r!=ERROR_SUCCESS)
1184 SetLastError( ERROR_SERVICE_DOES_NOT_EXIST );
1188 len = strlenW(lpServiceName)+1;
1189 hsvc = sc_handle_alloc( SC_HTYPE_SERVICE,
1190 sizeof (struct sc_service) + len*sizeof(WCHAR),
1191 sc_handle_destroy_service );
1194 strcpyW( hsvc->name, lpServiceName );
1197 /* add reference to SCM handle */
1198 hscm->hdr.ref_count++;
1201 TRACE("returning %p\n",hsvc);
1203 return (SC_HANDLE) &hsvc->hdr;
1206 /******************************************************************************
1207 * CreateServiceW [ADVAPI32.@]
1210 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1211 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
1212 DWORD dwServiceType, DWORD dwStartType,
1213 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1214 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1215 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
1216 LPCWSTR lpPassword )
1218 struct sc_manager *hscm;
1219 struct sc_service *hsvc = NULL;
1223 struct reg_value val[10];
1226 TRACE("%p %s %s\n", hSCManager,
1227 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
1229 hscm = sc_handle_get_handle_data( hSCManager, SC_HTYPE_MANAGER );
1232 SetLastError( ERROR_INVALID_HANDLE );
1236 r = RegCreateKeyExW(hscm->hkey, lpServiceName, 0, NULL,
1237 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp);
1238 if (r!=ERROR_SUCCESS)
1241 if (dp != REG_CREATED_NEW_KEY)
1243 SetLastError(ERROR_SERVICE_EXISTS);
1248 service_set_string( &val[n++], szDisplayName, lpDisplayName );
1250 service_set_dword( &val[n++], szType, &dwServiceType );
1251 service_set_dword( &val[n++], szStart, &dwStartType );
1252 service_set_dword( &val[n++], szError, &dwErrorControl );
1254 if( lpBinaryPathName )
1255 service_set_string( &val[n++], szImagePath, lpBinaryPathName );
1257 if( lpLoadOrderGroup )
1258 service_set_string( &val[n++], szGroup, lpLoadOrderGroup );
1260 if( lpDependencies )
1261 service_set_multi_string( &val[n++], szDependencies, lpDependencies );
1264 FIXME("Don't know how to add a Password for a service.\n");
1266 if( lpServiceStartName )
1267 service_set_string( &val[n++], szDependOnService, lpServiceStartName );
1269 r = service_write_values( hKey, val, n );
1270 if( r != ERROR_SUCCESS )
1273 len = strlenW(lpServiceName)+1;
1274 len = sizeof (struct sc_service) + len*sizeof(WCHAR);
1275 hsvc = sc_handle_alloc( SC_HTYPE_SERVICE, len, sc_handle_destroy_service );
1278 lstrcpyW( hsvc->name, lpServiceName );
1281 hscm->hdr.ref_count++;
1283 return (SC_HANDLE) &hsvc->hdr;
1286 RegCloseKey( hKey );
1291 /******************************************************************************
1292 * CreateServiceA [ADVAPI32.@]
1295 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1296 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
1297 DWORD dwServiceType, DWORD dwStartType,
1298 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1299 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
1300 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
1303 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
1304 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
1307 TRACE("%p %s %s\n", hSCManager,
1308 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
1310 lpServiceNameW = SERV_dup( lpServiceName );
1311 lpDisplayNameW = SERV_dup( lpDisplayName );
1312 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
1313 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
1314 lpDependenciesW = SERV_dupmulti( lpDependencies );
1315 lpServiceStartNameW = SERV_dup( lpServiceStartName );
1316 lpPasswordW = SERV_dup( lpPassword );
1318 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
1319 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
1320 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
1321 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
1323 SERV_free( lpServiceNameW );
1324 SERV_free( lpDisplayNameW );
1325 SERV_free( lpBinaryPathNameW );
1326 SERV_free( lpLoadOrderGroupW );
1327 SERV_free( lpDependenciesW );
1328 SERV_free( lpServiceStartNameW );
1329 SERV_free( lpPasswordW );
1335 /******************************************************************************
1336 * DeleteService [ADVAPI32.@]
1338 * Delete a service from the service control manager database.
1341 * hService [I] Handle of the service to delete
1347 BOOL WINAPI DeleteService( SC_HANDLE hService )
1349 struct sc_service *hsvc;
1351 WCHAR valname[MAX_PATH+1];
1356 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1359 SetLastError( ERROR_INVALID_HANDLE );
1365 /* Clean out the values */
1366 rc = RegEnumValueW(hKey, index, valname,&size,0,0,0,0);
1367 while (rc == ERROR_SUCCESS)
1369 RegDeleteValueW(hKey,valname);
1372 rc = RegEnumValueW(hKey, index, valname, &size,0,0,0,0);
1378 /* delete the key */
1379 RegDeleteKeyW(hsvc->scm->hkey, hsvc->name);
1385 /******************************************************************************
1386 * StartServiceA [ADVAPI32.@]
1391 * hService [I] Handle of service
1392 * dwNumServiceArgs [I] Number of arguments
1393 * lpServiceArgVectors [I] Address of array of argument strings
1396 * - NT implements this function using an obscure RPC call.
1397 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
1398 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
1399 * - This will only work for shared address space. How should the service
1400 * args be transferred when address spaces are separated?
1401 * - Can only start one service at a time.
1402 * - Has no concept of privilege.
1408 BOOL WINAPI StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
1409 LPCSTR *lpServiceArgVectors )
1411 LPWSTR *lpwstr=NULL;
1415 TRACE("(%p,%d,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
1417 if (dwNumServiceArgs)
1418 lpwstr = HeapAlloc( GetProcessHeap(), 0,
1419 dwNumServiceArgs*sizeof(LPWSTR) );
1421 for(i=0; i<dwNumServiceArgs; i++)
1422 lpwstr[i]=SERV_dup(lpServiceArgVectors[i]);
1424 r = StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
1426 if (dwNumServiceArgs)
1428 for(i=0; i<dwNumServiceArgs; i++)
1429 SERV_free(lpwstr[i]);
1430 HeapFree(GetProcessHeap(), 0, lpwstr);
1436 /******************************************************************************
1437 * service_start_process [INTERNAL]
1439 static DWORD service_start_process(struct sc_service *hsvc)
1441 static const WCHAR _ImagePathW[] = {'I','m','a','g','e','P','a','t','h',0};
1442 PROCESS_INFORMATION pi;
1444 LPWSTR path = NULL, str;
1445 DWORD type, size, ret;
1449 /* read the executable path from memory */
1451 ret = RegQueryValueExW(hsvc->hkey, _ImagePathW, NULL, &type, NULL, &size);
1452 if (ret!=ERROR_SUCCESS)
1454 str = HeapAlloc(GetProcessHeap(),0,size);
1455 ret = RegQueryValueExW(hsvc->hkey, _ImagePathW, NULL, &type, (LPBYTE)str, &size);
1456 if (ret==ERROR_SUCCESS)
1458 size = ExpandEnvironmentStringsW(str,NULL,0);
1459 path = HeapAlloc(GetProcessHeap(),0,size*sizeof(WCHAR));
1460 ExpandEnvironmentStringsW(str,path,size);
1462 HeapFree(GetProcessHeap(),0,str);
1466 /* wait for the process to start and set an event or terminate */
1467 handles[0] = service_get_event_handle( hsvc->name );
1468 ZeroMemory(&si, sizeof(STARTUPINFOW));
1469 si.cb = sizeof(STARTUPINFOW);
1470 r = CreateProcessW(NULL, path, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
1473 handles[1] = pi.hProcess;
1474 ret = WaitForMultipleObjectsEx(2, handles, FALSE, 30000, FALSE);
1475 if(ret != WAIT_OBJECT_0)
1477 SetLastError(ERROR_IO_PENDING);
1481 CloseHandle( pi.hThread );
1482 CloseHandle( pi.hProcess );
1484 CloseHandle( handles[0] );
1485 HeapFree(GetProcessHeap(),0,path);
1489 static BOOL service_wait_for_startup(SC_HANDLE hService)
1492 SERVICE_STATUS status;
1495 TRACE("%p\n", hService);
1497 for (i=0; i<30; i++)
1499 status.dwCurrentState = 0;
1500 r = QueryServiceStatus(hService, &status);
1503 if (status.dwCurrentState == SERVICE_RUNNING)
1505 TRACE("Service started successfully\n");
1514 /******************************************************************************
1515 * StartServiceW [ADVAPI32.@]
1517 * See StartServiceA.
1519 BOOL WINAPI StartServiceW(SC_HANDLE hService, DWORD dwNumServiceArgs,
1520 LPCWSTR *lpServiceArgVectors)
1522 struct sc_service *hsvc;
1525 HANDLE handle = INVALID_HANDLE_VALUE;
1527 TRACE("%p %d %p\n", hService, dwNumServiceArgs, lpServiceArgVectors);
1529 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1532 SetLastError(ERROR_INVALID_HANDLE);
1536 hLock = LockServiceDatabase((SC_HANDLE)hsvc->scm);
1540 handle = service_open_pipe(hsvc->name);
1541 if (handle==INVALID_HANDLE_VALUE)
1543 /* start the service process */
1544 if (service_start_process(hsvc))
1545 handle = service_open_pipe(hsvc->name);
1548 if (handle != INVALID_HANDLE_VALUE)
1550 service_send_start_message(handle, lpServiceArgVectors, dwNumServiceArgs);
1551 CloseHandle(handle);
1555 UnlockServiceDatabase( hLock );
1557 TRACE("returning %d\n", r);
1560 service_wait_for_startup(hService);
1565 /******************************************************************************
1566 * QueryServiceStatus [ADVAPI32.@]
1570 * lpservicestatus []
1573 BOOL WINAPI QueryServiceStatus(SC_HANDLE hService,
1574 LPSERVICE_STATUS lpservicestatus)
1576 struct sc_service *hsvc;
1577 DWORD size, type, val;
1581 TRACE("%p %p\n", hService, lpservicestatus);
1583 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1586 SetLastError( ERROR_INVALID_HANDLE );
1590 pipe = service_open_pipe(hsvc->name);
1591 if (pipe != INVALID_HANDLE_VALUE)
1593 r = service_get_status(pipe, lpservicestatus);
1599 TRACE("Failed to read service status\n");
1601 /* read the service type from the registry */
1603 r = RegQueryValueExA(hsvc->hkey, "Type", NULL, &type, (LPBYTE)&val, &size);
1604 if(r!=ERROR_SUCCESS || type!=REG_DWORD)
1607 lpservicestatus->dwServiceType = val;
1608 lpservicestatus->dwCurrentState = SERVICE_STOPPED; /* stopped */
1609 lpservicestatus->dwControlsAccepted = 0;
1610 lpservicestatus->dwWin32ExitCode = ERROR_SERVICE_NEVER_STARTED;
1611 lpservicestatus->dwServiceSpecificExitCode = 0;
1612 lpservicestatus->dwCheckPoint = 0;
1613 lpservicestatus->dwWaitHint = 0;
1618 /******************************************************************************
1619 * QueryServiceStatusEx [ADVAPI32.@]
1621 * Get information about a service.
1624 * hService [I] Handle to service to get information about
1625 * InfoLevel [I] Level of information to get
1626 * lpBuffer [O] Destination for requested information
1627 * cbBufSize [I] Size of lpBuffer in bytes
1628 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
1634 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
1635 LPBYTE lpBuffer, DWORD cbBufSize,
1636 LPDWORD pcbBytesNeeded)
1639 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1643 /******************************************************************************
1644 * QueryServiceConfigA [ADVAPI32.@]
1646 BOOL WINAPI QueryServiceConfigA( SC_HANDLE hService, LPQUERY_SERVICE_CONFIGA config,
1647 DWORD size, LPDWORD needed )
1652 QUERY_SERVICE_CONFIGW *configW;
1654 TRACE("%p %p %d %p\n", hService, config, size, needed);
1656 if (!(buffer = HeapAlloc( GetProcessHeap(), 0, 2 * size )))
1658 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1661 configW = (QUERY_SERVICE_CONFIGW *)buffer;
1662 ret = QueryServiceConfigW( hService, configW, 2 * size, needed );
1663 if (!ret) goto done;
1665 config->dwServiceType = configW->dwServiceType;
1666 config->dwStartType = configW->dwStartType;
1667 config->dwErrorControl = configW->dwErrorControl;
1668 config->lpBinaryPathName = NULL;
1669 config->lpLoadOrderGroup = NULL;
1670 config->dwTagId = configW->dwTagId;
1671 config->lpDependencies = NULL;
1672 config->lpServiceStartName = NULL;
1673 config->lpDisplayName = NULL;
1675 p = (LPSTR)(config + 1);
1676 n = size - sizeof(*config);
1679 #define MAP_STR(str) \
1683 DWORD sz = WideCharToMultiByte( CP_ACP, 0, configW->str, -1, p, n, NULL, NULL ); \
1684 if (!sz) goto done; \
1691 MAP_STR( lpBinaryPathName );
1692 MAP_STR( lpLoadOrderGroup );
1693 MAP_STR( lpDependencies );
1694 MAP_STR( lpServiceStartName );
1695 MAP_STR( lpDisplayName );
1698 *needed = p - buffer;
1702 HeapFree( GetProcessHeap(), 0, buffer );
1706 /******************************************************************************
1707 * QueryServiceConfigW [ADVAPI32.@]
1710 QueryServiceConfigW( SC_HANDLE hService,
1711 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1712 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1714 WCHAR str_buffer[ MAX_PATH ];
1716 DWORD type, val, sz, total, n;
1719 struct sc_service *hsvc;
1721 TRACE("%p %p %d %p\n", hService, lpServiceConfig,
1722 cbBufSize, pcbBytesNeeded);
1724 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1727 SetLastError( ERROR_INVALID_HANDLE );
1732 /* calculate the size required first */
1733 total = sizeof (QUERY_SERVICE_CONFIGW);
1735 sz = sizeof(str_buffer);
1736 r = RegQueryValueExW( hKey, szImagePath, 0, &type, (LPBYTE) str_buffer, &sz );
1737 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ || type == REG_EXPAND_SZ ) )
1739 sz = ExpandEnvironmentStringsW(str_buffer,NULL,0);
1740 if( 0 == sz ) return FALSE;
1742 total += sizeof(WCHAR) * sz;
1746 /* FIXME: set last error */
1751 r = RegQueryValueExW( hKey, szGroup, 0, &type, NULL, &sz );
1752 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
1756 r = RegQueryValueExW( hKey, szDependencies, 0, &type, NULL, &sz );
1757 if( ( r == ERROR_SUCCESS ) && ( type == REG_MULTI_SZ ) )
1760 total += sizeof(WCHAR);
1763 r = RegQueryValueExW( hKey, szStart, 0, &type, NULL, &sz );
1764 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
1768 r = RegQueryValueExW( hKey, szDisplayName, 0, &type, NULL, &sz );
1769 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
1772 *pcbBytesNeeded = total;
1774 /* if there's not enough memory, return an error */
1775 if( total > cbBufSize )
1777 SetLastError( ERROR_INSUFFICIENT_BUFFER );
1781 ZeroMemory( lpServiceConfig, total );
1784 r = RegQueryValueExW( hKey, szType, 0, &type, (LPBYTE)&val, &sz );
1785 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
1786 lpServiceConfig->dwServiceType = val;
1789 r = RegQueryValueExW( hKey, szStart, 0, &type, (LPBYTE)&val, &sz );
1790 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
1791 lpServiceConfig->dwStartType = val;
1794 r = RegQueryValueExW( hKey, szError, 0, &type, (LPBYTE)&val, &sz );
1795 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
1796 lpServiceConfig->dwErrorControl = val;
1798 /* now do the strings */
1799 p = (LPBYTE) &lpServiceConfig[1];
1800 n = total - sizeof (QUERY_SERVICE_CONFIGW);
1802 sz = sizeof(str_buffer);
1803 r = RegQueryValueExW( hKey, szImagePath, 0, &type, (LPBYTE) str_buffer, &sz );
1804 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ || type == REG_EXPAND_SZ ) )
1806 sz = ExpandEnvironmentStringsW(str_buffer, (LPWSTR) p, n);
1807 sz *= sizeof(WCHAR);
1808 if( 0 == sz || sz > n ) return FALSE;
1810 lpServiceConfig->lpBinaryPathName = (LPWSTR) p;
1816 /* FIXME: set last error */
1821 r = RegQueryValueExW( hKey, szGroup, 0, &type, p, &sz );
1822 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
1824 lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p;
1830 r = RegQueryValueExW( hKey, szDependencies, 0, &type, p, &sz );
1831 lpServiceConfig->lpDependencies = (LPWSTR) p;
1832 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
1845 ERR("Buffer overflow!\n");
1847 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1848 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1853 /******************************************************************************
1854 * EnumServicesStatusA [ADVAPI32.@]
1857 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
1858 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
1859 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1860 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1862 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1863 dwServiceType, dwServiceState, lpServices, cbBufSize,
1864 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1865 SetLastError (ERROR_ACCESS_DENIED);
1869 /******************************************************************************
1870 * EnumServicesStatusW [ADVAPI32.@]
1873 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
1874 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
1875 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
1876 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
1878 FIXME("%p type=%x state=%x %p %x %p %p %p\n", hSCManager,
1879 dwServiceType, dwServiceState, lpServices, cbBufSize,
1880 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
1881 SetLastError (ERROR_ACCESS_DENIED);
1885 /******************************************************************************
1886 * GetServiceKeyNameA [ADVAPI32.@]
1888 BOOL WINAPI GetServiceKeyNameA( SC_HANDLE hSCManager, LPCSTR lpDisplayName,
1889 LPSTR lpServiceName, LPDWORD lpcchBuffer )
1891 FIXME("%p %s %p %p\n", hSCManager, debugstr_a(lpDisplayName), lpServiceName, lpcchBuffer);
1895 /******************************************************************************
1896 * GetServiceKeyNameW [ADVAPI32.@]
1898 BOOL WINAPI GetServiceKeyNameW( SC_HANDLE hSCManager, LPCWSTR lpDisplayName,
1899 LPWSTR lpServiceName, LPDWORD lpcchBuffer )
1901 FIXME("%p %s %p %p\n", hSCManager, debugstr_w(lpDisplayName), lpServiceName, lpcchBuffer);
1905 /******************************************************************************
1906 * QueryServiceLockStatusA [ADVAPI32.@]
1908 BOOL WINAPI QueryServiceLockStatusA( SC_HANDLE hSCManager,
1909 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1910 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1912 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1917 /******************************************************************************
1918 * QueryServiceLockStatusW [ADVAPI32.@]
1920 BOOL WINAPI QueryServiceLockStatusW( SC_HANDLE hSCManager,
1921 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1922 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
1924 FIXME("%p %p %08x %p\n", hSCManager, lpLockStatus, cbBufSize, pcbBytesNeeded);
1929 /******************************************************************************
1930 * GetServiceDisplayNameA [ADVAPI32.@]
1932 BOOL WINAPI GetServiceDisplayNameA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
1933 LPSTR lpDisplayName, LPDWORD lpcchBuffer)
1935 FIXME("%p %s %p %p\n", hSCManager,
1936 debugstr_a(lpServiceName), lpDisplayName, lpcchBuffer);
1940 /******************************************************************************
1941 * GetServiceDisplayNameW [ADVAPI32.@]
1943 BOOL WINAPI GetServiceDisplayNameW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
1944 LPWSTR lpDisplayName, LPDWORD lpcchBuffer)
1946 FIXME("%p %s %p %p\n", hSCManager,
1947 debugstr_w(lpServiceName), lpDisplayName, lpcchBuffer);
1951 /******************************************************************************
1952 * ChangeServiceConfigW [ADVAPI32.@]
1954 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1955 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1956 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1957 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1959 struct reg_value val[10];
1960 struct sc_service *hsvc;
1961 DWORD r = ERROR_SUCCESS;
1965 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
1966 hService, dwServiceType, dwStartType, dwErrorControl,
1967 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1968 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1969 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1971 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
1974 SetLastError( ERROR_INVALID_HANDLE );
1979 if( dwServiceType != SERVICE_NO_CHANGE )
1980 service_set_dword( &val[n++], szType, &dwServiceType );
1982 if( dwStartType != SERVICE_NO_CHANGE )
1983 service_set_dword( &val[n++], szStart, &dwStartType );
1985 if( dwErrorControl != SERVICE_NO_CHANGE )
1986 service_set_dword( &val[n++], szError, &dwErrorControl );
1988 if( lpBinaryPathName )
1989 service_set_string( &val[n++], szImagePath, lpBinaryPathName );
1991 if( lpLoadOrderGroup )
1992 service_set_string( &val[n++], szGroup, lpLoadOrderGroup );
1994 if( lpDependencies )
1995 service_set_multi_string( &val[n++], szDependencies, lpDependencies );
1998 FIXME("ignoring password\n");
2000 if( lpServiceStartName )
2001 service_set_string( &val[n++], szDependOnService, lpServiceStartName );
2003 r = service_write_values( hsvc->hkey, val, n );
2005 return (r == ERROR_SUCCESS) ? TRUE : FALSE ;
2008 /******************************************************************************
2009 * ChangeServiceConfigA [ADVAPI32.@]
2011 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
2012 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
2013 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
2014 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
2016 LPWSTR wBinaryPathName, wLoadOrderGroup, wDependencies;
2017 LPWSTR wServiceStartName, wPassword, wDisplayName;
2020 TRACE("%p %d %d %d %s %s %p %p %s %s %s\n",
2021 hService, dwServiceType, dwStartType, dwErrorControl,
2022 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
2023 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
2024 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
2026 wBinaryPathName = SERV_dup( lpBinaryPathName );
2027 wLoadOrderGroup = SERV_dup( lpLoadOrderGroup );
2028 wDependencies = SERV_dupmulti( lpDependencies );
2029 wServiceStartName = SERV_dup( lpServiceStartName );
2030 wPassword = SERV_dup( lpPassword );
2031 wDisplayName = SERV_dup( lpDisplayName );
2033 r = ChangeServiceConfigW( hService, dwServiceType,
2034 dwStartType, dwErrorControl, wBinaryPathName,
2035 wLoadOrderGroup, lpdwTagId, wDependencies,
2036 wServiceStartName, wPassword, wDisplayName);
2038 SERV_free( wBinaryPathName );
2039 SERV_free( wLoadOrderGroup );
2040 SERV_free( wDependencies );
2041 SERV_free( wServiceStartName );
2042 SERV_free( wPassword );
2043 SERV_free( wDisplayName );
2048 /******************************************************************************
2049 * ChangeServiceConfig2A [ADVAPI32.@]
2051 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
2056 TRACE("%p %d %p\n",hService, dwInfoLevel, lpInfo);
2058 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2060 LPSERVICE_DESCRIPTIONA sd = (LPSERVICE_DESCRIPTIONA) lpInfo;
2061 SERVICE_DESCRIPTIONW sdw;
2063 sdw.lpDescription = SERV_dup( sd->lpDescription );
2065 r = ChangeServiceConfig2W( hService, dwInfoLevel, &sdw );
2067 SERV_free( sdw.lpDescription );
2069 else if (dwInfoLevel == SERVICE_CONFIG_FAILURE_ACTIONS)
2071 LPSERVICE_FAILURE_ACTIONSA fa = (LPSERVICE_FAILURE_ACTIONSA) lpInfo;
2072 SERVICE_FAILURE_ACTIONSW faw;
2074 faw.dwResetPeriod = fa->dwResetPeriod;
2075 faw.lpRebootMsg = SERV_dup( fa->lpRebootMsg );
2076 faw.lpCommand = SERV_dup( fa->lpCommand );
2077 faw.cActions = fa->cActions;
2078 faw.lpsaActions = fa->lpsaActions;
2080 r = ChangeServiceConfig2W( hService, dwInfoLevel, &faw );
2082 SERV_free( faw.lpRebootMsg );
2083 SERV_free( faw.lpCommand );
2086 SetLastError( ERROR_INVALID_PARAMETER );
2091 /******************************************************************************
2092 * ChangeServiceConfig2W [ADVAPI32.@]
2094 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
2098 struct sc_service *hsvc;
2100 hsvc = sc_handle_get_handle_data(hService, SC_HTYPE_SERVICE);
2103 SetLastError( ERROR_INVALID_HANDLE );
2108 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
2110 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
2111 LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo;
2112 if (sd->lpDescription)
2114 TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
2115 if (sd->lpDescription[0] == 0)
2116 RegDeleteValueW(hKey,szDescription);
2118 RegSetValueExW(hKey, szDescription, 0, REG_SZ,
2119 (LPVOID)sd->lpDescription,
2120 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
2124 FIXME("STUB: %p %d %p\n",hService, dwInfoLevel, lpInfo);
2128 /******************************************************************************
2129 * QueryServiceObjectSecurity [ADVAPI32.@]
2131 BOOL WINAPI QueryServiceObjectSecurity(SC_HANDLE hService,
2132 SECURITY_INFORMATION dwSecurityInformation,
2133 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2134 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
2138 FIXME("%p %d %p %u %p\n", hService, dwSecurityInformation,
2139 lpSecurityDescriptor, cbBufSize, pcbBytesNeeded);
2141 InitializeSecurityDescriptor(lpSecurityDescriptor, SECURITY_DESCRIPTOR_REVISION);
2143 pACL = HeapAlloc( GetProcessHeap(), 0, sizeof(ACL) );
2144 InitializeAcl(pACL, sizeof(ACL), ACL_REVISION);
2145 SetSecurityDescriptorDacl(lpSecurityDescriptor, TRUE, pACL, TRUE);
2149 /******************************************************************************
2150 * SetServiceObjectSecurity [ADVAPI32.@]
2152 BOOL WINAPI SetServiceObjectSecurity(SC_HANDLE hService,
2153 SECURITY_INFORMATION dwSecurityInformation,
2154 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2156 FIXME("%p %d %p\n", hService, dwSecurityInformation, lpSecurityDescriptor);
2160 /******************************************************************************
2161 * SetServiceBits [ADVAPI32.@]
2163 BOOL WINAPI SetServiceBits( SERVICE_STATUS_HANDLE hServiceStatus,
2164 DWORD dwServiceBits,
2166 BOOL bUpdateImmediately)
2168 FIXME("%p %08x %x %x\n", hServiceStatus, dwServiceBits,
2169 bSetBitsOn, bUpdateImmediately);
2173 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExA( LPCSTR lpServiceName,
2174 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2176 FIXME("%s %p %p\n", debugstr_a(lpServiceName), lpHandlerProc, lpContext);
2180 SERVICE_STATUS_HANDLE WINAPI RegisterServiceCtrlHandlerExW( LPCWSTR lpServiceName,
2181 LPHANDLER_FUNCTION_EX lpHandlerProc, LPVOID lpContext )
2183 service_data *service;
2185 TRACE("%s %p %p\n", debugstr_w(lpServiceName), lpHandlerProc, lpContext);
2187 EnterCriticalSection( &service_cs );
2188 for(service = service_list; service; service = service->next)
2189 if(!strcmpW(lpServiceName, service->name))
2193 service->handler.handler_ex = lpHandlerProc;
2194 service->context = lpContext;
2195 service->extended = TRUE;
2197 LeaveCriticalSection( &service_cs );
2199 return (SERVICE_STATUS_HANDLE)service;