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};
44 /******************************************************************************
45 * EnumServicesStatusA [ADVAPI32.@]
48 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
49 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
50 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
51 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
52 { FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
53 dwServiceType, dwServiceState, lpServices, cbBufSize,
54 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
55 SetLastError (ERROR_ACCESS_DENIED);
59 /******************************************************************************
60 * EnumServicesStatusW [ADVAPI32.@]
63 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
64 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
65 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
66 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
67 { FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
68 dwServiceType, dwServiceState, lpServices, cbBufSize,
69 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
70 SetLastError (ERROR_ACCESS_DENIED);
74 /******************************************************************************
75 * StartServiceCtrlDispatcherA [ADVAPI32.@]
78 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
80 LPSERVICE_MAIN_FUNCTIONA fpMain;
82 DWORD dwNumServiceArgs ;
87 TRACE("(%p)\n", servent);
88 wait = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW);
91 ERR("Couldn't find wait semaphore\n");
92 ERR("perhaps you need to start services using StartService\n");
96 dwNumServiceArgs = start_dwNumServiceArgs;
97 lpArgVecW = start_lpServiceArgVectors;
99 ReleaseSemaphore(wait, 1, NULL);
101 /* Convert the Unicode arg vectors back to ASCII */
103 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
104 dwNumServiceArgs*sizeof(LPSTR) );
108 for(i=0; i<dwNumServiceArgs; i++)
109 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
111 /* FIXME: should we blindly start all services? */
112 while (servent->lpServiceName) {
113 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
114 fpMain = servent->lpServiceProc;
116 /* try to start the service */
117 fpMain( dwNumServiceArgs, lpArgVecA);
124 /* free arg strings */
125 for(i=0; i<dwNumServiceArgs; i++)
126 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
127 HeapFree(GetProcessHeap(), 0, lpArgVecA);
133 /******************************************************************************
134 * StartServiceCtrlDispatcherW [ADVAPI32.@]
140 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
142 LPSERVICE_MAIN_FUNCTIONW fpMain;
144 DWORD dwNumServiceArgs ;
145 LPWSTR *lpServiceArgVectors ;
147 TRACE("(%p)\n", servent);
148 wait = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW);
151 ERR("Couldn't find wait semaphore\n");
152 ERR("perhaps you need to start services using StartService\n");
156 dwNumServiceArgs = start_dwNumServiceArgs;
157 lpServiceArgVectors = start_lpServiceArgVectors;
159 ReleaseSemaphore(wait, 1, NULL);
161 /* FIXME: should we blindly start all services? */
162 while (servent->lpServiceName) {
163 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
164 fpMain = servent->lpServiceProc;
166 /* try to start the service */
167 fpMain( dwNumServiceArgs, lpServiceArgVectors);
175 /******************************************************************************
176 * LockServiceDatabase [ADVAPI32.@]
178 LPVOID WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
180 FIXME("%p\n",hSCManager);
181 return (SC_HANDLE)0xcacacafe;
184 /******************************************************************************
185 * UnlockServiceDatabase [ADVAPI32.@]
187 BOOL WINAPI UnlockServiceDatabase (LPVOID ScLock)
189 FIXME(": %p\n",ScLock);
193 /******************************************************************************
194 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
196 SERVICE_STATUS_HANDLE WINAPI
197 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
198 LPHANDLER_FUNCTION lpfHandler )
199 { FIXME("%s %p\n", lpServiceName, lpfHandler);
203 /******************************************************************************
204 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
210 SERVICE_STATUS_HANDLE WINAPI
211 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
212 LPHANDLER_FUNCTION lpfHandler )
213 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
217 /******************************************************************************
218 * SetServiceStatus [ADVAPI32.@]
225 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
226 { FIXME("0x%lx %p\n",hService, lpStatus);
227 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
228 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
229 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
230 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
231 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
232 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
233 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
237 /******************************************************************************
238 * OpenSCManagerA [ADVAPI32.@]
241 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
242 DWORD dwDesiredAccess )
244 UNICODE_STRING lpMachineNameW;
245 UNICODE_STRING lpDatabaseNameW;
248 RtlCreateUnicodeStringFromAsciiz (&lpMachineNameW,lpMachineName);
249 RtlCreateUnicodeStringFromAsciiz (&lpDatabaseNameW,lpDatabaseName);
250 ret = OpenSCManagerW(lpMachineNameW.Buffer,lpDatabaseNameW.Buffer, dwDesiredAccess);
251 RtlFreeUnicodeString(&lpDatabaseNameW);
252 RtlFreeUnicodeString(&lpMachineNameW);
256 /******************************************************************************
257 * OpenSCManagerW [ADVAPI32.@]
258 * Establishes a connection to the service control manager and opens database
261 * This should return a SC_HANDLE
264 * lpMachineName [I] Pointer to machine name string
265 * lpDatabaseName [I] Pointer to database name string
266 * dwDesiredAccess [I] Type of access
269 * Success: Handle to service control manager database
273 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
274 DWORD dwDesiredAccess )
276 const WCHAR szKey[] = { 'S','y','s','t','e','m','\\',
277 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
278 'S','e','r','v','i','c','e','s','\\',0 };
279 HKEY hReg, hKey = NULL;
282 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
283 debugstr_w(lpDatabaseName), dwDesiredAccess);
286 * FIXME: what is lpDatabaseName?
287 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
288 * docs, but what if it isn't?
291 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
292 if (r==ERROR_SUCCESS)
294 r = RegOpenKeyExW(hReg, szKey, 0, dwDesiredAccess, &hKey );
298 TRACE("returning %p\n", hKey);
304 /******************************************************************************
305 * AllocateLocallyUniqueId [ADVAPI32.@]
311 AllocateLocallyUniqueId( PLUID lpluid )
313 lpluid->LowPart = time(NULL);
314 lpluid->HighPart = 0;
319 /******************************************************************************
320 * ControlService [ADVAPI32.@]
321 * Sends a control code to a Win32-based service.
331 ControlService( SC_HANDLE hService, DWORD dwControl,
332 LPSERVICE_STATUS lpServiceStatus )
334 FIXME("(%p,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
339 /******************************************************************************
340 * CloseServiceHandle [ADVAPI32.@]
341 * Close handle to service or service control manager
344 * hSCObject [I] Handle to service or service control manager database
349 CloseServiceHandle( SC_HANDLE hSCObject )
351 TRACE("(%p)\n", hSCObject);
353 RegCloseKey(hSCObject);
359 /******************************************************************************
360 * OpenServiceA [ADVAPI32.@]
363 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
364 DWORD dwDesiredAccess )
366 UNICODE_STRING lpServiceNameW;
368 RtlCreateUnicodeStringFromAsciiz (&lpServiceNameW,lpServiceName);
370 TRACE("Request for service %s\n",lpServiceName);
373 ret = OpenServiceW( hSCManager, lpServiceNameW.Buffer, dwDesiredAccess);
374 RtlFreeUnicodeString(&lpServiceNameW);
379 /******************************************************************************
380 * OpenServiceW [ADVAPI32.@]
381 * Opens a handle to an existing service
389 * Success: Handle to the service
393 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
394 DWORD dwDesiredAccess)
399 TRACE("(%p,%p,%ld)\n",hSCManager, lpServiceName,
402 /* FIXME: dwDesiredAccess may need some processing */
403 r = RegOpenKeyExW(hSCManager, lpServiceName, 0, dwDesiredAccess, &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, dwDesiredAccess, NULL, &hKey, &dp);
440 if (r!=ERROR_SUCCESS)
442 if (dp != REG_CREATED_NEW_KEY)
447 r = RegSetValueExW(hKey, szDisplayName, 0, REG_SZ, (LPBYTE)lpDisplayName,
448 (strlenW(lpDisplayName)+1)*sizeof(WCHAR) );
449 if (r!=ERROR_SUCCESS)
453 r = RegSetValueExW(hKey, szType, 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
454 if (r!=ERROR_SUCCESS)
457 r = RegSetValueExW(hKey, szStart, 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
458 if (r!=ERROR_SUCCESS)
461 r = RegSetValueExW(hKey, szError, 0, REG_DWORD,
462 (LPVOID)&dwErrorControl, sizeof (DWORD) );
463 if (r!=ERROR_SUCCESS)
468 r = RegSetValueExW(hKey, szImagePath, 0, REG_SZ, (LPBYTE)lpBinaryPathName,
469 (strlenW(lpBinaryPathName)+1)*sizeof(WCHAR) );
470 if (r!=ERROR_SUCCESS)
476 r = RegSetValueExW(hKey, szGroup, 0, REG_SZ, (LPBYTE)lpLoadOrderGroup,
477 (strlenW(lpLoadOrderGroup)+1)*sizeof(WCHAR) );
478 if (r!=ERROR_SUCCESS)
486 /* determine the length of a double null terminated multi string */
488 len += (strlenW(&lpDependencies[len])+1);
489 } while (lpDependencies[len++]);
491 r = RegSetValueExW(hKey, szDependencies, 0, REG_MULTI_SZ,
492 (LPBYTE)lpDependencies, len );
493 if (r!=ERROR_SUCCESS)
499 FIXME("Don't know how to add a Password for a service.\n");
502 if(lpServiceStartName)
504 FIXME("Don't know how to add a ServiceStartName for a service.\n");
511 static inline LPWSTR SERV_dup( LPCSTR str )
518 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
519 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
520 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
524 static inline LPWSTR SERV_dupmulti( LPCSTR str )
530 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
531 n += (strlen( &str[n] ) + 1);
536 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
537 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
541 static inline VOID SERV_free( LPWSTR wstr )
543 HeapFree( GetProcessHeap(), 0, wstr );
546 /******************************************************************************
547 * CreateServiceA [ADVAPI32.@]
550 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
551 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
552 DWORD dwServiceType, DWORD dwStartType,
553 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
554 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
555 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
558 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
559 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
562 TRACE("%p %s %s\n", hSCManager,
563 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
565 lpServiceNameW = SERV_dup( lpServiceName );
566 lpDisplayNameW = SERV_dup( lpDisplayName );
567 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
568 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
569 lpDependenciesW = SERV_dupmulti( lpDependencies );
570 lpServiceStartNameW = SERV_dup( lpServiceStartName );
571 lpPasswordW = SERV_dup( lpPassword );
573 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
574 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
575 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
576 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
578 SERV_free( lpServiceNameW );
579 SERV_free( lpDisplayNameW );
580 SERV_free( lpBinaryPathNameW );
581 SERV_free( lpLoadOrderGroupW );
582 SERV_free( lpDependenciesW );
583 SERV_free( lpServiceStartNameW );
584 SERV_free( lpPasswordW );
590 /******************************************************************************
591 * DeleteService [ADVAPI32.@]
594 * hService [I] Handle to service
600 DeleteService( SC_HANDLE hService )
602 FIXME("(%p): stub\n",hService);
607 /******************************************************************************
608 * StartServiceA [ADVAPI32.@]
612 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
613 LPCSTR *lpServiceArgVectors )
616 UNICODE_STRING usBuffer;
619 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
622 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
623 dwNumServiceArgs*sizeof(LPWSTR) );
627 for(i=0; i<dwNumServiceArgs; i++)
629 RtlCreateUnicodeStringFromAsciiz (&usBuffer,lpServiceArgVectors[i]);
630 lpwstr[i]=usBuffer.Buffer;
633 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
637 for(i=0; i<dwNumServiceArgs; i++)
638 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
639 HeapFree(GetProcessHeap(), 0, lpwstr);
646 /******************************************************************************
647 * StartServiceW [ADVAPI32.@]
651 * hService [I] Handle of service
652 * dwNumServiceArgs [I] Number of arguments
653 * lpServiceArgVectors [I] Address of array of argument string pointers
657 * NT implements this function using an obscure RPC call...
659 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
660 * to get things like %SystemRoot%\\System32\\service.exe to load.
662 * Will only work for shared address space. How should the service
663 * args be transferred when address spaces are separated?
665 * Can only start one service at a time.
667 * Has no concept of privilege.
673 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
674 LPCWSTR *lpServiceArgVectors )
676 static const WCHAR _WaitServiceStartW[] = {'A','D','V','A','P','I','_','W',
677 'a','i','t','S','e','r','v','i',
678 'c','e','S','t','a','r','t',0};
679 static const WCHAR _ImagePathW[] = {'I','m','a','g','e','P','a','t','h',0};
681 WCHAR path[MAX_PATH],str[MAX_PATH];
685 PROCESS_INFORMATION procinfo;
686 STARTUPINFOW startupinfo;
687 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,
688 lpServiceArgVectors);
691 r = RegQueryValueExW(hService, _ImagePathW, NULL, &type, (LPVOID)str, &size);
692 if (r!=ERROR_SUCCESS)
694 ExpandEnvironmentStringsW(str,path,sizeof(path));
696 TRACE("Starting service %s\n", debugstr_w(path) );
698 data = CreateSemaphoreW(NULL,1,1,_ServiceStartDataW);
701 ERR("Couldn't create data semaphore\n");
704 wait = CreateSemaphoreW(NULL,0,1,_WaitServiceStartW);
707 ERR("Couldn't create wait semaphore\n");
712 * FIXME: lpServiceArgsVectors need to be stored and returned to
713 * the service when it calls StartServiceCtrlDispatcher
715 * Chuck these in a global (yuk) so we can pass them to
716 * another process - address space separation will break this.
719 r = WaitForSingleObject(data,INFINITE);
721 if( r == WAIT_FAILED)
724 FIXME("problematic because of address space separation.\n");
725 start_dwNumServiceArgs = dwNumServiceArgs;
726 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
728 ZeroMemory(&startupinfo,sizeof(STARTUPINFOW));
729 startupinfo.cb = sizeof(STARTUPINFOW);
731 r = CreateProcessW(path,
733 NULL, /* process security attribs */
734 NULL, /* thread security attribs */
735 FALSE, /* inherit handles */
736 0, /* creation flags */
737 NULL, /* environment */
738 NULL, /* current directory */
739 &startupinfo, /* startup info */
740 &procinfo); /* process info */
744 ERR("Couldn't start process\n");
745 /* ReleaseSemaphore(data, 1, NULL);
749 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
750 r = WaitForSingleObject(wait,30000);
752 ReleaseSemaphore(data, 1, NULL);
754 if( r == WAIT_FAILED)
760 /******************************************************************************
761 * QueryServiceStatus [ADVAPI32.@]
769 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
772 DWORD type, val, size;
774 FIXME("(%p,%p) partial\n",hService,lpservicestatus);
776 /* read the service type from the registry */
778 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
781 ERR("invalid Type\n");
784 lpservicestatus->dwServiceType = val;
785 /* FIXME: how are these determined or read from the registry? */
786 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
787 lpservicestatus->dwCurrentState = 1;
788 lpservicestatus->dwControlsAccepted = 0;
789 lpservicestatus->dwWin32ExitCode = NO_ERROR;
790 lpservicestatus->dwServiceSpecificExitCode = 0;
791 lpservicestatus->dwCheckPoint = 0;
792 lpservicestatus->dwWaitHint = 0;
797 /******************************************************************************
798 * QueryServiceStatusEx [ADVAPI32.@]
801 * hService [handle to service]
802 * InfoLevel [information level]
804 * cbBufSize [size of buffer]
805 * pcbBytesNeeded [bytes needed]
807 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
808 LPBYTE lpBuffer, DWORD cbBufSize,
809 LPDWORD pcbBytesNeeded)
812 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
816 /******************************************************************************
817 * QueryServiceConfigA [ADVAPI32.@]
820 QueryServiceConfigA( SC_HANDLE hService,
821 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
822 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
824 FIXME("%p %p %ld %p\n", hService, lpServiceConfig,
825 cbBufSize, pcbBytesNeeded);
829 /******************************************************************************
830 * QueryServiceConfigW [ADVAPI32.@]
833 QueryServiceConfigW( SC_HANDLE hService,
834 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
835 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
837 const WCHAR szDisplayName[] = {
838 'D','i','s','p','l','a','y','N','a','m','e', 0 };
839 const WCHAR szType[] = {'T','y','p','e',0};
840 const WCHAR szStart[] = {'S','t','a','r','t',0};
841 const WCHAR szError[] = {
842 'E','r','r','o','r','C','o','n','t','r','o','l', 0};
843 const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
844 const WCHAR szGroup[] = {'G','r','o','u','p',0};
845 const WCHAR szDependencies[] = {
846 'D','e','p','e','n','d','e','n','c','i','e','s',0};
848 DWORD type, val, sz, total, n;
851 TRACE("%p %p %ld %p\n", hService, lpServiceConfig,
852 cbBufSize, pcbBytesNeeded);
854 /* calculate the size required first */
855 total = sizeof (QUERY_SERVICE_CONFIGW);
858 r = RegQueryValueExW( hService, szImagePath, 0, &type, NULL, &sz );
859 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
863 r = RegQueryValueExW( hService, szGroup, 0, &type, NULL, &sz );
864 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
868 r = RegQueryValueExW( hService, szDependencies, 0, &type, NULL, &sz );
869 if( ( r == ERROR_SUCCESS ) && ( type == REG_MULTI_SZ ) )
873 r = RegQueryValueExW( hService, szStart, 0, &type, NULL, &sz );
874 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
878 r = RegQueryValueExW( hService, szDisplayName, 0, &type, NULL, &sz );
879 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
882 /* if there's not enough memory, return an error */
883 if( total > *pcbBytesNeeded )
885 *pcbBytesNeeded = total;
886 SetLastError( ERROR_INSUFFICIENT_BUFFER );
890 *pcbBytesNeeded = total;
891 ZeroMemory( lpServiceConfig, total );
894 r = RegQueryValueExW( hService, szType, 0, &type, (LPBYTE)&val, &sz );
895 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
896 lpServiceConfig->dwServiceType = val;
899 r = RegQueryValueExW( hService, szStart, 0, &type, (LPBYTE)&val, &sz );
900 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
901 lpServiceConfig->dwStartType = val;
904 r = RegQueryValueExW( hService, szError, 0, &type, (LPBYTE)&val, &sz );
905 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
906 lpServiceConfig->dwErrorControl = val;
908 /* now do the strings */
909 p = (LPBYTE) &lpServiceConfig[1];
910 n = total - sizeof (QUERY_SERVICE_CONFIGW);
913 r = RegQueryValueExW( hService, szImagePath, 0, &type, p, &sz );
914 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
916 lpServiceConfig->lpBinaryPathName = (LPWSTR) p;
922 r = RegQueryValueExW( hService, szGroup, 0, &type, p, &sz );
923 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
925 lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p;
931 r = RegQueryValueExW( hService, szDependencies, 0, &type, p, &sz );
932 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
934 lpServiceConfig->lpDependencies = (LPWSTR) p;
940 ERR("Buffer overflow!\n");
942 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
943 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
948 /******************************************************************************
949 * ChangeServiceConfigW [ADVAPI32.@]
951 BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
952 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
953 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
954 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
956 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
957 hService, dwServiceType, dwStartType, dwErrorControl,
958 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
959 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
960 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
964 /******************************************************************************
965 * ChangeServiceConfigA [ADVAPI32.@]
967 BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
968 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
969 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
970 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
972 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
973 hService, dwServiceType, dwStartType, dwErrorControl,
974 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
975 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
976 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );