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.@]
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 * EnumServicesStatusW [ADVAPI32.@]
40 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
41 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
42 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
43 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
44 { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
45 dwServiceType, dwServiceState, lpServices, cbBufSize,
46 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
47 SetLastError (ERROR_ACCESS_DENIED);
51 /******************************************************************************
52 * StartServiceCtrlDispatcherA [ADVAPI32.196]
55 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
57 LPSERVICE_MAIN_FUNCTIONA fpMain;
59 DWORD dwNumServiceArgs ;
64 TRACE("(%p)\n", servent);
65 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
68 ERR("Couldn't find wait semaphore\n");
69 ERR("perhaps you need to start services using StartService\n");
73 dwNumServiceArgs = start_dwNumServiceArgs;
74 lpArgVecW = start_lpServiceArgVectors;
76 ReleaseSemaphore(wait, 1, NULL);
78 /* Convert the Unicode arg vectors back to ASCII */
80 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
81 dwNumServiceArgs*sizeof(LPSTR) );
85 for(i=0; i<dwNumServiceArgs; i++)
86 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
88 /* FIXME: should we blindly start all services? */
89 while (servent->lpServiceName) {
90 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
91 fpMain = servent->lpServiceProc;
93 /* try to start the service */
94 fpMain( dwNumServiceArgs, lpArgVecA);
101 /* free arg strings */
102 for(i=0; i<dwNumServiceArgs; i++)
103 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
104 HeapFree(GetProcessHeap(), 0, lpArgVecA);
110 /******************************************************************************
111 * StartServiceCtrlDispatcherW [ADVAPI32.197]
117 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
119 LPSERVICE_MAIN_FUNCTIONW fpMain;
121 DWORD dwNumServiceArgs ;
122 LPWSTR *lpServiceArgVectors ;
124 TRACE("(%p)\n", servent);
125 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
128 ERR("Couldn't find wait semaphore\n");
129 ERR("perhaps you need to start services using StartService\n");
133 dwNumServiceArgs = start_dwNumServiceArgs;
134 lpServiceArgVectors = start_lpServiceArgVectors;
136 ReleaseSemaphore(wait, 1, NULL);
138 /* FIXME: should we blindly start all services? */
139 while (servent->lpServiceName) {
140 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
141 fpMain = servent->lpServiceProc;
143 /* try to start the service */
144 fpMain( dwNumServiceArgs, lpServiceArgVectors);
152 /******************************************************************************
153 * RegisterServiceCtrlHandlerA [ADVAPI32.176]
155 SERVICE_STATUS_HANDLE WINAPI
156 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
157 LPHANDLER_FUNCTION lpfHandler )
158 { FIXME("%s %p\n", lpServiceName, lpfHandler);
162 /******************************************************************************
163 * RegisterServiceCtrlHandlerW [ADVAPI32.177]
169 SERVICE_STATUS_HANDLE WINAPI
170 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
171 LPHANDLER_FUNCTION lpfHandler )
172 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
176 /******************************************************************************
177 * SetServiceStatus [ADVAPI32.192]
184 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
185 { FIXME("%lx %p\n",hService, lpStatus);
186 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
187 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
188 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
189 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
190 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
191 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
192 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
196 /******************************************************************************
197 * OpenSCManagerA [ADVAPI32.110]
200 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
201 DWORD dwDesiredAccess )
203 LPWSTR lpMachineNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpMachineName);
204 LPWSTR lpDatabaseNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpDatabaseName);
205 DWORD ret = OpenSCManagerW(lpMachineNameW,lpDatabaseNameW,
207 HeapFree(GetProcessHeap(),0,lpDatabaseNameW);
208 HeapFree(GetProcessHeap(),0,lpMachineNameW);
212 /******************************************************************************
213 * OpenSCManagerW [ADVAPI32.111]
214 * Establishes a connection to the service control manager and opens database
217 * This should return a SC_HANDLE
220 * lpMachineName [I] Pointer to machine name string
221 * lpDatabaseName [I] Pointer to database name string
222 * dwDesiredAccess [I] Type of access
225 * Success: Handle to service control manager database
229 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
230 DWORD dwDesiredAccess )
235 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
236 debugstr_w(lpDatabaseName), dwDesiredAccess);
239 * FIXME: what is lpDatabaseName?
240 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
241 * docs, but what if it isn't?
244 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey);
245 if (r!=ERROR_SUCCESS)
248 TRACE("returning %x\n",hKey);
254 /******************************************************************************
255 * AllocateLocallyUniqueId [ADVAPI32.12]
261 AllocateLocallyUniqueId( PLUID lpluid )
263 lpluid->s.LowPart = time(NULL);
264 lpluid->s.HighPart = 0;
269 /******************************************************************************
270 * ControlService [ADVAPI32.23]
271 * Sends a control code to a Win32-based service.
281 ControlService( SC_HANDLE hService, DWORD dwControl,
282 LPSERVICE_STATUS lpServiceStatus )
284 FIXME("(%d,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
289 /******************************************************************************
290 * CloseServiceHandle [ADVAPI32.22]
291 * Close handle to service or service control manager
294 * hSCObject [I] Handle to service or service control manager database
299 CloseServiceHandle( SC_HANDLE hSCObject )
301 TRACE("(%x)\n", hSCObject);
303 RegCloseKey(hSCObject);
309 /******************************************************************************
310 * OpenServiceA [ADVAPI32.112]
313 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
314 DWORD dwDesiredAccess )
316 LPWSTR lpServiceNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName);
320 TRACE("Request for service %s\n",lpServiceName);
323 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
324 HeapFree(GetProcessHeap(),0,lpServiceNameW);
329 /******************************************************************************
330 * OpenServiceW [ADVAPI32.113]
331 * Opens a handle to an existing service
339 * Success: Handle to the service
343 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
344 DWORD dwDesiredAccess)
346 const char *str = "System\\CurrentControlSet\\Services\\";
347 WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */
351 TRACE("(%d,%p,%ld)\n",hSCManager, lpServiceName,
354 lstrcpyAtoW(lpServiceKey,str);
355 lstrcatW(lpServiceKey,lpServiceName);
357 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey));
359 /* FIXME: dwDesiredAccess may need some processing */
360 r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey );
361 if (r!=ERROR_SUCCESS)
364 TRACE("returning %x\n",hKey);
369 /******************************************************************************
370 * CreateServiceW [ADVAPI32.29]
373 CreateServiceW( DWORD hSCManager, LPCWSTR lpServiceName,
374 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
375 DWORD dwServiceType, DWORD dwStartType,
376 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
377 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
378 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
381 FIXME("(%ld,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
386 /******************************************************************************
387 * CreateServiceA [ADVAPI32.28]
390 CreateServiceA( DWORD hSCManager, LPCSTR lpServiceName,
391 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
392 DWORD dwServiceType, DWORD dwStartType,
393 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
394 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
395 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
402 TRACE("(%ld,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
404 r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL,
405 REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp);
406 if (r!=ERROR_SUCCESS)
408 if (dp != REG_CREATED_NEW_KEY)
413 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, lstrlenA(lpDisplayName) );
414 if (r!=ERROR_SUCCESS)
418 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
419 if (r!=ERROR_SUCCESS)
422 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
423 if (r!=ERROR_SUCCESS)
426 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
427 (LPVOID)&dwErrorControl, sizeof (DWORD) );
428 if (r!=ERROR_SUCCESS)
433 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
434 lpBinaryPathName,lstrlenA(lpBinaryPathName)+1 );
435 if (r!=ERROR_SUCCESS)
441 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
442 lpLoadOrderGroup, lstrlenA(lpLoadOrderGroup)+1 );
443 if (r!=ERROR_SUCCESS)
447 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
448 (LPVOID)&dwErrorControl, sizeof (DWORD) );
449 if (r!=ERROR_SUCCESS)
456 /* determine the length of a double null terminated multi string */
458 len += (lstrlenA(&lpDependencies[len])+1);
459 } while (lpDependencies[len++]);
461 /* fixme: this should be unicode */
462 r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ,
463 lpDependencies, len );
464 if (r!=ERROR_SUCCESS)
470 FIXME("Don't know how to add a Password for a service.\n");
473 if(lpServiceStartName)
475 FIXME("Don't know how to add a ServiceStartName for a service.\n");
482 /******************************************************************************
483 * DeleteService [ADVAPI32.31]
486 * hService [I] Handle to service
492 DeleteService( SC_HANDLE hService )
494 FIXME("(%d): stub\n",hService);
499 /******************************************************************************
500 * StartServiceA [ADVAPI32.195]
504 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
505 LPCSTR *lpServiceArgVectors )
510 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
513 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
514 dwNumServiceArgs*sizeof(LPWSTR) );
518 for(i=0; i<dwNumServiceArgs; i++)
519 lpwstr[i]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors[i]);
521 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
525 for(i=0; i<dwNumServiceArgs; i++)
526 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
527 HeapFree(GetProcessHeap(), 0, lpwstr);
534 /******************************************************************************
535 * StartServiceW [ADVAPI32.198]
539 * hService [I] Handle of service
540 * dwNumServiceArgs [I] Number of arguments
541 * lpServiceArgVectors [I] Address of array of argument string pointers
545 * NT implements this function using an obscure RPC call...
547 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
548 * to get things like %SystemRoot%\\System32\\service.exe to load.
550 * Will only work for shared address space. How should the service
551 * args be transferred when address spaces are separated?
553 * Can only start one service at a time.
555 * Has no concept of priviledge.
561 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
562 LPCWSTR *lpServiceArgVectors )
564 CHAR path[MAX_PATH],str[MAX_PATH];
568 PROCESS_INFORMATION procinfo;
569 STARTUPINFOA startupinfo;
571 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,
572 lpServiceArgVectors);
575 r = RegQueryValueExA(hService, "ImagePath", NULL, &type, (LPVOID)str, &size);
576 if (r!=ERROR_SUCCESS)
578 ExpandEnvironmentStringsA(str,path,sizeof path);
580 TRACE("Starting service %s\n", debugstr_a(path) );
582 data = CreateSemaphoreA(NULL,1,1,"ADVAPI32_ServiceStartData");
583 if(data == ERROR_INVALID_HANDLE)
585 data = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
588 ERR("Couldn't create data semaphore\n");
592 wait = CreateSemaphoreA(NULL,0,1,"ADVAPI32_WaitServiceStart");
594 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
597 ERR("Couldn't create wait semaphore\n");
603 * FIXME: lpServiceArgsVectors need to be stored and returned to
604 * the service when it calls StartServiceCtrlDispatcher
606 * Chuck these in a global (yuk) so we can pass them to
607 * another process - address space separation will break this.
610 r = WaitForSingleObject(data,INFINITE);
612 if( r == WAIT_FAILED)
615 start_dwNumServiceArgs = dwNumServiceArgs;
616 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
618 ZeroMemory(&startupinfo,sizeof(STARTUPINFOA));
619 startupinfo.cb = sizeof(STARTUPINFOA);
621 r = CreateProcessA(path,
623 NULL, /* process security attribs */
624 NULL, /* thread security attribs */
625 FALSE, /* inherit handles */
626 0, /* creation flags */
627 NULL, /* environment */
628 NULL, /* current directory */
629 &startupinfo, /* startup info */
630 &procinfo); /* process info */
634 ERR("Couldn't start process\n");
635 /* ReleaseSemaphore(data, 1, NULL);
639 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
640 r = WaitForSingleObject(wait,30000);
642 ReleaseSemaphore(data, 1, NULL);
644 if( r == WAIT_FAILED)
650 /******************************************************************************
651 * QueryServiceStatus [ADVAPI32.123]
659 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
662 DWORD type, val, size;
664 FIXME("(%x,%p) partial\n",hService,lpservicestatus);
666 /* read the service type from the registry */
668 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
671 ERR("invalid Type\n");
674 lpservicestatus->dwServiceType = val;
675 /* FIXME: how are these determined or read from the registry? */
676 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
677 lpservicestatus->dwCurrentState = 1;
678 lpservicestatus->dwControlsAccepted = 0;
679 lpservicestatus->dwWin32ExitCode = NO_ERROR;
680 lpservicestatus->dwServiceSpecificExitCode = 0;
681 lpservicestatus->dwCheckPoint = 0;
682 lpservicestatus->dwWaitHint = 0;