2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
14 #include "debugtools.h"
16 DEFAULT_DEBUG_CHANNEL(advapi)
18 static DWORD start_dwNumServiceArgs;
19 static LPWSTR *start_lpServiceArgVectors;
21 /******************************************************************************
22 * EnumServicesStatusA [ADVAPI32.38]
25 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
26 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
27 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
28 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
29 { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
30 dwServiceType, dwServiceState, lpServices, cbBufSize,
31 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
32 SetLastError (ERROR_ACCESS_DENIED);
36 /******************************************************************************
37 * StartServiceCtrlDispatcherA [ADVAPI32.196]
40 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
42 LPSERVICE_MAIN_FUNCTIONA fpMain;
44 DWORD dwNumServiceArgs ;
49 TRACE("(%p)\n", servent);
50 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
53 ERR("Couldn't find wait semaphore\n");
54 ERR("perhaps you need to start services using StartService\n");
58 dwNumServiceArgs = start_dwNumServiceArgs;
59 lpArgVecW = start_lpServiceArgVectors;
61 ReleaseSemaphore(wait, 1, NULL);
63 /* Convert the Unicode arg vectors back to ASCII */
65 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
66 dwNumServiceArgs*sizeof(LPSTR) );
70 for(i=0; i<dwNumServiceArgs; i++)
71 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
73 /* FIXME: should we blindly start all services? */
74 while (servent->lpServiceName) {
75 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
76 fpMain = servent->lpServiceProc;
78 /* try to start the service */
79 fpMain( dwNumServiceArgs, lpArgVecA);
86 /* free arg strings */
87 for(i=0; i<dwNumServiceArgs; i++)
88 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
89 HeapFree(GetProcessHeap(), 0, lpArgVecA);
95 /******************************************************************************
96 * StartServiceCtrlDispatcherW [ADVAPI32.197]
102 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
104 LPSERVICE_MAIN_FUNCTIONW fpMain;
106 DWORD dwNumServiceArgs ;
107 LPWSTR *lpServiceArgVectors ;
109 TRACE("(%p)\n", servent);
110 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
113 ERR("Couldn't find wait semaphore\n");
114 ERR("perhaps you need to start services using StartService\n");
118 dwNumServiceArgs = start_dwNumServiceArgs;
119 lpServiceArgVectors = start_lpServiceArgVectors;
121 ReleaseSemaphore(wait, 1, NULL);
123 /* FIXME: should we blindly start all services? */
124 while (servent->lpServiceName) {
125 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
126 fpMain = servent->lpServiceProc;
128 /* try to start the service */
129 fpMain( dwNumServiceArgs, lpServiceArgVectors);
137 /******************************************************************************
138 * RegisterServiceCtrlHandlerA [ADVAPI32.176]
140 SERVICE_STATUS_HANDLE WINAPI
141 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
142 LPHANDLER_FUNCTION lpfHandler )
143 { FIXME("%s %p\n", lpServiceName, lpfHandler);
147 /******************************************************************************
148 * RegisterServiceCtrlHandlerW [ADVAPI32.177]
154 SERVICE_STATUS_HANDLE WINAPI
155 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
156 LPHANDLER_FUNCTION lpfHandler )
157 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
161 /******************************************************************************
162 * SetServiceStatus [ADVAPI32.192]
169 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
170 { FIXME("%lx %p\n",hService, lpStatus);
171 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
172 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
173 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
174 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
175 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
176 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
177 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
181 /******************************************************************************
182 * OpenSCManagerA [ADVAPI32.110]
185 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
186 DWORD dwDesiredAccess )
188 LPWSTR lpMachineNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpMachineName);
189 LPWSTR lpDatabaseNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpDatabaseName);
190 DWORD ret = OpenSCManagerW(lpMachineNameW,lpDatabaseNameW,
192 HeapFree(GetProcessHeap(),0,lpDatabaseNameW);
193 HeapFree(GetProcessHeap(),0,lpMachineNameW);
197 /******************************************************************************
198 * OpenSCManagerW [ADVAPI32.111]
199 * Establishes a connection to the service control manager and opens database
202 * This should return a SC_HANDLE
205 * lpMachineName [I] Pointer to machine name string
206 * lpDatabaseName [I] Pointer to database name string
207 * dwDesiredAccess [I] Type of access
210 * Success: Handle to service control manager database
214 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
215 DWORD dwDesiredAccess )
220 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
221 debugstr_w(lpDatabaseName), dwDesiredAccess);
224 * FIXME: what is lpDatabaseName?
225 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
226 * docs, but what if it isn't?
229 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey);
230 if (r!=ERROR_SUCCESS)
233 TRACE("returning %x\n",hKey);
239 /******************************************************************************
240 * AllocateLocallyUniqueId [ADVAPI32.12]
246 AllocateLocallyUniqueId( PLUID lpluid )
248 lpluid->s.LowPart = time(NULL);
249 lpluid->s.HighPart = 0;
254 /******************************************************************************
255 * ControlService [ADVAPI32.23]
256 * Sends a control code to a Win32-based service.
266 ControlService( SC_HANDLE hService, DWORD dwControl,
267 LPSERVICE_STATUS lpServiceStatus )
269 FIXME("(%d,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
274 /******************************************************************************
275 * CloseServiceHandle [ADVAPI32.22]
276 * Close handle to service or service control manager
279 * hSCObject [I] Handle to service or service control manager database
284 CloseServiceHandle( SC_HANDLE hSCObject )
286 TRACE("(%x)\n", hSCObject);
288 RegCloseKey(hSCObject);
294 /******************************************************************************
295 * OpenServiceA [ADVAPI32.112]
298 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
299 DWORD dwDesiredAccess )
301 LPWSTR lpServiceNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName);
305 TRACE("Request for service %s\n",lpServiceName);
308 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
309 HeapFree(GetProcessHeap(),0,lpServiceNameW);
314 /******************************************************************************
315 * OpenServiceW [ADVAPI32.113]
316 * Opens a handle to an existing service
324 * Success: Handle to the service
328 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
329 DWORD dwDesiredAccess)
331 const char *str = "System\\CurrentControlSet\\Services\\";
332 WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */
336 TRACE("(%d,%p,%ld)\n",hSCManager, lpServiceName,
339 lstrcpyAtoW(lpServiceKey,str);
340 lstrcatW(lpServiceKey,lpServiceName);
342 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey));
344 /* FIXME: dwDesiredAccess may need some processing */
345 r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey );
346 if (r!=ERROR_SUCCESS)
349 TRACE("returning %x\n",hKey);
354 /******************************************************************************
355 * CreateServiceW [ADVAPI32.29]
358 CreateServiceW( DWORD hSCManager, LPCWSTR lpServiceName,
359 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
360 DWORD dwServiceType, DWORD dwStartType,
361 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
362 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
363 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
366 FIXME("(%ld,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
371 /******************************************************************************
372 * CreateServiceA [ADVAPI32.28]
375 CreateServiceA( DWORD hSCManager, LPCSTR lpServiceName,
376 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
377 DWORD dwServiceType, DWORD dwStartType,
378 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
379 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
380 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
387 TRACE("(%ld,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
389 r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL,
390 REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp);
391 if (r!=ERROR_SUCCESS)
393 if (dp != REG_CREATED_NEW_KEY)
398 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, lstrlenA(lpDisplayName) );
399 if (r!=ERROR_SUCCESS)
403 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
404 if (r!=ERROR_SUCCESS)
407 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
408 if (r!=ERROR_SUCCESS)
411 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
412 (LPVOID)&dwErrorControl, sizeof (DWORD) );
413 if (r!=ERROR_SUCCESS)
418 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
419 lpBinaryPathName,lstrlenA(lpBinaryPathName)+1 );
420 if (r!=ERROR_SUCCESS)
426 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
427 lpLoadOrderGroup, lstrlenA(lpLoadOrderGroup)+1 );
428 if (r!=ERROR_SUCCESS)
432 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
433 (LPVOID)&dwErrorControl, sizeof (DWORD) );
434 if (r!=ERROR_SUCCESS)
441 /* determine the length of a double null terminated multi string */
443 len += (lstrlenA(&lpDependencies[len])+1);
444 } while (lpDependencies[len++]);
446 /* fixme: this should be unicode */
447 r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ,
448 lpDependencies, len );
449 if (r!=ERROR_SUCCESS)
455 FIXME("Don't know how to add a Password for a service.\n");
458 if(lpServiceStartName)
460 FIXME("Don't know how to add a ServiceStartName for a service.\n");
467 /******************************************************************************
468 * DeleteService [ADVAPI32.31]
471 * hService [I] Handle to service
477 DeleteService( SC_HANDLE hService )
479 FIXME("(%d): stub\n",hService);
484 /******************************************************************************
485 * StartServiceA [ADVAPI32.195]
489 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
490 LPCSTR *lpServiceArgVectors )
495 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
498 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
499 dwNumServiceArgs*sizeof(LPWSTR) );
503 for(i=0; i<dwNumServiceArgs; i++)
504 lpwstr[i]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors[i]);
506 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
510 for(i=0; i<dwNumServiceArgs; i++)
511 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
512 HeapFree(GetProcessHeap(), 0, lpwstr);
519 /******************************************************************************
520 * StartServiceW [ADVAPI32.198]
524 * hService [I] Handle of service
525 * dwNumServiceArgs [I] Number of arguments
526 * lpServiceArgVectors [I] Address of array of argument string pointers
530 * NT implements this function using an obscure RPC call...
532 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
533 * to get things like %SystemRoot%\\System32\\service.exe to load.
535 * Will only work for shared address space. How should the service
536 * args be transferred when address spaces are separated?
538 * Can only start one service at a time.
540 * Has no concept of priviledge.
546 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
547 LPCWSTR *lpServiceArgVectors )
549 CHAR path[MAX_PATH],str[MAX_PATH];
553 PROCESS_INFORMATION procinfo;
554 STARTUPINFOA startupinfo;
556 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,
557 lpServiceArgVectors);
560 r = RegQueryValueExA(hService, "ImagePath", NULL, &type, (LPVOID)str, &size);
561 if (r!=ERROR_SUCCESS)
563 ExpandEnvironmentStringsA(str,path,sizeof path);
565 TRACE("Starting service %s\n", debugstr_a(path) );
567 data = CreateSemaphoreA(NULL,1,1,"ADVAPI32_ServiceStartData");
568 if(data == ERROR_INVALID_HANDLE)
570 data = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
573 ERR("Couldn't create data semaphore\n");
577 wait = CreateSemaphoreA(NULL,0,1,"ADVAPI32_WaitServiceStart");
579 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
582 ERR("Couldn't create wait semaphore\n");
588 * FIXME: lpServiceArgsVectors need to be stored and returned to
589 * the service when it calls StartServiceCtrlDispatcher
591 * Chuck these in a global (yuk) so we can pass them to
592 * another process - address space separation will break this.
595 r = WaitForSingleObject(data,INFINITE);
597 if( r == WAIT_FAILED)
600 start_dwNumServiceArgs = dwNumServiceArgs;
601 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
603 ZeroMemory(&startupinfo,sizeof(STARTUPINFOA));
604 startupinfo.cb = sizeof(STARTUPINFOA);
606 r = CreateProcessA(path,
608 NULL, /* process security attribs */
609 NULL, /* thread security attribs */
610 FALSE, /* inherit handles */
611 0, /* creation flags */
612 NULL, /* environment */
613 NULL, /* current directory */
614 &startupinfo, /* startup info */
615 &procinfo); /* process info */
619 ERR("Couldn't start process\n");
620 /* ReleaseSemaphore(data, 1, NULL);
624 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
625 r = WaitForSingleObject(wait,30000);
627 ReleaseSemaphore(data, 1, NULL);
629 if( r == WAIT_FAILED)
635 /******************************************************************************
636 * QueryServiceStatus [ADVAPI32.123]
644 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
647 DWORD type, val, size;
649 FIXME("(%x,%p) partial\n",hService,lpservicestatus);
651 /* read the service type from the registry */
653 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
656 ERR("invalid Type\n");
659 lpservicestatus->dwServiceType = val;
660 /* FIXME: how are these determined or read from the registry? */
661 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
662 lpservicestatus->dwCurrentState = 1;
663 lpservicestatus->dwControlsAccepted = 0;
664 lpservicestatus->dwWin32ExitCode = NO_ERROR;
665 lpservicestatus->dwServiceSpecificExitCode = 0;
666 lpservicestatus->dwCheckPoint = 0;
667 lpservicestatus->dwWaitHint = 0;