2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "wine/unicode.h"
30 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
35 static DWORD start_dwNumServiceArgs;
36 static LPWSTR *start_lpServiceArgVectors;
38 /******************************************************************************
39 * EnumServicesStatusA [ADVAPI32.@]
42 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
43 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
44 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
45 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
46 { FIXME("%p 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 * EnumServicesStatusW [ADVAPI32.@]
57 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
58 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
59 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
60 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
61 { FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
62 dwServiceType, dwServiceState, lpServices, cbBufSize,
63 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
64 SetLastError (ERROR_ACCESS_DENIED);
68 /******************************************************************************
69 * StartServiceCtrlDispatcherA [ADVAPI32.@]
72 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
74 LPSERVICE_MAIN_FUNCTIONA fpMain;
76 DWORD dwNumServiceArgs ;
81 TRACE("(%p)\n", servent);
82 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
85 ERR("Couldn't find wait semaphore\n");
86 ERR("perhaps you need to start services using StartService\n");
90 dwNumServiceArgs = start_dwNumServiceArgs;
91 lpArgVecW = start_lpServiceArgVectors;
93 ReleaseSemaphore(wait, 1, NULL);
95 /* Convert the Unicode arg vectors back to ASCII */
97 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
98 dwNumServiceArgs*sizeof(LPSTR) );
102 for(i=0; i<dwNumServiceArgs; i++)
103 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
105 /* FIXME: should we blindly start all services? */
106 while (servent->lpServiceName) {
107 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
108 fpMain = servent->lpServiceProc;
110 /* try to start the service */
111 fpMain( dwNumServiceArgs, lpArgVecA);
118 /* free arg strings */
119 for(i=0; i<dwNumServiceArgs; i++)
120 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
121 HeapFree(GetProcessHeap(), 0, lpArgVecA);
127 /******************************************************************************
128 * StartServiceCtrlDispatcherW [ADVAPI32.@]
134 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
136 LPSERVICE_MAIN_FUNCTIONW fpMain;
138 DWORD dwNumServiceArgs ;
139 LPWSTR *lpServiceArgVectors ;
141 TRACE("(%p)\n", servent);
142 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
145 ERR("Couldn't find wait semaphore\n");
146 ERR("perhaps you need to start services using StartService\n");
150 dwNumServiceArgs = start_dwNumServiceArgs;
151 lpServiceArgVectors = start_lpServiceArgVectors;
153 ReleaseSemaphore(wait, 1, NULL);
155 /* FIXME: should we blindly start all services? */
156 while (servent->lpServiceName) {
157 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
158 fpMain = servent->lpServiceProc;
160 /* try to start the service */
161 fpMain( dwNumServiceArgs, lpServiceArgVectors);
169 /******************************************************************************
170 * LockServiceDatabase [ADVAPI32.@]
172 LPVOID WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
174 FIXME("%p\n",hSCManager);
175 return (SC_HANDLE)0xcacacafe;
178 /******************************************************************************
179 * UnlockServiceDatabase [ADVAPI32.@]
181 BOOL WINAPI UnlockServiceDatabase (LPVOID ScLock)
183 FIXME(": %p\n",ScLock);
187 /******************************************************************************
188 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
190 SERVICE_STATUS_HANDLE WINAPI
191 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
192 LPHANDLER_FUNCTION lpfHandler )
193 { FIXME("%s %p\n", lpServiceName, lpfHandler);
197 /******************************************************************************
198 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
204 SERVICE_STATUS_HANDLE WINAPI
205 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
206 LPHANDLER_FUNCTION lpfHandler )
207 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
211 /******************************************************************************
212 * SetServiceStatus [ADVAPI32.@]
219 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
220 { FIXME("0x%lx %p\n",hService, lpStatus);
221 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
222 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
223 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
224 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
225 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
226 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
227 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
231 /******************************************************************************
232 * OpenSCManagerA [ADVAPI32.@]
235 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
236 DWORD dwDesiredAccess )
238 UNICODE_STRING lpMachineNameW;
239 UNICODE_STRING lpDatabaseNameW;
242 RtlCreateUnicodeStringFromAsciiz (&lpMachineNameW,lpMachineName);
243 RtlCreateUnicodeStringFromAsciiz (&lpDatabaseNameW,lpDatabaseName);
244 ret = OpenSCManagerW(lpMachineNameW.Buffer,lpDatabaseNameW.Buffer, dwDesiredAccess);
245 RtlFreeUnicodeString(&lpDatabaseNameW);
246 RtlFreeUnicodeString(&lpMachineNameW);
250 /******************************************************************************
251 * OpenSCManagerW [ADVAPI32.@]
252 * Establishes a connection to the service control manager and opens database
255 * This should return a SC_HANDLE
258 * lpMachineName [I] Pointer to machine name string
259 * lpDatabaseName [I] Pointer to database name string
260 * dwDesiredAccess [I] Type of access
263 * Success: Handle to service control manager database
267 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
268 DWORD dwDesiredAccess )
273 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
274 debugstr_w(lpDatabaseName), dwDesiredAccess);
277 * FIXME: what is lpDatabaseName?
278 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
279 * docs, but what if it isn't?
282 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey);
283 if (r!=ERROR_SUCCESS)
286 TRACE("returning %p\n",hKey);
292 /******************************************************************************
293 * AllocateLocallyUniqueId [ADVAPI32.@]
299 AllocateLocallyUniqueId( PLUID lpluid )
301 lpluid->LowPart = time(NULL);
302 lpluid->HighPart = 0;
307 /******************************************************************************
308 * ControlService [ADVAPI32.@]
309 * Sends a control code to a Win32-based service.
319 ControlService( SC_HANDLE hService, DWORD dwControl,
320 LPSERVICE_STATUS lpServiceStatus )
322 FIXME("(%p,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
327 /******************************************************************************
328 * CloseServiceHandle [ADVAPI32.@]
329 * Close handle to service or service control manager
332 * hSCObject [I] Handle to service or service control manager database
337 CloseServiceHandle( SC_HANDLE hSCObject )
339 TRACE("(%p)\n", hSCObject);
341 RegCloseKey(hSCObject);
347 /******************************************************************************
348 * OpenServiceA [ADVAPI32.@]
351 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
352 DWORD dwDesiredAccess )
354 UNICODE_STRING lpServiceNameW;
356 RtlCreateUnicodeStringFromAsciiz (&lpServiceNameW,lpServiceName);
358 TRACE("Request for service %s\n",lpServiceName);
361 ret = OpenServiceW( hSCManager, lpServiceNameW.Buffer, dwDesiredAccess);
362 RtlFreeUnicodeString(&lpServiceNameW);
367 /******************************************************************************
368 * OpenServiceW [ADVAPI32.@]
369 * Opens a handle to an existing service
377 * Success: Handle to the service
381 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
382 DWORD dwDesiredAccess)
384 const char *str = "System\\CurrentControlSet\\Services\\";
385 WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */
389 TRACE("(%p,%p,%ld)\n",hSCManager, lpServiceName,
392 MultiByteToWideChar( CP_ACP, 0, str, -1, lpServiceKey, sizeof(lpServiceKey)/sizeof(WCHAR) );
393 strcatW(lpServiceKey,lpServiceName);
395 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey));
397 /* FIXME: dwDesiredAccess may need some processing */
398 r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey );
399 if (r!=ERROR_SUCCESS)
402 TRACE("returning %p\n",hKey);
407 /******************************************************************************
408 * CreateServiceW [ADVAPI32.@]
411 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
412 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
413 DWORD dwServiceType, DWORD dwStartType,
414 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
415 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
416 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
419 FIXME("(%p,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
424 /******************************************************************************
425 * CreateServiceA [ADVAPI32.@]
428 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
429 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
430 DWORD dwServiceType, DWORD dwStartType,
431 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
432 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
433 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
440 TRACE("(%p,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
442 r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL,
443 REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp);
444 if (r!=ERROR_SUCCESS)
446 if (dp != REG_CREATED_NEW_KEY)
451 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, strlen(lpDisplayName) );
452 if (r!=ERROR_SUCCESS)
456 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
457 if (r!=ERROR_SUCCESS)
460 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
461 if (r!=ERROR_SUCCESS)
464 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
465 (LPVOID)&dwErrorControl, sizeof (DWORD) );
466 if (r!=ERROR_SUCCESS)
471 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
472 lpBinaryPathName,strlen(lpBinaryPathName)+1 );
473 if (r!=ERROR_SUCCESS)
479 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
480 lpLoadOrderGroup, strlen(lpLoadOrderGroup)+1 );
481 if (r!=ERROR_SUCCESS)
485 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
486 (LPVOID)&dwErrorControl, sizeof (DWORD) );
487 if (r!=ERROR_SUCCESS)
494 /* determine the length of a double null terminated multi string */
496 len += (strlen(&lpDependencies[len])+1);
497 } while (lpDependencies[len++]);
499 /* FIXME: this should be unicode */
500 r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ,
501 lpDependencies, len );
502 if (r!=ERROR_SUCCESS)
508 FIXME("Don't know how to add a Password for a service.\n");
511 if(lpServiceStartName)
513 FIXME("Don't know how to add a ServiceStartName for a service.\n");
520 /******************************************************************************
521 * DeleteService [ADVAPI32.@]
524 * hService [I] Handle to service
530 DeleteService( SC_HANDLE hService )
532 FIXME("(%p): stub\n",hService);
537 /******************************************************************************
538 * StartServiceA [ADVAPI32.@]
542 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
543 LPCSTR *lpServiceArgVectors )
548 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
551 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
552 dwNumServiceArgs*sizeof(LPWSTR) );
556 for(i=0; i<dwNumServiceArgs; i++)
557 lpwstr[i]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors[i]);
559 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
563 for(i=0; i<dwNumServiceArgs; i++)
564 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
565 HeapFree(GetProcessHeap(), 0, lpwstr);
572 /******************************************************************************
573 * StartServiceW [ADVAPI32.@]
577 * hService [I] Handle of service
578 * dwNumServiceArgs [I] Number of arguments
579 * lpServiceArgVectors [I] Address of array of argument string pointers
583 * NT implements this function using an obscure RPC call...
585 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
586 * to get things like %SystemRoot%\\System32\\service.exe to load.
588 * Will only work for shared address space. How should the service
589 * args be transferred when address spaces are separated?
591 * Can only start one service at a time.
593 * Has no concept of privilege.
599 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
600 LPCWSTR *lpServiceArgVectors )
602 CHAR path[MAX_PATH],str[MAX_PATH];
606 PROCESS_INFORMATION procinfo;
607 STARTUPINFOA startupinfo;
609 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,
610 lpServiceArgVectors);
613 r = RegQueryValueExA(hService, "ImagePath", NULL, &type, (LPVOID)str, &size);
614 if (r!=ERROR_SUCCESS)
616 ExpandEnvironmentStringsA(str,path,sizeof path);
618 TRACE("Starting service %s\n", debugstr_a(path) );
620 data = CreateSemaphoreA(NULL,1,1,"ADVAPI32_ServiceStartData");
623 data = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
626 ERR("Couldn't create data semaphore\n");
630 wait = CreateSemaphoreA(NULL,0,1,"ADVAPI32_WaitServiceStart");
632 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
635 ERR("Couldn't create wait semaphore\n");
641 * FIXME: lpServiceArgsVectors need to be stored and returned to
642 * the service when it calls StartServiceCtrlDispatcher
644 * Chuck these in a global (yuk) so we can pass them to
645 * another process - address space separation will break this.
648 r = WaitForSingleObject(data,INFINITE);
650 if( r == WAIT_FAILED)
653 FIXME("problematic because of address space separation.\n");
654 start_dwNumServiceArgs = dwNumServiceArgs;
655 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
657 ZeroMemory(&startupinfo,sizeof(STARTUPINFOA));
658 startupinfo.cb = sizeof(STARTUPINFOA);
660 r = CreateProcessA(path,
662 NULL, /* process security attribs */
663 NULL, /* thread security attribs */
664 FALSE, /* inherit handles */
665 0, /* creation flags */
666 NULL, /* environment */
667 NULL, /* current directory */
668 &startupinfo, /* startup info */
669 &procinfo); /* process info */
673 ERR("Couldn't start process\n");
674 /* ReleaseSemaphore(data, 1, NULL);
678 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
679 r = WaitForSingleObject(wait,30000);
681 ReleaseSemaphore(data, 1, NULL);
683 if( r == WAIT_FAILED)
689 /******************************************************************************
690 * QueryServiceStatus [ADVAPI32.@]
698 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
701 DWORD type, val, size;
703 FIXME("(%p,%p) partial\n",hService,lpservicestatus);
705 /* read the service type from the registry */
707 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
710 ERR("invalid Type\n");
713 lpservicestatus->dwServiceType = val;
714 /* FIXME: how are these determined or read from the registry? */
715 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
716 lpservicestatus->dwCurrentState = 1;
717 lpservicestatus->dwControlsAccepted = 0;
718 lpservicestatus->dwWin32ExitCode = NO_ERROR;
719 lpservicestatus->dwServiceSpecificExitCode = 0;
720 lpservicestatus->dwCheckPoint = 0;
721 lpservicestatus->dwWaitHint = 0;
726 /******************************************************************************
727 * QueryServiceStatusEx [ADVAPI32.@]
730 * hService [handle to service]
731 * InfoLevel [information level]
733 * cbBufSize [size of buffer]
734 * pcbBytesNeeded [bytes needed]
736 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
737 LPBYTE lpBuffer, DWORD cbBufSize,
738 LPDWORD pcbBytesNeeded)
741 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);