2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
13 #include "wine/unicode.h"
14 #include "wine/winestring.h"
16 #include "debugtools.h"
18 DEFAULT_DEBUG_CHANNEL(advapi);
20 static DWORD start_dwNumServiceArgs;
21 static LPWSTR *start_lpServiceArgVectors;
23 /******************************************************************************
24 * EnumServicesStatusA [ADVAPI32.@]
27 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
28 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
29 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
30 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
31 { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
32 dwServiceType, dwServiceState, lpServices, cbBufSize,
33 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
34 SetLastError (ERROR_ACCESS_DENIED);
38 /******************************************************************************
39 * EnumServicesStatusW [ADVAPI32.@]
42 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
43 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
44 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
45 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
46 { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
47 dwServiceType, dwServiceState, lpServices, cbBufSize,
48 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
49 SetLastError (ERROR_ACCESS_DENIED);
53 /******************************************************************************
54 * StartServiceCtrlDispatcherA [ADVAPI32.196]
57 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
59 LPSERVICE_MAIN_FUNCTIONA fpMain;
61 DWORD dwNumServiceArgs ;
66 TRACE("(%p)\n", servent);
67 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
70 ERR("Couldn't find wait semaphore\n");
71 ERR("perhaps you need to start services using StartService\n");
75 dwNumServiceArgs = start_dwNumServiceArgs;
76 lpArgVecW = start_lpServiceArgVectors;
78 ReleaseSemaphore(wait, 1, NULL);
80 /* Convert the Unicode arg vectors back to ASCII */
82 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
83 dwNumServiceArgs*sizeof(LPSTR) );
87 for(i=0; i<dwNumServiceArgs; i++)
88 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
90 /* FIXME: should we blindly start all services? */
91 while (servent->lpServiceName) {
92 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
93 fpMain = servent->lpServiceProc;
95 /* try to start the service */
96 fpMain( dwNumServiceArgs, lpArgVecA);
103 /* free arg strings */
104 for(i=0; i<dwNumServiceArgs; i++)
105 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
106 HeapFree(GetProcessHeap(), 0, lpArgVecA);
112 /******************************************************************************
113 * StartServiceCtrlDispatcherW [ADVAPI32.197]
119 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
121 LPSERVICE_MAIN_FUNCTIONW fpMain;
123 DWORD dwNumServiceArgs ;
124 LPWSTR *lpServiceArgVectors ;
126 TRACE("(%p)\n", servent);
127 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
130 ERR("Couldn't find wait semaphore\n");
131 ERR("perhaps you need to start services using StartService\n");
135 dwNumServiceArgs = start_dwNumServiceArgs;
136 lpServiceArgVectors = start_lpServiceArgVectors;
138 ReleaseSemaphore(wait, 1, NULL);
140 /* FIXME: should we blindly start all services? */
141 while (servent->lpServiceName) {
142 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
143 fpMain = servent->lpServiceProc;
145 /* try to start the service */
146 fpMain( dwNumServiceArgs, lpServiceArgVectors);
154 /******************************************************************************
155 * RegisterServiceCtrlHandlerA [ADVAPI32.176]
157 SERVICE_STATUS_HANDLE WINAPI
158 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
159 LPHANDLER_FUNCTION lpfHandler )
160 { FIXME("%s %p\n", lpServiceName, lpfHandler);
164 /******************************************************************************
165 * RegisterServiceCtrlHandlerW [ADVAPI32.177]
171 SERVICE_STATUS_HANDLE WINAPI
172 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
173 LPHANDLER_FUNCTION lpfHandler )
174 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
178 /******************************************************************************
179 * SetServiceStatus [ADVAPI32.192]
186 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
187 { FIXME("%x %p\n",hService, lpStatus);
188 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
189 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
190 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
191 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
192 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
193 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
194 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
198 /******************************************************************************
199 * OpenSCManagerA [ADVAPI32.110]
202 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
203 DWORD dwDesiredAccess )
205 LPWSTR lpMachineNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpMachineName);
206 LPWSTR lpDatabaseNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpDatabaseName);
207 DWORD ret = OpenSCManagerW(lpMachineNameW,lpDatabaseNameW,
209 HeapFree(GetProcessHeap(),0,lpDatabaseNameW);
210 HeapFree(GetProcessHeap(),0,lpMachineNameW);
214 /******************************************************************************
215 * OpenSCManagerW [ADVAPI32.111]
216 * Establishes a connection to the service control manager and opens database
219 * This should return a SC_HANDLE
222 * lpMachineName [I] Pointer to machine name string
223 * lpDatabaseName [I] Pointer to database name string
224 * dwDesiredAccess [I] Type of access
227 * Success: Handle to service control manager database
231 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
232 DWORD dwDesiredAccess )
237 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
238 debugstr_w(lpDatabaseName), dwDesiredAccess);
241 * FIXME: what is lpDatabaseName?
242 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
243 * docs, but what if it isn't?
246 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey);
247 if (r!=ERROR_SUCCESS)
250 TRACE("returning %x\n",hKey);
256 /******************************************************************************
257 * AllocateLocallyUniqueId [ADVAPI32.12]
263 AllocateLocallyUniqueId( PLUID lpluid )
265 lpluid->s.LowPart = time(NULL);
266 lpluid->s.HighPart = 0;
271 /******************************************************************************
272 * ControlService [ADVAPI32.23]
273 * Sends a control code to a Win32-based service.
283 ControlService( SC_HANDLE hService, DWORD dwControl,
284 LPSERVICE_STATUS lpServiceStatus )
286 FIXME("(%d,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
291 /******************************************************************************
292 * CloseServiceHandle [ADVAPI32.22]
293 * Close handle to service or service control manager
296 * hSCObject [I] Handle to service or service control manager database
301 CloseServiceHandle( SC_HANDLE hSCObject )
303 TRACE("(%x)\n", hSCObject);
305 RegCloseKey(hSCObject);
311 /******************************************************************************
312 * OpenServiceA [ADVAPI32.112]
315 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
316 DWORD dwDesiredAccess )
318 LPWSTR lpServiceNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName);
322 TRACE("Request for service %s\n",lpServiceName);
325 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
326 HeapFree(GetProcessHeap(),0,lpServiceNameW);
331 /******************************************************************************
332 * OpenServiceW [ADVAPI32.113]
333 * Opens a handle to an existing service
341 * Success: Handle to the service
345 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
346 DWORD dwDesiredAccess)
348 const char *str = "System\\CurrentControlSet\\Services\\";
349 WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */
353 TRACE("(%d,%p,%ld)\n",hSCManager, lpServiceName,
356 lstrcpyAtoW(lpServiceKey,str);
357 strcatW(lpServiceKey,lpServiceName);
359 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey));
361 /* FIXME: dwDesiredAccess may need some processing */
362 r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey );
363 if (r!=ERROR_SUCCESS)
366 TRACE("returning %x\n",hKey);
371 /******************************************************************************
372 * CreateServiceW [ADVAPI32.29]
375 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
376 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
377 DWORD dwServiceType, DWORD dwStartType,
378 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
379 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
380 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
383 FIXME("(%u,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
388 /******************************************************************************
389 * CreateServiceA [ADVAPI32.28]
392 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
393 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
394 DWORD dwServiceType, DWORD dwStartType,
395 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
396 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
397 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
404 TRACE("(%u,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
406 r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL,
407 REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp);
408 if (r!=ERROR_SUCCESS)
410 if (dp != REG_CREATED_NEW_KEY)
415 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, strlen(lpDisplayName) );
416 if (r!=ERROR_SUCCESS)
420 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
421 if (r!=ERROR_SUCCESS)
424 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
425 if (r!=ERROR_SUCCESS)
428 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
429 (LPVOID)&dwErrorControl, sizeof (DWORD) );
430 if (r!=ERROR_SUCCESS)
435 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
436 lpBinaryPathName,strlen(lpBinaryPathName)+1 );
437 if (r!=ERROR_SUCCESS)
443 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
444 lpLoadOrderGroup, strlen(lpLoadOrderGroup)+1 );
445 if (r!=ERROR_SUCCESS)
449 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
450 (LPVOID)&dwErrorControl, sizeof (DWORD) );
451 if (r!=ERROR_SUCCESS)
458 /* determine the length of a double null terminated multi string */
460 len += (strlen(&lpDependencies[len])+1);
461 } while (lpDependencies[len++]);
463 /* fixme: this should be unicode */
464 r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ,
465 lpDependencies, len );
466 if (r!=ERROR_SUCCESS)
472 FIXME("Don't know how to add a Password for a service.\n");
475 if(lpServiceStartName)
477 FIXME("Don't know how to add a ServiceStartName for a service.\n");
484 /******************************************************************************
485 * DeleteService [ADVAPI32.31]
488 * hService [I] Handle to service
494 DeleteService( SC_HANDLE hService )
496 FIXME("(%d): stub\n",hService);
501 /******************************************************************************
502 * StartServiceA [ADVAPI32.195]
506 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
507 LPCSTR *lpServiceArgVectors )
512 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
515 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
516 dwNumServiceArgs*sizeof(LPWSTR) );
520 for(i=0; i<dwNumServiceArgs; i++)
521 lpwstr[i]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors[i]);
523 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
527 for(i=0; i<dwNumServiceArgs; i++)
528 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
529 HeapFree(GetProcessHeap(), 0, lpwstr);
536 /******************************************************************************
537 * StartServiceW [ADVAPI32.198]
541 * hService [I] Handle of service
542 * dwNumServiceArgs [I] Number of arguments
543 * lpServiceArgVectors [I] Address of array of argument string pointers
547 * NT implements this function using an obscure RPC call...
549 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
550 * to get things like %SystemRoot%\\System32\\service.exe to load.
552 * Will only work for shared address space. How should the service
553 * args be transferred when address spaces are separated?
555 * Can only start one service at a time.
557 * Has no concept of priviledge.
563 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
564 LPCWSTR *lpServiceArgVectors )
566 CHAR path[MAX_PATH],str[MAX_PATH];
570 PROCESS_INFORMATION procinfo;
571 STARTUPINFOA startupinfo;
573 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,
574 lpServiceArgVectors);
577 r = RegQueryValueExA(hService, "ImagePath", NULL, &type, (LPVOID)str, &size);
578 if (r!=ERROR_SUCCESS)
580 ExpandEnvironmentStringsA(str,path,sizeof path);
582 TRACE("Starting service %s\n", debugstr_a(path) );
584 data = CreateSemaphoreA(NULL,1,1,"ADVAPI32_ServiceStartData");
585 if(data == ERROR_INVALID_HANDLE)
587 data = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
590 ERR("Couldn't create data semaphore\n");
594 wait = CreateSemaphoreA(NULL,0,1,"ADVAPI32_WaitServiceStart");
596 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
599 ERR("Couldn't create wait semaphore\n");
605 * FIXME: lpServiceArgsVectors need to be stored and returned to
606 * the service when it calls StartServiceCtrlDispatcher
608 * Chuck these in a global (yuk) so we can pass them to
609 * another process - address space separation will break this.
612 r = WaitForSingleObject(data,INFINITE);
614 if( r == WAIT_FAILED)
617 start_dwNumServiceArgs = dwNumServiceArgs;
618 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
620 ZeroMemory(&startupinfo,sizeof(STARTUPINFOA));
621 startupinfo.cb = sizeof(STARTUPINFOA);
623 r = CreateProcessA(path,
625 NULL, /* process security attribs */
626 NULL, /* thread security attribs */
627 FALSE, /* inherit handles */
628 0, /* creation flags */
629 NULL, /* environment */
630 NULL, /* current directory */
631 &startupinfo, /* startup info */
632 &procinfo); /* process info */
636 ERR("Couldn't start process\n");
637 /* ReleaseSemaphore(data, 1, NULL);
641 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
642 r = WaitForSingleObject(wait,30000);
644 ReleaseSemaphore(data, 1, NULL);
646 if( r == WAIT_FAILED)
652 /******************************************************************************
653 * QueryServiceStatus [ADVAPI32.123]
661 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
664 DWORD type, val, size;
666 FIXME("(%x,%p) partial\n",hService,lpservicestatus);
668 /* read the service type from the registry */
670 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
673 ERR("invalid Type\n");
676 lpservicestatus->dwServiceType = val;
677 /* FIXME: how are these determined or read from the registry? */
678 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
679 lpservicestatus->dwCurrentState = 1;
680 lpservicestatus->dwControlsAccepted = 0;
681 lpservicestatus->dwWin32ExitCode = NO_ERROR;
682 lpservicestatus->dwServiceSpecificExitCode = 0;
683 lpservicestatus->dwCheckPoint = 0;
684 lpservicestatus->dwWaitHint = 0;