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 r = RegOpenKeyExW(hSCManager, lpServiceName, 0, KEY_ALL_ACCESS, &hKey );
404 if (r!=ERROR_SUCCESS)
407 TRACE("returning %p\n",hKey);
412 /******************************************************************************
413 * CreateServiceW [ADVAPI32.@]
416 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
417 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
418 DWORD dwServiceType, DWORD dwStartType,
419 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
420 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
421 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
427 const WCHAR szDisplayName[] = { 'D','i','s','p','l','a','y','N','a','m','e', 0 };
428 const WCHAR szType[] = {'T','y','p','e',0};
429 const WCHAR szStart[] = {'S','t','a','r','t',0};
430 const WCHAR szError[] = {'E','r','r','o','r','C','o','n','t','r','o','l', 0};
431 const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
432 const WCHAR szGroup[] = {'G','r','o','u','p',0};
433 const WCHAR szDependencies[] = { 'D','e','p','e','n','d','e','n','c','i','e','s',0};
435 FIXME("%p %s %s\n", hSCManager,
436 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
438 r = RegCreateKeyExW(hSCManager, lpServiceName, 0, NULL,
439 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp);
440 if (r!=ERROR_SUCCESS)
443 if (dp != REG_CREATED_NEW_KEY)
448 r = RegSetValueExW(hKey, szDisplayName, 0, REG_SZ, (LPBYTE)lpDisplayName,
449 (strlenW(lpDisplayName)+1)*sizeof(WCHAR) );
450 if (r!=ERROR_SUCCESS)
454 r = RegSetValueExW(hKey, szType, 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
455 if (r!=ERROR_SUCCESS)
458 r = RegSetValueExW(hKey, szStart, 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
459 if (r!=ERROR_SUCCESS)
462 r = RegSetValueExW(hKey, szError, 0, REG_DWORD,
463 (LPVOID)&dwErrorControl, sizeof (DWORD) );
464 if (r!=ERROR_SUCCESS)
469 r = RegSetValueExW(hKey, szImagePath, 0, REG_SZ, (LPBYTE)lpBinaryPathName,
470 (strlenW(lpBinaryPathName)+1)*sizeof(WCHAR) );
471 if (r!=ERROR_SUCCESS)
477 r = RegSetValueExW(hKey, szGroup, 0, REG_SZ, (LPBYTE)lpLoadOrderGroup,
478 (strlenW(lpLoadOrderGroup)+1)*sizeof(WCHAR) );
479 if (r!=ERROR_SUCCESS)
487 /* determine the length of a double null terminated multi string */
489 len += (strlenW(&lpDependencies[len])+1);
490 } while (lpDependencies[len++]);
492 r = RegSetValueExW(hKey, szDependencies, 0, REG_MULTI_SZ,
493 (LPBYTE)lpDependencies, len );
494 if (r!=ERROR_SUCCESS)
500 FIXME("Don't know how to add a Password for a service.\n");
503 if(lpServiceStartName)
505 FIXME("Don't know how to add a ServiceStartName for a service.\n");
512 static inline LPWSTR SERV_dup( LPCSTR str )
519 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
520 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
521 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
525 static inline LPWSTR SERV_dupmulti( LPCSTR str )
533 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
534 n += (strlen( &str[n] ) + 1);
539 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
540 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
544 static inline VOID SERV_free( LPWSTR wstr )
546 HeapFree( GetProcessHeap(), 0, wstr );
549 /******************************************************************************
550 * CreateServiceA [ADVAPI32.@]
553 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
554 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
555 DWORD dwServiceType, DWORD dwStartType,
556 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
557 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
558 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
561 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
562 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
565 TRACE("%p %s %s\n", hSCManager,
566 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
568 lpServiceNameW = SERV_dup( lpServiceName );
569 lpDisplayNameW = SERV_dup( lpDisplayName );
570 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
571 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
572 lpDependenciesW = SERV_dupmulti( lpDependencies );
573 lpServiceStartNameW = SERV_dup( lpServiceStartName );
574 lpPasswordW = SERV_dup( lpPassword );
576 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
577 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
578 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
579 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
581 SERV_free( lpServiceNameW );
582 SERV_free( lpDisplayNameW );
583 SERV_free( lpBinaryPathNameW );
584 SERV_free( lpLoadOrderGroupW );
585 SERV_free( lpDependenciesW );
586 SERV_free( lpServiceStartNameW );
587 SERV_free( lpPasswordW );
593 /******************************************************************************
594 * DeleteService [ADVAPI32.@]
597 * hService [I] Handle to service
603 DeleteService( SC_HANDLE hService )
605 WCHAR valname[MAX_PATH+1];
612 static const WCHAR szDeleted[] = {'D','e','l','e','t','e','d',0};
614 FIXME("(%p): stub\n",hService);
617 /* Clean out the values */
618 rc = RegEnumValueW(hService, index, valname,&size,0,0,0,0);
619 while (rc == ERROR_SUCCESS)
621 RegDeleteValueW(hService,valname);
624 rc = RegEnumValueW(hService, index, valname, &size,0,0,0,0);
627 /* tag for deletion */
628 RegSetValueExW(hService, szDeleted, 0, REG_DWORD, (LPVOID)&value,
631 RegCloseKey(hService);
633 /* find and delete the key */
634 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szServiceManagerKey,0,
635 KEY_ALL_ACCESS, &hKey );
638 rc = RegEnumKeyExW(hKey,0, valname, &size, 0, 0, 0, 0);
639 while (rc == ERROR_SUCCESS)
642 rc = RegOpenKeyExW(hKey,valname,0,KEY_ALL_ACCESS,&checking);
643 if (rc == ERROR_SUCCESS)
646 DWORD size = sizeof(DWORD);
647 rc = RegQueryValueExW(checking, szDeleted , NULL, NULL,
648 (LPVOID)&deleted, &size);
651 RegDeleteValueW(checking,szDeleted);
652 RegDeleteKeyW(hKey,valname);
656 RegCloseKey(checking);
659 rc = RegEnumKeyExW(hKey, index, valname, &size, 0, 0, 0, 0);
667 /******************************************************************************
668 * StartServiceA [ADVAPI32.@]
672 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
673 LPCSTR *lpServiceArgVectors )
676 UNICODE_STRING usBuffer;
679 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
682 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
683 dwNumServiceArgs*sizeof(LPWSTR) );
687 for(i=0; i<dwNumServiceArgs; i++)
689 RtlCreateUnicodeStringFromAsciiz (&usBuffer,lpServiceArgVectors[i]);
690 lpwstr[i]=usBuffer.Buffer;
693 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
697 for(i=0; i<dwNumServiceArgs; i++)
698 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
699 HeapFree(GetProcessHeap(), 0, lpwstr);
706 /******************************************************************************
707 * StartServiceW [ADVAPI32.@]
711 * hService [I] Handle of service
712 * dwNumServiceArgs [I] Number of arguments
713 * lpServiceArgVectors [I] Address of array of argument string pointers
717 * NT implements this function using an obscure RPC call...
719 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
720 * to get things like %SystemRoot%\\System32\\service.exe to load.
722 * Will only work for shared address space. How should the service
723 * args be transferred when address spaces are separated?
725 * Can only start one service at a time.
727 * Has no concept of privilege.
733 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
734 LPCWSTR *lpServiceArgVectors )
736 static const WCHAR _WaitServiceStartW[] = {'A','D','V','A','P','I','_','W',
737 'a','i','t','S','e','r','v','i',
738 'c','e','S','t','a','r','t',0};
739 static const WCHAR _ImagePathW[] = {'I','m','a','g','e','P','a','t','h',0};
741 WCHAR path[MAX_PATH],str[MAX_PATH];
745 PROCESS_INFORMATION procinfo;
746 STARTUPINFOW startupinfo;
747 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,
748 lpServiceArgVectors);
751 r = RegQueryValueExW(hService, _ImagePathW, NULL, &type, (LPVOID)str, &size);
752 if (r!=ERROR_SUCCESS)
754 ExpandEnvironmentStringsW(str,path,sizeof(path));
756 TRACE("Starting service %s\n", debugstr_w(path) );
758 data = CreateSemaphoreW(NULL,1,1,_ServiceStartDataW);
761 ERR("Couldn't create data semaphore\n");
764 wait = CreateSemaphoreW(NULL,0,1,_WaitServiceStartW);
767 ERR("Couldn't create wait semaphore\n");
772 * FIXME: lpServiceArgsVectors need to be stored and returned to
773 * the service when it calls StartServiceCtrlDispatcher
775 * Chuck these in a global (yuk) so we can pass them to
776 * another process - address space separation will break this.
779 r = WaitForSingleObject(data,INFINITE);
781 if( r == WAIT_FAILED)
784 FIXME("problematic because of address space separation.\n");
785 start_dwNumServiceArgs = dwNumServiceArgs;
786 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
788 ZeroMemory(&startupinfo,sizeof(STARTUPINFOW));
789 startupinfo.cb = sizeof(STARTUPINFOW);
791 r = CreateProcessW(path,
793 NULL, /* process security attribs */
794 NULL, /* thread security attribs */
795 FALSE, /* inherit handles */
796 0, /* creation flags */
797 NULL, /* environment */
798 NULL, /* current directory */
799 &startupinfo, /* startup info */
800 &procinfo); /* process info */
804 ERR("Couldn't start process\n");
805 /* ReleaseSemaphore(data, 1, NULL);
809 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
810 r = WaitForSingleObject(wait,30000);
812 ReleaseSemaphore(data, 1, NULL);
814 if( r == WAIT_FAILED)
820 /******************************************************************************
821 * QueryServiceStatus [ADVAPI32.@]
829 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
832 DWORD type, val, size;
834 FIXME("(%p,%p) partial\n",hService,lpservicestatus);
836 /* read the service type from the registry */
838 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
841 ERR("invalid Type\n");
844 lpservicestatus->dwServiceType = val;
845 /* FIXME: how are these determined or read from the registry? */
846 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
847 lpservicestatus->dwCurrentState = 1;
848 lpservicestatus->dwControlsAccepted = 0;
849 lpservicestatus->dwWin32ExitCode = NO_ERROR;
850 lpservicestatus->dwServiceSpecificExitCode = 0;
851 lpservicestatus->dwCheckPoint = 0;
852 lpservicestatus->dwWaitHint = 0;
857 /******************************************************************************
858 * QueryServiceStatusEx [ADVAPI32.@]
861 * hService [handle to service]
862 * InfoLevel [information level]
864 * cbBufSize [size of buffer]
865 * pcbBytesNeeded [bytes needed]
867 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
868 LPBYTE lpBuffer, DWORD cbBufSize,
869 LPDWORD pcbBytesNeeded)
872 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
876 /******************************************************************************
877 * QueryServiceConfigA [ADVAPI32.@]
880 QueryServiceConfigA( SC_HANDLE hService,
881 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
882 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
884 FIXME("%p %p %ld %p\n", hService, lpServiceConfig,
885 cbBufSize, pcbBytesNeeded);
889 /******************************************************************************
890 * QueryServiceConfigW [ADVAPI32.@]
893 QueryServiceConfigW( SC_HANDLE hService,
894 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
895 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
897 const WCHAR szDisplayName[] = {
898 'D','i','s','p','l','a','y','N','a','m','e', 0 };
899 const WCHAR szType[] = {'T','y','p','e',0};
900 const WCHAR szStart[] = {'S','t','a','r','t',0};
901 const WCHAR szError[] = {
902 'E','r','r','o','r','C','o','n','t','r','o','l', 0};
903 const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
904 const WCHAR szGroup[] = {'G','r','o','u','p',0};
905 const WCHAR szDependencies[] = {
906 'D','e','p','e','n','d','e','n','c','i','e','s',0};
908 DWORD type, val, sz, total, n;
911 TRACE("%p %p %ld %p\n", hService, lpServiceConfig,
912 cbBufSize, pcbBytesNeeded);
914 /* calculate the size required first */
915 total = sizeof (QUERY_SERVICE_CONFIGW);
918 r = RegQueryValueExW( hService, szImagePath, 0, &type, NULL, &sz );
919 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
923 r = RegQueryValueExW( hService, szGroup, 0, &type, NULL, &sz );
924 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
928 r = RegQueryValueExW( hService, szDependencies, 0, &type, NULL, &sz );
929 if( ( r == ERROR_SUCCESS ) && ( type == REG_MULTI_SZ ) )
933 r = RegQueryValueExW( hService, szStart, 0, &type, NULL, &sz );
934 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
938 r = RegQueryValueExW( hService, szDisplayName, 0, &type, NULL, &sz );
939 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
942 /* if there's not enough memory, return an error */
943 if( total > *pcbBytesNeeded )
945 *pcbBytesNeeded = total;
946 SetLastError( ERROR_INSUFFICIENT_BUFFER );
950 *pcbBytesNeeded = total;
951 ZeroMemory( lpServiceConfig, total );
954 r = RegQueryValueExW( hService, szType, 0, &type, (LPBYTE)&val, &sz );
955 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
956 lpServiceConfig->dwServiceType = val;
959 r = RegQueryValueExW( hService, szStart, 0, &type, (LPBYTE)&val, &sz );
960 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
961 lpServiceConfig->dwStartType = val;
964 r = RegQueryValueExW( hService, szError, 0, &type, (LPBYTE)&val, &sz );
965 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
966 lpServiceConfig->dwErrorControl = val;
968 /* now do the strings */
969 p = (LPBYTE) &lpServiceConfig[1];
970 n = total - sizeof (QUERY_SERVICE_CONFIGW);
973 r = RegQueryValueExW( hService, szImagePath, 0, &type, p, &sz );
974 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
976 lpServiceConfig->lpBinaryPathName = (LPWSTR) p;
982 r = RegQueryValueExW( hService, szGroup, 0, &type, p, &sz );
983 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
985 lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p;
991 r = RegQueryValueExW( hService, szDependencies, 0, &type, p, &sz );
992 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
994 lpServiceConfig->lpDependencies = (LPWSTR) p;
1000 ERR("Buffer overflow!\n");
1002 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1003 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1008 /******************************************************************************
1009 * ChangeServiceConfigW [ADVAPI32.@]
1011 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1012 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1013 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1014 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1016 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1017 hService, dwServiceType, dwStartType, dwErrorControl,
1018 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1019 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1020 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1024 /******************************************************************************
1025 * ChangeServiceConfigA [ADVAPI32.@]
1027 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
1028 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1029 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
1030 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
1032 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1033 hService, dwServiceType, dwStartType, dwErrorControl,
1034 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
1035 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
1036 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
1040 /******************************************************************************
1041 * ChangeServiceConfig2A [ADVAPI32.@]
1043 BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
1046 FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo);
1050 /******************************************************************************
1051 * ChangeServiceConfig2W [ADVAPI32.@]
1053 BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
1056 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
1058 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1059 LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo;
1060 if (sd->lpDescription)
1062 TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
1063 if (sd->lpDescription[0] == 0)
1064 RegDeleteValueW(hService,szDescription);
1066 RegSetValueExW(hService, szDescription, 0, REG_SZ,
1067 (LPVOID)sd->lpDescription,
1068 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
1072 FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo);