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
30 #include "wine/unicode.h"
32 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
37 static DWORD start_dwNumServiceArgs;
38 static LPWSTR *start_lpServiceArgVectors;
40 static const WCHAR _ServiceStartDataW[] = {'A','D','V','A','P','I','_','S',
41 'e','r','v','i','c','e','S','t',
42 'a','r','t','D','a','t','a',0};
43 static const WCHAR szServiceManagerKey[] = { 'S','y','s','t','e','m','\\',
44 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
45 'S','e','r','v','i','c','e','s','\\',0 };
48 /******************************************************************************
49 * EnumServicesStatusA [ADVAPI32.@]
52 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
53 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
54 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
55 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
56 { FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
57 dwServiceType, dwServiceState, lpServices, cbBufSize,
58 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
59 SetLastError (ERROR_ACCESS_DENIED);
63 /******************************************************************************
64 * EnumServicesStatusW [ADVAPI32.@]
67 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
68 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
69 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
70 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
71 { FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
72 dwServiceType, dwServiceState, lpServices, cbBufSize,
73 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
74 SetLastError (ERROR_ACCESS_DENIED);
78 /******************************************************************************
79 * StartServiceCtrlDispatcherA [ADVAPI32.@]
82 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
84 LPSERVICE_MAIN_FUNCTIONA fpMain;
86 DWORD dwNumServiceArgs ;
91 TRACE("(%p)\n", servent);
92 wait = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW);
95 ERR("Couldn't find wait semaphore\n");
96 ERR("perhaps you need to start services using StartService\n");
100 dwNumServiceArgs = start_dwNumServiceArgs;
101 lpArgVecW = start_lpServiceArgVectors;
103 ReleaseSemaphore(wait, 1, NULL);
105 /* Convert the Unicode arg vectors back to ASCII */
107 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
108 dwNumServiceArgs*sizeof(LPSTR) );
112 for(i=0; i<dwNumServiceArgs; i++)
113 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
115 /* FIXME: should we blindly start all services? */
116 while (servent->lpServiceName) {
117 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
118 fpMain = servent->lpServiceProc;
120 /* try to start the service */
121 fpMain( dwNumServiceArgs, lpArgVecA);
128 /* free arg strings */
129 for(i=0; i<dwNumServiceArgs; i++)
130 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
131 HeapFree(GetProcessHeap(), 0, lpArgVecA);
137 /******************************************************************************
138 * StartServiceCtrlDispatcherW [ADVAPI32.@]
144 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
146 LPSERVICE_MAIN_FUNCTIONW fpMain;
148 DWORD dwNumServiceArgs ;
149 LPWSTR *lpServiceArgVectors ;
151 TRACE("(%p)\n", servent);
152 wait = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW);
155 ERR("Couldn't find wait semaphore\n");
156 ERR("perhaps you need to start services using StartService\n");
160 dwNumServiceArgs = start_dwNumServiceArgs;
161 lpServiceArgVectors = start_lpServiceArgVectors;
163 ReleaseSemaphore(wait, 1, NULL);
165 /* FIXME: should we blindly start all services? */
166 while (servent->lpServiceName) {
167 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
168 fpMain = servent->lpServiceProc;
170 /* try to start the service */
171 fpMain( dwNumServiceArgs, lpServiceArgVectors);
179 /******************************************************************************
180 * LockServiceDatabase [ADVAPI32.@]
182 LPVOID WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
184 FIXME("%p\n",hSCManager);
185 return (SC_HANDLE)0xcacacafe;
188 /******************************************************************************
189 * UnlockServiceDatabase [ADVAPI32.@]
191 BOOL WINAPI UnlockServiceDatabase (LPVOID ScLock)
193 FIXME(": %p\n",ScLock);
197 /******************************************************************************
198 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
200 SERVICE_STATUS_HANDLE WINAPI
201 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
202 LPHANDLER_FUNCTION lpfHandler )
203 { FIXME("%s %p\n", lpServiceName, lpfHandler);
207 /******************************************************************************
208 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
214 SERVICE_STATUS_HANDLE WINAPI
215 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
216 LPHANDLER_FUNCTION lpfHandler )
217 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
221 /******************************************************************************
222 * SetServiceStatus [ADVAPI32.@]
229 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
230 { FIXME("0x%lx %p\n",hService, lpStatus);
231 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
232 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
233 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
234 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
235 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
236 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
237 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
241 /******************************************************************************
242 * OpenSCManagerA [ADVAPI32.@]
244 * Establish a connection to the service control manager and open its database.
247 * lpMachineName [I] Pointer to machine name string
248 * lpDatabaseName [I] Pointer to database name string
249 * dwDesiredAccess [I] Type of access
252 * Success: A Handle to the service control manager database
255 SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
256 DWORD dwDesiredAccess )
258 UNICODE_STRING lpMachineNameW;
259 UNICODE_STRING lpDatabaseNameW;
262 RtlCreateUnicodeStringFromAsciiz (&lpMachineNameW,lpMachineName);
263 RtlCreateUnicodeStringFromAsciiz (&lpDatabaseNameW,lpDatabaseName);
264 ret = OpenSCManagerW(lpMachineNameW.Buffer,lpDatabaseNameW.Buffer, dwDesiredAccess);
265 RtlFreeUnicodeString(&lpDatabaseNameW);
266 RtlFreeUnicodeString(&lpMachineNameW);
270 /******************************************************************************
271 * OpenSCManagerW [ADVAPI32.@]
273 * See OpenSCManagerA.
275 SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
276 DWORD dwDesiredAccess )
278 HKEY hReg, hKey = NULL;
281 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
282 debugstr_w(lpDatabaseName), dwDesiredAccess);
285 * FIXME: what is lpDatabaseName?
286 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
287 * docs, but what if it isn't?
290 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
291 if (r==ERROR_SUCCESS)
293 r = RegOpenKeyExW(hReg, szServiceManagerKey,0, dwDesiredAccess, &hKey );
297 TRACE("returning %p\n", hKey);
303 /******************************************************************************
304 * AllocateLocallyUniqueId [ADVAPI32.@]
310 AllocateLocallyUniqueId( PLUID lpluid )
312 lpluid->LowPart = time(NULL);
313 lpluid->HighPart = 0;
318 /******************************************************************************
319 * ControlService [ADVAPI32.@]
321 * Send a control code to a service.
324 * hService [I] Handle of the service control manager database
325 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
326 * lpServiceStatus [O] Destination for the status of the service, if available
332 BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
333 LPSERVICE_STATUS lpServiceStatus )
335 FIXME("(%p,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
340 /******************************************************************************
341 * CloseServiceHandle [ADVAPI32.@]
343 * Close a handle to a service or the service control manager database.
346 * hSCObject [I] Handle to service or service control manager database
353 CloseServiceHandle( SC_HANDLE hSCObject )
355 TRACE("(%p)\n", hSCObject);
357 RegCloseKey(hSCObject);
363 /******************************************************************************
364 * OpenServiceA [ADVAPI32.@]
366 * Open a handle to a service.
369 * hSCManager [I] Handle of the service control manager database
370 * lpServiceName [I] Name of the service to open
371 * dwDesiredAccess [I] Access required to the service
374 * Success: Handle to the service
377 SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
378 DWORD dwDesiredAccess )
380 UNICODE_STRING lpServiceNameW;
382 RtlCreateUnicodeStringFromAsciiz (&lpServiceNameW,lpServiceName);
384 TRACE("Request for service %s\n",lpServiceName);
387 ret = OpenServiceW( hSCManager, lpServiceNameW.Buffer, dwDesiredAccess);
388 RtlFreeUnicodeString(&lpServiceNameW);
393 /******************************************************************************
394 * OpenServiceW [ADVAPI32.@]
398 SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
399 DWORD dwDesiredAccess)
404 TRACE("(%p,%p,%ld)\n",hSCManager, lpServiceName,
407 r = RegOpenKeyExW(hSCManager, lpServiceName, 0, KEY_ALL_ACCESS, &hKey );
408 if (r!=ERROR_SUCCESS)
411 TRACE("returning %p\n",hKey);
416 /******************************************************************************
417 * CreateServiceW [ADVAPI32.@]
420 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
421 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
422 DWORD dwServiceType, DWORD dwStartType,
423 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
424 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
425 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
431 static const WCHAR szDisplayName[] = { 'D','i','s','p','l','a','y','N','a','m','e', 0 };
432 static const WCHAR szType[] = {'T','y','p','e',0};
433 static const WCHAR szStart[] = {'S','t','a','r','t',0};
434 static const WCHAR szError[] = {'E','r','r','o','r','C','o','n','t','r','o','l', 0};
435 static const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
436 static const WCHAR szGroup[] = {'G','r','o','u','p',0};
437 static const WCHAR szDependencies[] = { 'D','e','p','e','n','d','e','n','c','i','e','s',0};
439 FIXME("%p %s %s\n", hSCManager,
440 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
442 r = RegCreateKeyExW(hSCManager, lpServiceName, 0, NULL,
443 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp);
444 if (r!=ERROR_SUCCESS)
447 if (dp != REG_CREATED_NEW_KEY)
452 r = RegSetValueExW(hKey, szDisplayName, 0, REG_SZ, (LPBYTE)lpDisplayName,
453 (strlenW(lpDisplayName)+1)*sizeof(WCHAR) );
454 if (r!=ERROR_SUCCESS)
458 r = RegSetValueExW(hKey, szType, 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
459 if (r!=ERROR_SUCCESS)
462 r = RegSetValueExW(hKey, szStart, 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
463 if (r!=ERROR_SUCCESS)
466 r = RegSetValueExW(hKey, szError, 0, REG_DWORD,
467 (LPVOID)&dwErrorControl, sizeof (DWORD) );
468 if (r!=ERROR_SUCCESS)
473 r = RegSetValueExW(hKey, szImagePath, 0, REG_SZ, (LPBYTE)lpBinaryPathName,
474 (strlenW(lpBinaryPathName)+1)*sizeof(WCHAR) );
475 if (r!=ERROR_SUCCESS)
481 r = RegSetValueExW(hKey, szGroup, 0, REG_SZ, (LPBYTE)lpLoadOrderGroup,
482 (strlenW(lpLoadOrderGroup)+1)*sizeof(WCHAR) );
483 if (r!=ERROR_SUCCESS)
491 /* determine the length of a double null terminated multi string */
493 len += (strlenW(&lpDependencies[len])+1);
494 } while (lpDependencies[len++]);
496 r = RegSetValueExW(hKey, szDependencies, 0, REG_MULTI_SZ,
497 (LPBYTE)lpDependencies, len );
498 if (r!=ERROR_SUCCESS)
504 FIXME("Don't know how to add a Password for a service.\n");
507 if(lpServiceStartName)
509 FIXME("Don't know how to add a ServiceStartName for a service.\n");
516 static inline LPWSTR SERV_dup( LPCSTR str )
523 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
524 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
525 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
529 static inline LPWSTR SERV_dupmulti( LPCSTR str )
537 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
538 n += (strlen( &str[n] ) + 1);
543 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
544 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
548 static inline VOID SERV_free( LPWSTR wstr )
550 HeapFree( GetProcessHeap(), 0, wstr );
553 /******************************************************************************
554 * CreateServiceA [ADVAPI32.@]
557 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
558 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
559 DWORD dwServiceType, DWORD dwStartType,
560 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
561 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
562 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
565 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
566 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
569 TRACE("%p %s %s\n", hSCManager,
570 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
572 lpServiceNameW = SERV_dup( lpServiceName );
573 lpDisplayNameW = SERV_dup( lpDisplayName );
574 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
575 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
576 lpDependenciesW = SERV_dupmulti( lpDependencies );
577 lpServiceStartNameW = SERV_dup( lpServiceStartName );
578 lpPasswordW = SERV_dup( lpPassword );
580 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
581 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
582 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
583 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
585 SERV_free( lpServiceNameW );
586 SERV_free( lpDisplayNameW );
587 SERV_free( lpBinaryPathNameW );
588 SERV_free( lpLoadOrderGroupW );
589 SERV_free( lpDependenciesW );
590 SERV_free( lpServiceStartNameW );
591 SERV_free( lpPasswordW );
597 /******************************************************************************
598 * DeleteService [ADVAPI32.@]
600 * Delete a service from the service control manager database.
603 * hService [I] Handle of the service to delete
609 BOOL WINAPI DeleteService( SC_HANDLE hService )
611 WCHAR valname[MAX_PATH+1];
618 static const WCHAR szDeleted[] = {'D','e','l','e','t','e','d',0};
620 FIXME("(%p): stub\n",hService);
623 /* Clean out the values */
624 rc = RegEnumValueW(hService, index, valname,&size,0,0,0,0);
625 while (rc == ERROR_SUCCESS)
627 RegDeleteValueW(hService,valname);
630 rc = RegEnumValueW(hService, index, valname, &size,0,0,0,0);
633 /* tag for deletion */
634 RegSetValueExW(hService, szDeleted, 0, REG_DWORD, (LPVOID)&value,
637 RegCloseKey(hService);
639 /* find and delete the key */
640 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szServiceManagerKey,0,
641 KEY_ALL_ACCESS, &hKey );
644 rc = RegEnumKeyExW(hKey,0, valname, &size, 0, 0, 0, 0);
645 while (rc == ERROR_SUCCESS)
648 rc = RegOpenKeyExW(hKey,valname,0,KEY_ALL_ACCESS,&checking);
649 if (rc == ERROR_SUCCESS)
652 DWORD size = sizeof(DWORD);
653 rc = RegQueryValueExW(checking, szDeleted , NULL, NULL,
654 (LPVOID)&deleted, &size);
657 RegDeleteValueW(checking,szDeleted);
658 RegDeleteKeyW(hKey,valname);
662 RegCloseKey(checking);
665 rc = RegEnumKeyExW(hKey, index, valname, &size, 0, 0, 0, 0);
673 /******************************************************************************
674 * StartServiceA [ADVAPI32.@]
679 * hService [I] Handle of service
680 * dwNumServiceArgs [I] Number of arguments
681 * lpServiceArgVectors [I] Address of array of argument strings
684 * - NT implements this function using an obscure RPC call.
685 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
686 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
687 * - This will only work for shared address space. How should the service
688 * args be transferred when address spaces are separated?
689 * - Can only start one service at a time.
690 * - Has no concept of privilege.
697 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
698 LPCSTR *lpServiceArgVectors )
701 UNICODE_STRING usBuffer;
704 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
707 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
708 dwNumServiceArgs*sizeof(LPWSTR) );
712 for(i=0; i<dwNumServiceArgs; i++)
714 RtlCreateUnicodeStringFromAsciiz (&usBuffer,lpServiceArgVectors[i]);
715 lpwstr[i]=usBuffer.Buffer;
718 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
722 for(i=0; i<dwNumServiceArgs; i++)
723 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
724 HeapFree(GetProcessHeap(), 0, lpwstr);
731 /******************************************************************************
732 * StartServiceW [ADVAPI32.@]
737 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
738 LPCWSTR *lpServiceArgVectors )
740 static const WCHAR _WaitServiceStartW[] = {'A','D','V','A','P','I','_','W',
741 'a','i','t','S','e','r','v','i',
742 'c','e','S','t','a','r','t',0};
743 static const WCHAR _ImagePathW[] = {'I','m','a','g','e','P','a','t','h',0};
745 WCHAR path[MAX_PATH],str[MAX_PATH];
749 PROCESS_INFORMATION procinfo;
750 STARTUPINFOW startupinfo;
751 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,
752 lpServiceArgVectors);
755 r = RegQueryValueExW(hService, _ImagePathW, NULL, &type, (LPVOID)str, &size);
756 if (r!=ERROR_SUCCESS)
758 ExpandEnvironmentStringsW(str,path,sizeof(path));
760 TRACE("Starting service %s\n", debugstr_w(path) );
762 data = CreateSemaphoreW(NULL,1,1,_ServiceStartDataW);
765 ERR("Couldn't create data semaphore\n");
768 wait = CreateSemaphoreW(NULL,0,1,_WaitServiceStartW);
771 ERR("Couldn't create wait semaphore\n");
776 * FIXME: lpServiceArgsVectors need to be stored and returned to
777 * the service when it calls StartServiceCtrlDispatcher
779 * Chuck these in a global (yuk) so we can pass them to
780 * another process - address space separation will break this.
783 r = WaitForSingleObject(data,INFINITE);
785 if( r == WAIT_FAILED)
788 FIXME("problematic because of address space separation.\n");
789 start_dwNumServiceArgs = dwNumServiceArgs;
790 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
792 ZeroMemory(&startupinfo,sizeof(STARTUPINFOW));
793 startupinfo.cb = sizeof(STARTUPINFOW);
795 r = CreateProcessW(path,
797 NULL, /* process security attribs */
798 NULL, /* thread security attribs */
799 FALSE, /* inherit handles */
800 0, /* creation flags */
801 NULL, /* environment */
802 NULL, /* current directory */
803 &startupinfo, /* startup info */
804 &procinfo); /* process info */
808 ERR("Couldn't start process\n");
809 /* ReleaseSemaphore(data, 1, NULL);
813 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
814 r = WaitForSingleObject(wait,30000);
816 ReleaseSemaphore(data, 1, NULL);
818 if( r == WAIT_FAILED)
824 /******************************************************************************
825 * QueryServiceStatus [ADVAPI32.@]
833 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
836 DWORD type, val, size;
838 FIXME("(%p,%p) partial\n",hService,lpservicestatus);
840 /* read the service type from the registry */
842 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
845 ERR("invalid Type\n");
848 lpservicestatus->dwServiceType = val;
849 /* FIXME: how are these determined or read from the registry? */
850 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
851 lpservicestatus->dwCurrentState = 1;
852 lpservicestatus->dwControlsAccepted = 0;
853 lpservicestatus->dwWin32ExitCode = NO_ERROR;
854 lpservicestatus->dwServiceSpecificExitCode = 0;
855 lpservicestatus->dwCheckPoint = 0;
856 lpservicestatus->dwWaitHint = 0;
861 /******************************************************************************
862 * QueryServiceStatusEx [ADVAPI32.@]
864 * Get information about a service.
867 * hService [I] Handle to service to get information about
868 * InfoLevel [I] Level of information to get
869 * lpBuffer [O] Destination for requested information
870 * cbBufSize [I] Size of lpBuffer in bytes
871 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
877 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
878 LPBYTE lpBuffer, DWORD cbBufSize,
879 LPDWORD pcbBytesNeeded)
882 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
886 /******************************************************************************
887 * QueryServiceConfigA [ADVAPI32.@]
890 QueryServiceConfigA( SC_HANDLE hService,
891 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
892 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
894 FIXME("%p %p %ld %p\n", hService, lpServiceConfig,
895 cbBufSize, pcbBytesNeeded);
899 /******************************************************************************
900 * QueryServiceConfigW [ADVAPI32.@]
903 QueryServiceConfigW( SC_HANDLE hService,
904 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
905 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
907 static const WCHAR szDisplayName[] = {
908 'D','i','s','p','l','a','y','N','a','m','e', 0 };
909 static const WCHAR szType[] = {'T','y','p','e',0};
910 static const WCHAR szStart[] = {'S','t','a','r','t',0};
911 static const WCHAR szError[] = {
912 'E','r','r','o','r','C','o','n','t','r','o','l', 0};
913 static const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
914 static const WCHAR szGroup[] = {'G','r','o','u','p',0};
915 static const WCHAR szDependencies[] = {
916 'D','e','p','e','n','d','e','n','c','i','e','s',0};
918 DWORD type, val, sz, total, n;
921 TRACE("%p %p %ld %p\n", hService, lpServiceConfig,
922 cbBufSize, pcbBytesNeeded);
924 /* calculate the size required first */
925 total = sizeof (QUERY_SERVICE_CONFIGW);
928 r = RegQueryValueExW( hService, szImagePath, 0, &type, NULL, &sz );
929 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
933 r = RegQueryValueExW( hService, szGroup, 0, &type, NULL, &sz );
934 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
938 r = RegQueryValueExW( hService, szDependencies, 0, &type, NULL, &sz );
939 if( ( r == ERROR_SUCCESS ) && ( type == REG_MULTI_SZ ) )
943 r = RegQueryValueExW( hService, szStart, 0, &type, NULL, &sz );
944 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
948 r = RegQueryValueExW( hService, szDisplayName, 0, &type, NULL, &sz );
949 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
952 /* if there's not enough memory, return an error */
953 if( total > *pcbBytesNeeded )
955 *pcbBytesNeeded = total;
956 SetLastError( ERROR_INSUFFICIENT_BUFFER );
960 *pcbBytesNeeded = total;
961 ZeroMemory( lpServiceConfig, total );
964 r = RegQueryValueExW( hService, szType, 0, &type, (LPBYTE)&val, &sz );
965 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
966 lpServiceConfig->dwServiceType = val;
969 r = RegQueryValueExW( hService, szStart, 0, &type, (LPBYTE)&val, &sz );
970 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
971 lpServiceConfig->dwStartType = val;
974 r = RegQueryValueExW( hService, szError, 0, &type, (LPBYTE)&val, &sz );
975 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
976 lpServiceConfig->dwErrorControl = val;
978 /* now do the strings */
979 p = (LPBYTE) &lpServiceConfig[1];
980 n = total - sizeof (QUERY_SERVICE_CONFIGW);
983 r = RegQueryValueExW( hService, szImagePath, 0, &type, p, &sz );
984 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
986 lpServiceConfig->lpBinaryPathName = (LPWSTR) p;
992 r = RegQueryValueExW( hService, szGroup, 0, &type, p, &sz );
993 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
995 lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p;
1001 r = RegQueryValueExW( hService, szDependencies, 0, &type, p, &sz );
1002 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
1004 lpServiceConfig->lpDependencies = (LPWSTR) p;
1010 ERR("Buffer overflow!\n");
1012 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1013 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1018 /******************************************************************************
1019 * ChangeServiceConfigW [ADVAPI32.@]
1021 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1022 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1023 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1024 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1026 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1027 hService, dwServiceType, dwStartType, dwErrorControl,
1028 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1029 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1030 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1034 /******************************************************************************
1035 * ChangeServiceConfigA [ADVAPI32.@]
1037 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
1038 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1039 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
1040 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
1042 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1043 hService, dwServiceType, dwStartType, dwErrorControl,
1044 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
1045 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
1046 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
1050 /******************************************************************************
1051 * ChangeServiceConfig2A [ADVAPI32.@]
1053 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
1056 FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo);
1060 /******************************************************************************
1061 * ChangeServiceConfig2W [ADVAPI32.@]
1063 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
1066 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
1068 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1069 LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo;
1070 if (sd->lpDescription)
1072 TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
1073 if (sd->lpDescription[0] == 0)
1074 RegDeleteValueW(hService,szDescription);
1076 RegSetValueExW(hService, szDescription, 0, REG_SZ,
1077 (LPVOID)sd->lpDescription,
1078 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
1082 FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo);