2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
13 #include "wine/unicode.h"
15 #include "debugtools.h"
17 DEFAULT_DEBUG_CHANNEL(advapi);
19 static DWORD start_dwNumServiceArgs;
20 static LPWSTR *start_lpServiceArgVectors;
22 /******************************************************************************
23 * EnumServicesStatusA [ADVAPI32.@]
26 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
27 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
28 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
29 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
30 { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
31 dwServiceType, dwServiceState, lpServices, cbBufSize,
32 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
33 SetLastError (ERROR_ACCESS_DENIED);
37 /******************************************************************************
38 * EnumServicesStatusW [ADVAPI32.@]
41 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
42 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
43 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
44 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
45 { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
46 dwServiceType, dwServiceState, lpServices, cbBufSize,
47 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
48 SetLastError (ERROR_ACCESS_DENIED);
52 /******************************************************************************
53 * StartServiceCtrlDispatcherA [ADVAPI32.196]
56 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
58 LPSERVICE_MAIN_FUNCTIONA fpMain;
60 DWORD dwNumServiceArgs ;
65 TRACE("(%p)\n", servent);
66 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
69 ERR("Couldn't find wait semaphore\n");
70 ERR("perhaps you need to start services using StartService\n");
74 dwNumServiceArgs = start_dwNumServiceArgs;
75 lpArgVecW = start_lpServiceArgVectors;
77 ReleaseSemaphore(wait, 1, NULL);
79 /* Convert the Unicode arg vectors back to ASCII */
81 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
82 dwNumServiceArgs*sizeof(LPSTR) );
86 for(i=0; i<dwNumServiceArgs; i++)
87 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
89 /* FIXME: should we blindly start all services? */
90 while (servent->lpServiceName) {
91 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
92 fpMain = servent->lpServiceProc;
94 /* try to start the service */
95 fpMain( dwNumServiceArgs, lpArgVecA);
102 /* free arg strings */
103 for(i=0; i<dwNumServiceArgs; i++)
104 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
105 HeapFree(GetProcessHeap(), 0, lpArgVecA);
111 /******************************************************************************
112 * StartServiceCtrlDispatcherW [ADVAPI32.197]
118 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
120 LPSERVICE_MAIN_FUNCTIONW fpMain;
122 DWORD dwNumServiceArgs ;
123 LPWSTR *lpServiceArgVectors ;
125 TRACE("(%p)\n", servent);
126 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
129 ERR("Couldn't find wait semaphore\n");
130 ERR("perhaps you need to start services using StartService\n");
134 dwNumServiceArgs = start_dwNumServiceArgs;
135 lpServiceArgVectors = start_lpServiceArgVectors;
137 ReleaseSemaphore(wait, 1, NULL);
139 /* FIXME: should we blindly start all services? */
140 while (servent->lpServiceName) {
141 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
142 fpMain = servent->lpServiceProc;
144 /* try to start the service */
145 fpMain( dwNumServiceArgs, lpServiceArgVectors);
153 /******************************************************************************
154 * RegisterServiceCtrlHandlerA [ADVAPI32.176]
156 SERVICE_STATUS_HANDLE WINAPI
157 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
158 LPHANDLER_FUNCTION lpfHandler )
159 { FIXME("%s %p\n", lpServiceName, lpfHandler);
163 /******************************************************************************
164 * RegisterServiceCtrlHandlerW [ADVAPI32.177]
170 SERVICE_STATUS_HANDLE WINAPI
171 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
172 LPHANDLER_FUNCTION lpfHandler )
173 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
177 /******************************************************************************
178 * SetServiceStatus [ADVAPI32.192]
185 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
186 { FIXME("%x %p\n",hService, lpStatus);
187 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
188 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
189 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
190 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
191 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
192 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
193 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
197 /******************************************************************************
198 * OpenSCManagerA [ADVAPI32.110]
201 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
202 DWORD dwDesiredAccess )
204 LPWSTR lpMachineNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpMachineName);
205 LPWSTR lpDatabaseNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpDatabaseName);
206 DWORD ret = OpenSCManagerW(lpMachineNameW,lpDatabaseNameW,
208 HeapFree(GetProcessHeap(),0,lpDatabaseNameW);
209 HeapFree(GetProcessHeap(),0,lpMachineNameW);
213 /******************************************************************************
214 * OpenSCManagerW [ADVAPI32.111]
215 * Establishes a connection to the service control manager and opens database
218 * This should return a SC_HANDLE
221 * lpMachineName [I] Pointer to machine name string
222 * lpDatabaseName [I] Pointer to database name string
223 * dwDesiredAccess [I] Type of access
226 * Success: Handle to service control manager database
230 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
231 DWORD dwDesiredAccess )
236 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
237 debugstr_w(lpDatabaseName), dwDesiredAccess);
240 * FIXME: what is lpDatabaseName?
241 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
242 * docs, but what if it isn't?
245 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey);
246 if (r!=ERROR_SUCCESS)
249 TRACE("returning %x\n",hKey);
255 /******************************************************************************
256 * AllocateLocallyUniqueId [ADVAPI32.12]
262 AllocateLocallyUniqueId( PLUID lpluid )
264 lpluid->s.LowPart = time(NULL);
265 lpluid->s.HighPart = 0;
270 /******************************************************************************
271 * ControlService [ADVAPI32.23]
272 * Sends a control code to a Win32-based service.
282 ControlService( SC_HANDLE hService, DWORD dwControl,
283 LPSERVICE_STATUS lpServiceStatus )
285 FIXME("(%d,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
290 /******************************************************************************
291 * CloseServiceHandle [ADVAPI32.22]
292 * Close handle to service or service control manager
295 * hSCObject [I] Handle to service or service control manager database
300 CloseServiceHandle( SC_HANDLE hSCObject )
302 TRACE("(%x)\n", hSCObject);
304 RegCloseKey(hSCObject);
310 /******************************************************************************
311 * OpenServiceA [ADVAPI32.112]
314 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
315 DWORD dwDesiredAccess )
317 LPWSTR lpServiceNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName);
321 TRACE("Request for service %s\n",lpServiceName);
324 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
325 HeapFree(GetProcessHeap(),0,lpServiceNameW);
330 /******************************************************************************
331 * OpenServiceW [ADVAPI32.113]
332 * Opens a handle to an existing service
340 * Success: Handle to the service
344 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
345 DWORD dwDesiredAccess)
347 const char *str = "System\\CurrentControlSet\\Services\\";
348 WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */
352 TRACE("(%d,%p,%ld)\n",hSCManager, lpServiceName,
355 lstrcpyAtoW(lpServiceKey,str);
356 strcatW(lpServiceKey,lpServiceName);
358 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey));
360 /* FIXME: dwDesiredAccess may need some processing */
361 r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey );
362 if (r!=ERROR_SUCCESS)
365 TRACE("returning %x\n",hKey);
370 /******************************************************************************
371 * CreateServiceW [ADVAPI32.29]
374 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
375 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
376 DWORD dwServiceType, DWORD dwStartType,
377 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
378 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
379 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
382 FIXME("(%u,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
387 /******************************************************************************
388 * CreateServiceA [ADVAPI32.28]
391 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
392 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
393 DWORD dwServiceType, DWORD dwStartType,
394 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
395 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
396 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
403 TRACE("(%u,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
405 r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL,
406 REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp);
407 if (r!=ERROR_SUCCESS)
409 if (dp != REG_CREATED_NEW_KEY)
414 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, strlen(lpDisplayName) );
415 if (r!=ERROR_SUCCESS)
419 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
420 if (r!=ERROR_SUCCESS)
423 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
424 if (r!=ERROR_SUCCESS)
427 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
428 (LPVOID)&dwErrorControl, sizeof (DWORD) );
429 if (r!=ERROR_SUCCESS)
434 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
435 lpBinaryPathName,strlen(lpBinaryPathName)+1 );
436 if (r!=ERROR_SUCCESS)
442 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
443 lpLoadOrderGroup, strlen(lpLoadOrderGroup)+1 );
444 if (r!=ERROR_SUCCESS)
448 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
449 (LPVOID)&dwErrorControl, sizeof (DWORD) );
450 if (r!=ERROR_SUCCESS)
457 /* determine the length of a double null terminated multi string */
459 len += (strlen(&lpDependencies[len])+1);
460 } while (lpDependencies[len++]);
462 /* fixme: this should be unicode */
463 r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ,
464 lpDependencies, len );
465 if (r!=ERROR_SUCCESS)
471 FIXME("Don't know how to add a Password for a service.\n");
474 if(lpServiceStartName)
476 FIXME("Don't know how to add a ServiceStartName for a service.\n");
483 /******************************************************************************
484 * DeleteService [ADVAPI32.31]
487 * hService [I] Handle to service
493 DeleteService( SC_HANDLE hService )
495 FIXME("(%d): stub\n",hService);
500 /******************************************************************************
501 * StartServiceA [ADVAPI32.195]
505 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
506 LPCSTR *lpServiceArgVectors )
511 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
514 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
515 dwNumServiceArgs*sizeof(LPWSTR) );
519 for(i=0; i<dwNumServiceArgs; i++)
520 lpwstr[i]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors[i]);
522 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
526 for(i=0; i<dwNumServiceArgs; i++)
527 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
528 HeapFree(GetProcessHeap(), 0, lpwstr);
535 /******************************************************************************
536 * StartServiceW [ADVAPI32.198]
540 * hService [I] Handle of service
541 * dwNumServiceArgs [I] Number of arguments
542 * lpServiceArgVectors [I] Address of array of argument string pointers
546 * NT implements this function using an obscure RPC call...
548 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
549 * to get things like %SystemRoot%\\System32\\service.exe to load.
551 * Will only work for shared address space. How should the service
552 * args be transferred when address spaces are separated?
554 * Can only start one service at a time.
556 * Has no concept of priviledge.
562 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
563 LPCWSTR *lpServiceArgVectors )
565 CHAR path[MAX_PATH],str[MAX_PATH];
569 PROCESS_INFORMATION procinfo;
570 STARTUPINFOA startupinfo;
572 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,
573 lpServiceArgVectors);
576 r = RegQueryValueExA(hService, "ImagePath", NULL, &type, (LPVOID)str, &size);
577 if (r!=ERROR_SUCCESS)
579 ExpandEnvironmentStringsA(str,path,sizeof path);
581 TRACE("Starting service %s\n", debugstr_a(path) );
583 data = CreateSemaphoreA(NULL,1,1,"ADVAPI32_ServiceStartData");
584 if(data == ERROR_INVALID_HANDLE)
586 data = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
589 ERR("Couldn't create data semaphore\n");
593 wait = CreateSemaphoreA(NULL,0,1,"ADVAPI32_WaitServiceStart");
595 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
598 ERR("Couldn't create wait semaphore\n");
604 * FIXME: lpServiceArgsVectors need to be stored and returned to
605 * the service when it calls StartServiceCtrlDispatcher
607 * Chuck these in a global (yuk) so we can pass them to
608 * another process - address space separation will break this.
611 r = WaitForSingleObject(data,INFINITE);
613 if( r == WAIT_FAILED)
616 start_dwNumServiceArgs = dwNumServiceArgs;
617 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
619 ZeroMemory(&startupinfo,sizeof(STARTUPINFOA));
620 startupinfo.cb = sizeof(STARTUPINFOA);
622 r = CreateProcessA(path,
624 NULL, /* process security attribs */
625 NULL, /* thread security attribs */
626 FALSE, /* inherit handles */
627 0, /* creation flags */
628 NULL, /* environment */
629 NULL, /* current directory */
630 &startupinfo, /* startup info */
631 &procinfo); /* process info */
635 ERR("Couldn't start process\n");
636 /* ReleaseSemaphore(data, 1, NULL);
640 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
641 r = WaitForSingleObject(wait,30000);
643 ReleaseSemaphore(data, 1, NULL);
645 if( r == WAIT_FAILED)
651 /******************************************************************************
652 * QueryServiceStatus [ADVAPI32.123]
660 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
663 DWORD type, val, size;
665 FIXME("(%x,%p) partial\n",hService,lpservicestatus);
667 /* read the service type from the registry */
669 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
672 ERR("invalid Type\n");
675 lpservicestatus->dwServiceType = val;
676 /* FIXME: how are these determined or read from the registry? */
677 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
678 lpservicestatus->dwCurrentState = 1;
679 lpservicestatus->dwControlsAccepted = 0;
680 lpservicestatus->dwWin32ExitCode = NO_ERROR;
681 lpservicestatus->dwServiceSpecificExitCode = 0;
682 lpservicestatus->dwCheckPoint = 0;
683 lpservicestatus->dwWaitHint = 0;