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
);