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.@]
245 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
246 DWORD dwDesiredAccess )
248 UNICODE_STRING lpMachineNameW;
249 UNICODE_STRING lpDatabaseNameW;
252 RtlCreateUnicodeStringFromAsciiz (&lpMachineNameW,lpMachineName);
253 RtlCreateUnicodeStringFromAsciiz (&lpDatabaseNameW,lpDatabaseName);
254 ret = OpenSCManagerW(lpMachineNameW.Buffer,lpDatabaseNameW.Buffer, dwDesiredAccess);
255 RtlFreeUnicodeString(&lpDatabaseNameW);
256 RtlFreeUnicodeString(&lpMachineNameW);
260 /******************************************************************************
261 * OpenSCManagerW [ADVAPI32.@]
262 * Establishes a connection to the service control manager and opens database
265 * This should return a SC_HANDLE
268 * lpMachineName [I] Pointer to machine name string
269 * lpDatabaseName [I] Pointer to database name string
270 * dwDesiredAccess [I] Type of access
273 * Success: Handle to service control manager database
277 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
278 DWORD dwDesiredAccess )
280 HKEY hReg, hKey = NULL;
283 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
284 debugstr_w(lpDatabaseName), dwDesiredAccess);
287 * FIXME: what is lpDatabaseName?
288 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
289 * docs, but what if it isn't?
292 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
293 if (r==ERROR_SUCCESS)
295 r = RegOpenKeyExW(hReg, szServiceManagerKey,0, dwDesiredAccess, &hKey );
299 TRACE("returning %p\n", hKey);
305 /******************************************************************************
306 * AllocateLocallyUniqueId [ADVAPI32.@]
312 AllocateLocallyUniqueId( PLUID lpluid )
314 lpluid->LowPart = time(NULL);
315 lpluid->HighPart = 0;
320 /******************************************************************************
321 * ControlService [ADVAPI32.@]
322 * Sends a control code to a Win32-based service.
332 ControlService( SC_HANDLE hService, DWORD dwControl,
333 LPSERVICE_STATUS lpServiceStatus )
335 FIXME("(%p,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
340 /******************************************************************************
341 * CloseServiceHandle [ADVAPI32.@]
342 * Close handle to service or service control manager
345 * hSCObject [I] Handle to service or service control manager database
350 CloseServiceHandle( SC_HANDLE hSCObject )
352 TRACE("(%p)\n", hSCObject);
354 RegCloseKey(hSCObject);
360 /******************************************************************************
361 * OpenServiceA [ADVAPI32.@]
364 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
365 DWORD dwDesiredAccess )
367 UNICODE_STRING lpServiceNameW;
369 RtlCreateUnicodeStringFromAsciiz (&lpServiceNameW,lpServiceName);
371 TRACE("Request for service %s\n",lpServiceName);
374 ret = OpenServiceW( hSCManager, lpServiceNameW.Buffer, dwDesiredAccess);
375 RtlFreeUnicodeString(&lpServiceNameW);
380 /******************************************************************************
381 * OpenServiceW [ADVAPI32.@]
382 * Opens a handle to an existing service
390 * Success: Handle to the service
394 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
395 DWORD dwDesiredAccess)
400 TRACE("(%p,%p,%ld)\n",hSCManager, lpServiceName,
403 /* FIXME: dwDesiredAccess may need some processing */
404 r = RegOpenKeyExW(hSCManager, lpServiceName, 0, dwDesiredAccess, &hKey );
405 if (r!=ERROR_SUCCESS)
408 TRACE("returning %p\n",hKey);
413 /******************************************************************************
414 * CreateServiceW [ADVAPI32.@]
417 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
418 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
419 DWORD dwServiceType, DWORD dwStartType,
420 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
421 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
422 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
428 const WCHAR szDisplayName[] = { 'D','i','s','p','l','a','y','N','a','m','e', 0 };
429 const WCHAR szType[] = {'T','y','p','e',0};
430 const WCHAR szStart[] = {'S','t','a','r','t',0};
431 const WCHAR szError[] = {'E','r','r','o','r','C','o','n','t','r','o','l', 0};
432 const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
433 const WCHAR szGroup[] = {'G','r','o','u','p',0};
434 const WCHAR szDependencies[] = { 'D','e','p','e','n','d','e','n','c','i','e','s',0};
436 FIXME("%p %s %s\n", hSCManager,
437 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
439 r = RegCreateKeyExW(hSCManager, lpServiceName, 0, NULL,
440 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp);
441 if (r!=ERROR_SUCCESS)
444 if (dp != REG_CREATED_NEW_KEY)
449 r = RegSetValueExW(hKey, szDisplayName, 0, REG_SZ, (LPBYTE)lpDisplayName,
450 (strlenW(lpDisplayName)+1)*sizeof(WCHAR) );
451 if (r!=ERROR_SUCCESS)
455 r = RegSetValueExW(hKey, szType, 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
456 if (r!=ERROR_SUCCESS)
459 r = RegSetValueExW(hKey, szStart, 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
460 if (r!=ERROR_SUCCESS)
463 r = RegSetValueExW(hKey, szError, 0, REG_DWORD,
464 (LPVOID)&dwErrorControl, sizeof (DWORD) );
465 if (r!=ERROR_SUCCESS)
470 r = RegSetValueExW(hKey, szImagePath, 0, REG_SZ, (LPBYTE)lpBinaryPathName,
471 (strlenW(lpBinaryPathName)+1)*sizeof(WCHAR) );
472 if (r!=ERROR_SUCCESS)
478 r = RegSetValueExW(hKey, szGroup, 0, REG_SZ, (LPBYTE)lpLoadOrderGroup,
479 (strlenW(lpLoadOrderGroup)+1)*sizeof(WCHAR) );
480 if (r!=ERROR_SUCCESS)
488 /* determine the length of a double null terminated multi string */
490 len += (strlenW(&lpDependencies[len])+1);
491 } while (lpDependencies[len++]);
493 r = RegSetValueExW(hKey, szDependencies, 0, REG_MULTI_SZ,
494 (LPBYTE)lpDependencies, len );
495 if (r!=ERROR_SUCCESS)
501 FIXME("Don't know how to add a Password for a service.\n");
504 if(lpServiceStartName)
506 FIXME("Don't know how to add a ServiceStartName for a service.\n");
513 static inline LPWSTR SERV_dup( LPCSTR str )
520 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
521 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
522 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
526 static inline LPWSTR SERV_dupmulti( LPCSTR str )
534 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
535 n += (strlen( &str[n] ) + 1);
540 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
541 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
545 static inline VOID SERV_free( LPWSTR wstr )
547 HeapFree( GetProcessHeap(), 0, wstr );
550 /******************************************************************************
551 * CreateServiceA [ADVAPI32.@]
554 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
555 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
556 DWORD dwServiceType, DWORD dwStartType,
557 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
558 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
559 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
562 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
563 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
566 TRACE("%p %s %s\n", hSCManager,
567 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
569 lpServiceNameW = SERV_dup( lpServiceName );
570 lpDisplayNameW = SERV_dup( lpDisplayName );
571 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
572 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
573 lpDependenciesW = SERV_dupmulti( lpDependencies );
574 lpServiceStartNameW = SERV_dup( lpServiceStartName );
575 lpPasswordW = SERV_dup( lpPassword );
577 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
578 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
579 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
580 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
582 SERV_free( lpServiceNameW );
583 SERV_free( lpDisplayNameW );
584 SERV_free( lpBinaryPathNameW );
585 SERV_free( lpLoadOrderGroupW );
586 SERV_free( lpDependenciesW );
587 SERV_free( lpServiceStartNameW );
588 SERV_free( lpPasswordW );
594 /******************************************************************************
595 * DeleteService [ADVAPI32.@]
598 * hService [I] Handle to service
604 DeleteService( SC_HANDLE hService )
606 WCHAR valname[MAX_PATH+1];
613 static const WCHAR szDeleted[] = {'D','e','l','e','t','e','d',0};
615 FIXME("(%p): stub\n",hService);
618 /* Clean out the values */
619 rc = RegEnumValueW(hService, index, valname,&size,0,0,0,0);
620 while (rc == ERROR_SUCCESS)
622 RegDeleteValueW(hService,valname);
625 rc = RegEnumValueW(hService, index, valname, &size,0,0,0,0);
628 /* tag for deletion */
629 RegSetValueExW(hService, szDeleted, 0, REG_DWORD, (LPVOID)&value,
632 RegCloseKey(hService);
634 /* find and delete the key */
635 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szServiceManagerKey,0,
636 KEY_ALL_ACCESS, &hKey );
639 rc = RegEnumKeyExW(hKey,0, valname, &size, 0, 0, 0, 0);
640 while (rc == ERROR_SUCCESS)
643 rc = RegOpenKeyExW(hKey,valname,0,KEY_ALL_ACCESS,&checking);
644 if (rc == ERROR_SUCCESS)
647 DWORD size = sizeof(DWORD);
648 rc = RegQueryValueExW(checking, szDeleted , NULL, NULL,
649 (LPVOID)&deleted, &size);
652 RegDeleteValueW(checking,szDeleted);
653 RegDeleteKeyW(hKey,valname);
657 RegCloseKey(checking);
660 rc = RegEnumKeyExW(hKey, index, valname, &size, 0, 0, 0, 0);
668 /******************************************************************************
669 * StartServiceA [ADVAPI32.@]
673 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
674 LPCSTR *lpServiceArgVectors )
677 UNICODE_STRING usBuffer;
680 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
683 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
684 dwNumServiceArgs*sizeof(LPWSTR) );
688 for(i=0; i<dwNumServiceArgs; i++)
690 RtlCreateUnicodeStringFromAsciiz (&usBuffer,lpServiceArgVectors[i]);
691 lpwstr[i]=usBuffer.Buffer;
694 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
698 for(i=0; i<dwNumServiceArgs; i++)
699 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
700 HeapFree(GetProcessHeap(), 0, lpwstr);
707 /******************************************************************************
708 * StartServiceW [ADVAPI32.@]
712 * hService [I] Handle of service
713 * dwNumServiceArgs [I] Number of arguments
714 * lpServiceArgVectors [I] Address of array of argument string pointers
718 * NT implements this function using an obscure RPC call...
720 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
721 * to get things like %SystemRoot%\\System32\\service.exe to load.
723 * Will only work for shared address space. How should the service
724 * args be transferred when address spaces are separated?
726 * Can only start one service at a time.
728 * Has no concept of privilege.
734 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
735 LPCWSTR *lpServiceArgVectors )
737 static const WCHAR _WaitServiceStartW[] = {'A','D','V','A','P','I','_','W',
738 'a','i','t','S','e','r','v','i',
739 'c','e','S','t','a','r','t',0};
740 static const WCHAR _ImagePathW[] = {'I','m','a','g','e','P','a','t','h',0};
742 WCHAR path[MAX_PATH],str[MAX_PATH];
746 PROCESS_INFORMATION procinfo;
747 STARTUPINFOW startupinfo;
748 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,
749 lpServiceArgVectors);
752 r = RegQueryValueExW(hService, _ImagePathW, NULL, &type, (LPVOID)str, &size);
753 if (r!=ERROR_SUCCESS)
755 ExpandEnvironmentStringsW(str,path,sizeof(path));
757 TRACE("Starting service %s\n", debugstr_w(path) );
759 data = CreateSemaphoreW(NULL,1,1,_ServiceStartDataW);
762 ERR("Couldn't create data semaphore\n");
765 wait = CreateSemaphoreW(NULL,0,1,_WaitServiceStartW);
768 ERR("Couldn't create wait semaphore\n");
773 * FIXME: lpServiceArgsVectors need to be stored and returned to
774 * the service when it calls StartServiceCtrlDispatcher
776 * Chuck these in a global (yuk) so we can pass them to
777 * another process - address space separation will break this.
780 r = WaitForSingleObject(data,INFINITE);
782 if( r == WAIT_FAILED)
785 FIXME("problematic because of address space separation.\n");
786 start_dwNumServiceArgs = dwNumServiceArgs;
787 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
789 ZeroMemory(&startupinfo,sizeof(STARTUPINFOW));
790 startupinfo.cb = sizeof(STARTUPINFOW);
792 r = CreateProcessW(path,
794 NULL, /* process security attribs */
795 NULL, /* thread security attribs */
796 FALSE, /* inherit handles */
797 0, /* creation flags */
798 NULL, /* environment */
799 NULL, /* current directory */
800 &startupinfo, /* startup info */
801 &procinfo); /* process info */
805 ERR("Couldn't start process\n");
806 /* ReleaseSemaphore(data, 1, NULL);
810 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
811 r = WaitForSingleObject(wait,30000);
813 ReleaseSemaphore(data, 1, NULL);
815 if( r == WAIT_FAILED)
821 /******************************************************************************
822 * QueryServiceStatus [ADVAPI32.@]
830 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
833 DWORD type, val, size;
835 FIXME("(%p,%p) partial\n",hService,lpservicestatus);
837 /* read the service type from the registry */
839 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
842 ERR("invalid Type\n");
845 lpservicestatus->dwServiceType = val;
846 /* FIXME: how are these determined or read from the registry? */
847 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
848 lpservicestatus->dwCurrentState = 1;
849 lpservicestatus->dwControlsAccepted = 0;
850 lpservicestatus->dwWin32ExitCode = NO_ERROR;
851 lpservicestatus->dwServiceSpecificExitCode = 0;
852 lpservicestatus->dwCheckPoint = 0;
853 lpservicestatus->dwWaitHint = 0;
858 /******************************************************************************
859 * QueryServiceStatusEx [ADVAPI32.@]
862 * hService [handle to service]
863 * InfoLevel [information level]
865 * cbBufSize [size of buffer]
866 * pcbBytesNeeded [bytes needed]
868 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
869 LPBYTE lpBuffer, DWORD cbBufSize,
870 LPDWORD pcbBytesNeeded)
873 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
877 /******************************************************************************
878 * QueryServiceConfigA [ADVAPI32.@]
881 QueryServiceConfigA( SC_HANDLE hService,
882 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
883 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
885 FIXME("%p %p %ld %p\n", hService, lpServiceConfig,
886 cbBufSize, pcbBytesNeeded);
890 /******************************************************************************
891 * QueryServiceConfigW [ADVAPI32.@]
894 QueryServiceConfigW( SC_HANDLE hService,
895 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
896 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
898 const WCHAR szDisplayName[] = {
899 'D','i','s','p','l','a','y','N','a','m','e', 0 };
900 const WCHAR szType[] = {'T','y','p','e',0};
901 const WCHAR szStart[] = {'S','t','a','r','t',0};
902 const WCHAR szError[] = {
903 'E','r','r','o','r','C','o','n','t','r','o','l', 0};
904 const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
905 const WCHAR szGroup[] = {'G','r','o','u','p',0};
906 const WCHAR szDependencies[] = {
907 'D','e','p','e','n','d','e','n','c','i','e','s',0};
909 DWORD type, val, sz, total, n;
912 TRACE("%p %p %ld %p\n", hService, lpServiceConfig,
913 cbBufSize, pcbBytesNeeded);
915 /* calculate the size required first */
916 total = sizeof (QUERY_SERVICE_CONFIGW);
919 r = RegQueryValueExW( hService, szImagePath, 0, &type, NULL, &sz );
920 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
924 r = RegQueryValueExW( hService, szGroup, 0, &type, NULL, &sz );
925 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
929 r = RegQueryValueExW( hService, szDependencies, 0, &type, NULL, &sz );
930 if( ( r == ERROR_SUCCESS ) && ( type == REG_MULTI_SZ ) )
934 r = RegQueryValueExW( hService, szStart, 0, &type, NULL, &sz );
935 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
939 r = RegQueryValueExW( hService, szDisplayName, 0, &type, NULL, &sz );
940 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
943 /* if there's not enough memory, return an error */
944 if( total > *pcbBytesNeeded )
946 *pcbBytesNeeded = total;
947 SetLastError( ERROR_INSUFFICIENT_BUFFER );
951 *pcbBytesNeeded = total;
952 ZeroMemory( lpServiceConfig, total );
955 r = RegQueryValueExW( hService, szType, 0, &type, (LPBYTE)&val, &sz );
956 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
957 lpServiceConfig->dwServiceType = val;
960 r = RegQueryValueExW( hService, szStart, 0, &type, (LPBYTE)&val, &sz );
961 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
962 lpServiceConfig->dwStartType = val;
965 r = RegQueryValueExW( hService, szError, 0, &type, (LPBYTE)&val, &sz );
966 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
967 lpServiceConfig->dwErrorControl = val;
969 /* now do the strings */
970 p = (LPBYTE) &lpServiceConfig[1];
971 n = total - sizeof (QUERY_SERVICE_CONFIGW);
974 r = RegQueryValueExW( hService, szImagePath, 0, &type, p, &sz );
975 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
977 lpServiceConfig->lpBinaryPathName = (LPWSTR) p;
983 r = RegQueryValueExW( hService, szGroup, 0, &type, p, &sz );
984 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
986 lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p;
992 r = RegQueryValueExW( hService, szDependencies, 0, &type, p, &sz );
993 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
995 lpServiceConfig->lpDependencies = (LPWSTR) p;
1001 ERR("Buffer overflow!\n");
1003 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1004 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1009 /******************************************************************************
1010 * ChangeServiceConfigW [ADVAPI32.@]
1012 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1013 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1014 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1015 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1017 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1018 hService, dwServiceType, dwStartType, dwErrorControl,
1019 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1020 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1021 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1025 /******************************************************************************
1026 * ChangeServiceConfigA [ADVAPI32.@]
1028 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
1029 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1030 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
1031 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
1033 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1034 hService, dwServiceType, dwStartType, dwErrorControl,
1035 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
1036 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
1037 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
1041 /******************************************************************************
1042 * ChangeServiceConfig2A [ADVAPI32.@]
1044 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
1047 FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo);
1051 /******************************************************************************
1052 * ChangeServiceConfig2W [ADVAPI32.@]
1054 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
1057 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
1059 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1060 LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo;
1061 if (sd->lpDescription)
1063 TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
1064 if (sd->lpDescription[0] == 0)
1065 RegDeleteValueW(hService,szDescription);
1067 RegSetValueExW(hService, szDescription, 0, REG_SZ,
1068 (LPVOID)sd->lpDescription,
1069 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
1073 FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo);