blob: cccab1f9b9f9ad529336cd1de6bbc5d15b9e7bac [file] [log] [blame]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +00001/*
2 * Win32 advapi functions
3 *
4 * Copyright 1995 Sven Verdoolaege
5 */
6
Juergen Schmiedf7b0de31999-01-03 12:48:29 +00007#include <time.h>
Patrik Stridvall4a739731999-07-04 11:01:21 +00008
Jim Aston2e1cafa1999-03-14 16:35:05 +00009#include "windef.h"
Patrik Stridvall4a739731999-07-04 11:01:21 +000010#include "winsvc.h"
Marcus Meissner317af321999-02-17 13:51:06 +000011#include "winerror.h"
Michael McCormack75a84131999-11-21 00:58:14 +000012#include "winreg.h"
Marcus Meissner317af321999-02-17 13:51:06 +000013#include "heap.h"
Alexandre Julliard9fe7a251999-05-14 08:17:14 +000014#include "debugtools.h"
Juergen Schmiedf7b0de31999-01-03 12:48:29 +000015
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000016DEFAULT_DEBUG_CHANNEL(advapi)
17
Michael McCormack0c0f7d31999-12-04 04:03:45 +000018static DWORD start_dwNumServiceArgs;
19static LPWSTR *start_lpServiceArgVectors;
20
Matthew Beckere905f3c1999-01-28 13:46:25 +000021/******************************************************************************
Michael McCormack0c0f7d31999-12-04 04:03:45 +000022 * EnumServicesStatusA [ADVAPI32.38]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +000023 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000024BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +000025EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
26 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
Matthew Beckere905f3c1999-01-28 13:46:25 +000027 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
28 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
Alexandre Julliard9fe7a251999-05-14 08:17:14 +000029{ FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
Juergen Schmiedf7b0de31999-01-03 12:48:29 +000030 dwServiceType, dwServiceState, lpServices, cbBufSize,
31 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
32 SetLastError (ERROR_ACCESS_DENIED);
33 return 0;
34}
Matthew Beckere905f3c1999-01-28 13:46:25 +000035
36/******************************************************************************
Michael McCormack0c0f7d31999-12-04 04:03:45 +000037 * StartServiceCtrlDispatcherA [ADVAPI32.196]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +000038 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000039BOOL WINAPI
40StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
Peter Schlaile096aba21999-11-21 01:01:04 +000041{
Michael McCormack0c0f7d31999-12-04 04:03:45 +000042 LPSERVICE_MAIN_FUNCTIONA fpMain;
43 HANDLE wait;
44 DWORD dwNumServiceArgs ;
45 LPWSTR *lpArgVecW;
46 LPSTR *lpArgVecA;
47 int i;
48
49 TRACE("(%p)\n", servent);
50 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
51 if(wait == 0)
52 {
53 ERR("Couldn't find wait semaphore\n");
54 ERR("perhaps you need to start services using StartService\n");
55 return FALSE;
56 }
Juergen Schmiedf7b0de31999-01-03 12:48:29 +000057
Michael McCormack0c0f7d31999-12-04 04:03:45 +000058 dwNumServiceArgs = start_dwNumServiceArgs;
59 lpArgVecW = start_lpServiceArgVectors;
60
61 ReleaseSemaphore(wait, 1, NULL);
62
63 /* Convert the Unicode arg vectors back to ASCII */
64 if(dwNumServiceArgs)
65 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
66 dwNumServiceArgs*sizeof(LPSTR) );
67 else
68 lpArgVecA = NULL;
69
70 for(i=0; i<dwNumServiceArgs; i++)
71 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
72
73 /* FIXME: should we blindly start all services? */
74 while (servent->lpServiceName) {
75 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
76 fpMain = servent->lpServiceProc;
77
78 /* try to start the service */
79 fpMain( dwNumServiceArgs, lpArgVecA);
80
81 servent++;
82 }
83
84 if(dwNumServiceArgs)
85 {
86 /* free arg strings */
87 for(i=0; i<dwNumServiceArgs; i++)
88 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
89 HeapFree(GetProcessHeap(), 0, lpArgVecA);
90 }
91
92 return TRUE;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +000093}
94
Matthew Beckere905f3c1999-01-28 13:46:25 +000095/******************************************************************************
Michael McCormack0c0f7d31999-12-04 04:03:45 +000096 * StartServiceCtrlDispatcherW [ADVAPI32.197]
Matthew Beckere905f3c1999-01-28 13:46:25 +000097 *
98 * PARAMS
99 * servent []
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000100 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000101BOOL WINAPI
102StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
Peter Schlaile096aba21999-11-21 01:01:04 +0000103{
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000104 LPSERVICE_MAIN_FUNCTIONW fpMain;
105 HANDLE wait;
106 DWORD dwNumServiceArgs ;
107 LPWSTR *lpServiceArgVectors ;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000108
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000109 TRACE("(%p)\n", servent);
110 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
111 if(wait == 0)
112 {
113 ERR("Couldn't find wait semaphore\n");
114 ERR("perhaps you need to start services using StartService\n");
115 return FALSE;
116 }
117
118 dwNumServiceArgs = start_dwNumServiceArgs;
119 lpServiceArgVectors = start_lpServiceArgVectors;
120
121 ReleaseSemaphore(wait, 1, NULL);
122
123 /* FIXME: should we blindly start all services? */
124 while (servent->lpServiceName) {
125 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
126 fpMain = servent->lpServiceProc;
127
128 /* try to start the service */
129 fpMain( dwNumServiceArgs, lpServiceArgVectors);
130
131 servent++;
132 }
133
134 return TRUE;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000135}
136
Matthew Becker6d594451999-01-30 12:54:32 +0000137/******************************************************************************
Matthew Beckere905f3c1999-01-28 13:46:25 +0000138 * RegisterServiceCtrlHandlerA [ADVAPI32.176]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000139 */
Matthew Beckere905f3c1999-01-28 13:46:25 +0000140SERVICE_STATUS_HANDLE WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000141RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000142 LPHANDLER_FUNCTION lpfHandler )
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000143{ FIXME("%s %p\n", lpServiceName, lpfHandler);
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000144 return 0xcacacafe;
145}
Matthew Beckere905f3c1999-01-28 13:46:25 +0000146
147/******************************************************************************
148 * RegisterServiceCtrlHandlerW [ADVAPI32.177]
149 *
150 * PARAMS
151 * lpServiceName []
152 * lpfHandler []
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000153 */
Matthew Beckere905f3c1999-01-28 13:46:25 +0000154SERVICE_STATUS_HANDLE WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000155RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000156 LPHANDLER_FUNCTION lpfHandler )
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000157{ FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000158 return 0xcacacafe;
159}
Matthew Beckere905f3c1999-01-28 13:46:25 +0000160
161/******************************************************************************
162 * SetServiceStatus [ADVAPI32.192]
163 *
164 * PARAMS
165 * hService []
166 * lpStatus []
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000167 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000168BOOL WINAPI
Matthew Beckere905f3c1999-01-28 13:46:25 +0000169SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000170{ FIXME("%lx %p\n",hService, lpStatus);
171 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
172 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
173 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
174 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
175 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
176 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
177 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000178 return TRUE;
179}
180
181/******************************************************************************
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000182 * OpenSCManagerA [ADVAPI32.110]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000183 */
Patrik Stridvall4a739731999-07-04 11:01:21 +0000184SC_HANDLE WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +0000185OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000186 DWORD dwDesiredAccess )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000187{
188 LPWSTR lpMachineNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpMachineName);
189 LPWSTR lpDatabaseNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpDatabaseName);
Alexandre Julliarda3960291999-02-26 11:11:13 +0000190 DWORD ret = OpenSCManagerW(lpMachineNameW,lpDatabaseNameW,
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000191 dwDesiredAccess);
192 HeapFree(GetProcessHeap(),0,lpDatabaseNameW);
193 HeapFree(GetProcessHeap(),0,lpMachineNameW);
194 return ret;
195}
196
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000197/******************************************************************************
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000198 * OpenSCManagerW [ADVAPI32.111]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000199 * Establishes a connection to the service control manager and opens database
200 *
201 * NOTES
Matthew Beckere905f3c1999-01-28 13:46:25 +0000202 * This should return a SC_HANDLE
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000203 *
204 * PARAMS
Matthew Beckere905f3c1999-01-28 13:46:25 +0000205 * lpMachineName [I] Pointer to machine name string
206 * lpDatabaseName [I] Pointer to database name string
207 * dwDesiredAccess [I] Type of access
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000208 *
209 * RETURNS
Matthew Beckere905f3c1999-01-28 13:46:25 +0000210 * Success: Handle to service control manager database
211 * Failure: NULL
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000212 */
Patrik Stridvall4a739731999-07-04 11:01:21 +0000213SC_HANDLE WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +0000214OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000215 DWORD dwDesiredAccess )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000216{
Michael McCormack75a84131999-11-21 00:58:14 +0000217 HKEY hKey;
218 LONG r;
219
220 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000221 debugstr_w(lpDatabaseName), dwDesiredAccess);
Michael McCormack75a84131999-11-21 00:58:14 +0000222
223 /*
224 * FIXME: what is lpDatabaseName?
225 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
226 * docs, but what if it isn't?
227 */
228
229 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey);
230 if (r!=ERROR_SUCCESS)
231 return 0;
232
233 TRACE("returning %x\n",hKey);
234
235 return hKey;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000236}
237
238
Matthew Beckere905f3c1999-01-28 13:46:25 +0000239/******************************************************************************
240 * AllocateLocallyUniqueId [ADVAPI32.12]
241 *
242 * PARAMS
243 * lpluid []
244 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000245BOOL WINAPI
Juergen Schmied1ed51af1999-02-12 17:47:07 +0000246AllocateLocallyUniqueId( PLUID lpluid )
Matthew Beckere905f3c1999-01-28 13:46:25 +0000247{
Patrik Stridvall311e4561999-09-19 14:20:33 +0000248 lpluid->s.LowPart = time(NULL);
249 lpluid->s.HighPart = 0;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000250 return TRUE;
251}
252
253
254/******************************************************************************
255 * ControlService [ADVAPI32.23]
256 * Sends a control code to a Win32-based service.
257 *
Matthew Beckere905f3c1999-01-28 13:46:25 +0000258 * PARAMS
259 * hService []
260 * dwControl []
261 * lpServiceStatus []
262 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000263 * RETURNS STD
264 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000265BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000266ControlService( SC_HANDLE hService, DWORD dwControl,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000267 LPSERVICE_STATUS lpServiceStatus )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000268{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000269 FIXME("(%d,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000270 return TRUE;
271}
272
273
274/******************************************************************************
275 * CloseServiceHandle [ADVAPI32.22]
276 * Close handle to service or service control manager
277 *
278 * PARAMS
Matthew Beckere905f3c1999-01-28 13:46:25 +0000279 * hSCObject [I] Handle to service or service control manager database
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000280 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000281 * RETURNS STD
282 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000283BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000284CloseServiceHandle( SC_HANDLE hSCObject )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000285{
Michael McCormack75a84131999-11-21 00:58:14 +0000286 TRACE("(%x)\n", hSCObject);
287
288 RegCloseKey(hSCObject);
289
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000290 return TRUE;
291}
292
293
294/******************************************************************************
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000295 * OpenServiceA [ADVAPI32.112]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000296 */
Patrik Stridvall4a739731999-07-04 11:01:21 +0000297SC_HANDLE WINAPI
298OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000299 DWORD dwDesiredAccess )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000300{
301 LPWSTR lpServiceNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName);
Michael McCormack75a84131999-11-21 00:58:14 +0000302 DWORD ret;
303
304 if(lpServiceName)
305 TRACE("Request for service %s\n",lpServiceName);
306 else
307 return FALSE;
308 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000309 HeapFree(GetProcessHeap(),0,lpServiceNameW);
310 return ret;
311}
312
313
314/******************************************************************************
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000315 * OpenServiceW [ADVAPI32.113]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000316 * Opens a handle to an existing service
317 *
Matthew Beckere905f3c1999-01-28 13:46:25 +0000318 * PARAMS
319 * hSCManager []
320 * lpServiceName []
321 * dwDesiredAccess []
322 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000323 * RETURNS
324 * Success: Handle to the service
325 * Failure: NULL
326 */
Patrik Stridvall4a739731999-07-04 11:01:21 +0000327SC_HANDLE WINAPI
328OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000329 DWORD dwDesiredAccess)
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000330{
Michael McCormack75a84131999-11-21 00:58:14 +0000331 const char *str = "System\\CurrentControlSet\\Services\\";
332 WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */
333 HKEY hKey;
334 long r;
335
336 TRACE("(%d,%p,%ld)\n",hSCManager, lpServiceName,
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000337 dwDesiredAccess);
Michael McCormack75a84131999-11-21 00:58:14 +0000338
339 lstrcpyAtoW(lpServiceKey,str);
340 lstrcatW(lpServiceKey,lpServiceName);
341
342 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey));
343
344 /* FIXME: dwDesiredAccess may need some processing */
345 r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey );
346 if (r!=ERROR_SUCCESS)
347 return 0;
348
349 TRACE("returning %x\n",hKey);
350
351 return hKey;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000352}
353
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000354/******************************************************************************
355 * CreateServiceW [ADVAPI32.29]
356 */
357SC_HANDLE WINAPI
358CreateServiceW( DWORD hSCManager, LPCWSTR lpServiceName,
359 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
360 DWORD dwServiceType, DWORD dwStartType,
361 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
362 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
363 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
364 LPCWSTR lpPassword )
365{
366 FIXME("(%ld,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
367 return FALSE;
368}
369
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000370
371/******************************************************************************
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000372 * CreateServiceA [ADVAPI32.28]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000373 */
Patrik Stridvall4a739731999-07-04 11:01:21 +0000374SC_HANDLE WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +0000375CreateServiceA( DWORD hSCManager, LPCSTR lpServiceName,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000376 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
377 DWORD dwServiceType, DWORD dwStartType,
378 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
379 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
380 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
381 LPCSTR lpPassword )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000382{
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000383 HKEY hKey;
384 LONG r;
385 DWORD dp;
386
387 TRACE("(%ld,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
388
389 r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL,
390 REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp);
391 if (r!=ERROR_SUCCESS)
392 return 0;
393 if (dp != REG_CREATED_NEW_KEY)
394 return 0;
395
396 if(lpDisplayName)
397 {
398 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, lstrlenA(lpDisplayName) );
399 if (r!=ERROR_SUCCESS)
400 return 0;
401 }
402
403 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
404 if (r!=ERROR_SUCCESS)
405 return 0;
406
407 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
408 if (r!=ERROR_SUCCESS)
409 return 0;
410
411 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
412 (LPVOID)&dwErrorControl, sizeof (DWORD) );
413 if (r!=ERROR_SUCCESS)
414 return 0;
415
416 if(lpBinaryPathName)
417 {
418 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
419 lpBinaryPathName,lstrlenA(lpBinaryPathName)+1 );
420 if (r!=ERROR_SUCCESS)
421 return 0;
422 }
423
424 if(lpLoadOrderGroup)
425 {
426 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
427 lpLoadOrderGroup, lstrlenA(lpLoadOrderGroup)+1 );
428 if (r!=ERROR_SUCCESS)
429 return 0;
430 }
431
432 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
433 (LPVOID)&dwErrorControl, sizeof (DWORD) );
434 if (r!=ERROR_SUCCESS)
435 return 0;
436
437 if(lpDependencies)
438 {
439 DWORD len = 0;
440
441 /* determine the length of a double null terminated multi string */
442 do {
443 len += (lstrlenA(&lpDependencies[len])+1);
444 } while (lpDependencies[len++]);
445
446 /* fixme: this should be unicode */
447 r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ,
448 lpDependencies, len );
449 if (r!=ERROR_SUCCESS)
450 return 0;
451 }
452
453 if(lpPassword)
454 {
455 FIXME("Don't know how to add a Password for a service.\n");
456 }
457
458 if(lpServiceStartName)
459 {
460 FIXME("Don't know how to add a ServiceStartName for a service.\n");
461 }
462
463 return hKey;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000464}
465
466
467/******************************************************************************
468 * DeleteService [ADVAPI32.31]
469 *
470 * PARAMS
471 * hService [I] Handle to service
472 *
473 * RETURNS STD
474 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000475 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000476BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000477DeleteService( SC_HANDLE hService )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000478{
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000479 FIXME("(%d): stub\n",hService);
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000480 return TRUE;
481}
482
483
484/******************************************************************************
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000485 * StartServiceA [ADVAPI32.195]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000486 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000487 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000488BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000489StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000490 LPCSTR *lpServiceArgVectors )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000491{
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000492 LPWSTR *lpwstr=NULL;
493 int i;
494
495 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
496
497 if(dwNumServiceArgs)
498 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
499 dwNumServiceArgs*sizeof(LPWSTR) );
500 else
501 lpwstr = NULL;
502
503 for(i=0; i<dwNumServiceArgs; i++)
504 lpwstr[i]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors[i]);
505
Andreas Mohr7fb732e1999-12-12 00:47:51 +0000506 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000507
508 if(dwNumServiceArgs)
509 {
510 for(i=0; i<dwNumServiceArgs; i++)
511 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
512 HeapFree(GetProcessHeap(), 0, lpwstr);
513 }
514
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000515 return TRUE;
516}
517
518
519/******************************************************************************
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000520 * StartServiceW [ADVAPI32.198]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000521 * Starts a service
522 *
523 * PARAMS
Matthew Beckere905f3c1999-01-28 13:46:25 +0000524 * hService [I] Handle of service
525 * dwNumServiceArgs [I] Number of arguments
526 * lpServiceArgVectors [I] Address of array of argument string pointers
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000527 *
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000528 * NOTES
529 *
530 * NT implements this function using an obscure RPC call...
531 *
532 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
533 * to get things like %SystemRoot%\\System32\\service.exe to load.
534 *
535 * Will only work for shared address space. How should the service
536 * args be transferred when address spaces are separated?
537 *
538 * Can only start one service at a time.
539 *
540 * Has no concept of priviledge.
541 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000542 * RETURNS STD
543 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000544 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000545BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000546StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000547 LPCWSTR *lpServiceArgVectors )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000548{
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000549 CHAR path[MAX_PATH],str[MAX_PATH];
550 DWORD type,size;
551 long r;
552 HANDLE data,wait;
553 PROCESS_INFORMATION procinfo;
554 STARTUPINFOA startupinfo;
555
556 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000557 lpServiceArgVectors);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000558
559 size = sizeof str;
560 r = RegQueryValueExA(hService, "ImagePath", NULL, &type, (LPVOID)str, &size);
561 if (r!=ERROR_SUCCESS)
562 return FALSE;
563 ExpandEnvironmentStringsA(str,path,sizeof path);
564
565 TRACE("Starting service %s\n", debugstr_a(path) );
566
567 data = CreateSemaphoreA(NULL,1,1,"ADVAPI32_ServiceStartData");
568 if(data == ERROR_INVALID_HANDLE)
569 {
570 data = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
571 if(data == 0)
572 {
573 ERR("Couldn't create data semaphore\n");
574 return FALSE;
575 }
576 }
577 wait = CreateSemaphoreA(NULL,0,1,"ADVAPI32_WaitServiceStart");
578 {
579 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
580 if(wait == 0)
581 {
582 ERR("Couldn't create wait semaphore\n");
583 return FALSE;
584 }
585 }
586
587 /*
588 * FIXME: lpServiceArgsVectors need to be stored and returned to
589 * the service when it calls StartServiceCtrlDispatcher
590 *
591 * Chuck these in a global (yuk) so we can pass them to
592 * another process - address space separation will break this.
593 */
594
595 r = WaitForSingleObject(data,INFINITE);
596
597 if( r == WAIT_FAILED)
598 return FALSE;
599
600 start_dwNumServiceArgs = dwNumServiceArgs;
Andreas Mohr7fb732e1999-12-12 00:47:51 +0000601 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000602
603 ZeroMemory(&startupinfo,sizeof(STARTUPINFOA));
604 startupinfo.cb = sizeof(STARTUPINFOA);
605
606 r = CreateProcessA(path,
607 NULL,
608 NULL, /* process security attribs */
609 NULL, /* thread security attribs */
610 FALSE, /* inherit handles */
611 0, /* creation flags */
612 NULL, /* environment */
613 NULL, /* current directory */
614 &startupinfo, /* startup info */
615 &procinfo); /* process info */
616
617 if(r == FALSE)
618 {
619 ERR("Couldn't start process\n");
620 /* ReleaseSemaphore(data, 1, NULL);
621 return FALSE; */
622 }
623
624 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
625 r = WaitForSingleObject(wait,30000);
626
627 ReleaseSemaphore(data, 1, NULL);
628
629 if( r == WAIT_FAILED)
630 return FALSE;
631
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000632 return TRUE;
633}
634
635/******************************************************************************
Matthew Beckere905f3c1999-01-28 13:46:25 +0000636 * QueryServiceStatus [ADVAPI32.123]
637 *
638 * PARAMS
639 * hService []
640 * lpservicestatus []
641 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000642 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000643BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000644QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
Matthew Beckere905f3c1999-01-28 13:46:25 +0000645{
Michael McCormack75a84131999-11-21 00:58:14 +0000646 LONG r;
647 DWORD type, val, size;
648
649 FIXME("(%x,%p) partial\n",hService,lpservicestatus);
650
651 /* read the service type from the registry */
652 size = sizeof val;
653 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
654 if(type!=REG_DWORD)
655 {
656 ERR("invalid Type\n");
657 return FALSE;
658 }
659 lpservicestatus->dwServiceType = val;
Michael McCormack75a84131999-11-21 00:58:14 +0000660 /* FIXME: how are these determined or read from the registry? */
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000661 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
662 lpservicestatus->dwCurrentState = 1;
Michael McCormack75a84131999-11-21 00:58:14 +0000663 lpservicestatus->dwControlsAccepted = 0;
664 lpservicestatus->dwWin32ExitCode = NO_ERROR;
665 lpservicestatus->dwServiceSpecificExitCode = 0;
666 lpservicestatus->dwCheckPoint = 0;
667 lpservicestatus->dwWaitHint = 0;
668
669 return TRUE;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000670}
671