Release 20000326.
[wine/gsoc-2012-control.git] / dlls / advapi32 / service.c
blobcccab1f9b9f9ad529336cd1de6bbc5d15b9e7bac
1 /*
2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
5 */
7 #include <time.h>
9 #include "windef.h"
10 #include "winsvc.h"
11 #include "winerror.h"
12 #include "winreg.h"
13 #include "heap.h"
14 #include "debugtools.h"
16 DEFAULT_DEBUG_CHANNEL(advapi)
18 static DWORD start_dwNumServiceArgs;
19 static LPWSTR *start_lpServiceArgVectors;
21 /******************************************************************************
22 * EnumServicesStatusA [ADVAPI32.38]
24 BOOL WINAPI
25 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
26 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
27 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
28 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
29 { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
30 dwServiceType, dwServiceState, lpServices, cbBufSize,
31 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
32 SetLastError (ERROR_ACCESS_DENIED);
33 return 0;
36 /******************************************************************************
37 * StartServiceCtrlDispatcherA [ADVAPI32.196]
39 BOOL WINAPI
40 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
42 LPSERVICE_MAIN_FUNCTIONA fpMain;
43 HANDLE wait;
44 DWORD dwNumServiceArgs ;
45 LPWSTR *lpArgVecW;
46 LPSTR *lpArgVecA;
47 int i;
49 TRACE("(%p)\n", servent);
50 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
51 if(wait == 0)
53 ERR("Couldn't find wait semaphore\n");
54 ERR("perhaps you need to start services using StartService\n");
55 return FALSE;
58 dwNumServiceArgs = start_dwNumServiceArgs;
59 lpArgVecW = start_lpServiceArgVectors;
61 ReleaseSemaphore(wait, 1, NULL);
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;
70 for(i=0; i<dwNumServiceArgs; i++)
71 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
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;
78 /* try to start the service */
79 fpMain( dwNumServiceArgs, lpArgVecA);
81 servent++;
84 if(dwNumServiceArgs)
86 /* free arg strings */
87 for(i=0; i<dwNumServiceArgs; i++)
88 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
89 HeapFree(GetProcessHeap(), 0, lpArgVecA);
92 return TRUE;
95 /******************************************************************************
96 * StartServiceCtrlDispatcherW [ADVAPI32.197]
98 * PARAMS
99 * servent []
101 BOOL WINAPI
102 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
104 LPSERVICE_MAIN_FUNCTIONW fpMain;
105 HANDLE wait;
106 DWORD dwNumServiceArgs ;
107 LPWSTR *lpServiceArgVectors ;
109 TRACE("(%p)\n", servent);
110 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
111 if(wait == 0)
113 ERR("Couldn't find wait semaphore\n");
114 ERR("perhaps you need to start services using StartService\n");
115 return FALSE;
118 dwNumServiceArgs = start_dwNumServiceArgs;
119 lpServiceArgVectors = start_lpServiceArgVectors;
121 ReleaseSemaphore(wait, 1, NULL);
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;
128 /* try to start the service */
129 fpMain( dwNumServiceArgs, lpServiceArgVectors);
131 servent++;
134 return TRUE;
137 /******************************************************************************
138 * RegisterServiceCtrlHandlerA [ADVAPI32.176]
140 SERVICE_STATUS_HANDLE WINAPI
141 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
142 LPHANDLER_FUNCTION lpfHandler )
143 { FIXME("%s %p\n", lpServiceName, lpfHandler);
144 return 0xcacacafe;
147 /******************************************************************************
148 * RegisterServiceCtrlHandlerW [ADVAPI32.177]
150 * PARAMS
151 * lpServiceName []
152 * lpfHandler []
154 SERVICE_STATUS_HANDLE WINAPI
155 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
156 LPHANDLER_FUNCTION lpfHandler )
157 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
158 return 0xcacacafe;
161 /******************************************************************************
162 * SetServiceStatus [ADVAPI32.192]
164 * PARAMS
165 * hService []
166 * lpStatus []
168 BOOL WINAPI
169 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
170 { 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);
178 return TRUE;
181 /******************************************************************************
182 * OpenSCManagerA [ADVAPI32.110]
184 SC_HANDLE WINAPI
185 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
186 DWORD dwDesiredAccess )
188 LPWSTR lpMachineNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpMachineName);
189 LPWSTR lpDatabaseNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpDatabaseName);
190 DWORD ret = OpenSCManagerW(lpMachineNameW,lpDatabaseNameW,
191 dwDesiredAccess);
192 HeapFree(GetProcessHeap(),0,lpDatabaseNameW);
193 HeapFree(GetProcessHeap(),0,lpMachineNameW);
194 return ret;
197 /******************************************************************************
198 * OpenSCManagerW [ADVAPI32.111]
199 * Establishes a connection to the service control manager and opens database
201 * NOTES
202 * This should return a SC_HANDLE
204 * PARAMS
205 * lpMachineName [I] Pointer to machine name string
206 * lpDatabaseName [I] Pointer to database name string
207 * dwDesiredAccess [I] Type of access
209 * RETURNS
210 * Success: Handle to service control manager database
211 * Failure: NULL
213 SC_HANDLE WINAPI
214 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
215 DWORD dwDesiredAccess )
217 HKEY hKey;
218 LONG r;
220 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
221 debugstr_w(lpDatabaseName), dwDesiredAccess);
224 * FIXME: what is lpDatabaseName?
225 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
226 * docs, but what if it isn't?
229 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey);
230 if (r!=ERROR_SUCCESS)
231 return 0;
233 TRACE("returning %x\n",hKey);
235 return hKey;
239 /******************************************************************************
240 * AllocateLocallyUniqueId [ADVAPI32.12]
242 * PARAMS
243 * lpluid []
245 BOOL WINAPI
246 AllocateLocallyUniqueId( PLUID lpluid )
248 lpluid->s.LowPart = time(NULL);
249 lpluid->s.HighPart = 0;
250 return TRUE;
254 /******************************************************************************
255 * ControlService [ADVAPI32.23]
256 * Sends a control code to a Win32-based service.
258 * PARAMS
259 * hService []
260 * dwControl []
261 * lpServiceStatus []
263 * RETURNS STD
265 BOOL WINAPI
266 ControlService( SC_HANDLE hService, DWORD dwControl,
267 LPSERVICE_STATUS lpServiceStatus )
269 FIXME("(%d,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
270 return TRUE;
274 /******************************************************************************
275 * CloseServiceHandle [ADVAPI32.22]
276 * Close handle to service or service control manager
278 * PARAMS
279 * hSCObject [I] Handle to service or service control manager database
281 * RETURNS STD
283 BOOL WINAPI
284 CloseServiceHandle( SC_HANDLE hSCObject )
286 TRACE("(%x)\n", hSCObject);
288 RegCloseKey(hSCObject);
290 return TRUE;
294 /******************************************************************************
295 * OpenServiceA [ADVAPI32.112]
297 SC_HANDLE WINAPI
298 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
299 DWORD dwDesiredAccess )
301 LPWSTR lpServiceNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName);
302 DWORD ret;
304 if(lpServiceName)
305 TRACE("Request for service %s\n",lpServiceName);
306 else
307 return FALSE;
308 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
309 HeapFree(GetProcessHeap(),0,lpServiceNameW);
310 return ret;
314 /******************************************************************************
315 * OpenServiceW [ADVAPI32.113]
316 * Opens a handle to an existing service
318 * PARAMS
319 * hSCManager []
320 * lpServiceName []
321 * dwDesiredAccess []
323 * RETURNS
324 * Success: Handle to the service
325 * Failure: NULL
327 SC_HANDLE WINAPI
328 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
329 DWORD dwDesiredAccess)
331 const char *str = "System\\CurrentControlSet\\Services\\";
332 WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */
333 HKEY hKey;
334 long r;
336 TRACE("(%d,%p,%ld)\n",hSCManager, lpServiceName,
337 dwDesiredAccess);
339 lstrcpyAtoW(lpServiceKey,str);
340 lstrcatW(lpServiceKey,lpServiceName);
342 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey));
344 /* FIXME: dwDesiredAccess may need some processing */
345 r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey );
346 if (r!=ERROR_SUCCESS)
347 return 0;
349 TRACE("returning %x\n",hKey);
351 return hKey;
354 /******************************************************************************
355 * CreateServiceW [ADVAPI32.29]
357 SC_HANDLE WINAPI
358 CreateServiceW( 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 )
366 FIXME("(%ld,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
367 return FALSE;
371 /******************************************************************************
372 * CreateServiceA [ADVAPI32.28]
374 SC_HANDLE WINAPI
375 CreateServiceA( DWORD hSCManager, LPCSTR lpServiceName,
376 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 )
383 HKEY hKey;
384 LONG r;
385 DWORD dp;
387 TRACE("(%ld,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
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;
396 if(lpDisplayName)
398 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, lstrlenA(lpDisplayName) );
399 if (r!=ERROR_SUCCESS)
400 return 0;
403 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
404 if (r!=ERROR_SUCCESS)
405 return 0;
407 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
408 if (r!=ERROR_SUCCESS)
409 return 0;
411 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
412 (LPVOID)&dwErrorControl, sizeof (DWORD) );
413 if (r!=ERROR_SUCCESS)
414 return 0;
416 if(lpBinaryPathName)
418 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
419 lpBinaryPathName,lstrlenA(lpBinaryPathName)+1 );
420 if (r!=ERROR_SUCCESS)
421 return 0;
424 if(lpLoadOrderGroup)
426 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
427 lpLoadOrderGroup, lstrlenA(lpLoadOrderGroup)+1 );
428 if (r!=ERROR_SUCCESS)
429 return 0;
432 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
433 (LPVOID)&dwErrorControl, sizeof (DWORD) );
434 if (r!=ERROR_SUCCESS)
435 return 0;
437 if(lpDependencies)
439 DWORD len = 0;
441 /* determine the length of a double null terminated multi string */
442 do {
443 len += (lstrlenA(&lpDependencies[len])+1);
444 } while (lpDependencies[len++]);
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;
453 if(lpPassword)
455 FIXME("Don't know how to add a Password for a service.\n");
458 if(lpServiceStartName)
460 FIXME("Don't know how to add a ServiceStartName for a service.\n");
463 return hKey;
467 /******************************************************************************
468 * DeleteService [ADVAPI32.31]
470 * PARAMS
471 * hService [I] Handle to service
473 * RETURNS STD
476 BOOL WINAPI
477 DeleteService( SC_HANDLE hService )
479 FIXME("(%d): stub\n",hService);
480 return TRUE;
484 /******************************************************************************
485 * StartServiceA [ADVAPI32.195]
488 BOOL WINAPI
489 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
490 LPCSTR *lpServiceArgVectors )
492 LPWSTR *lpwstr=NULL;
493 int i;
495 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
497 if(dwNumServiceArgs)
498 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
499 dwNumServiceArgs*sizeof(LPWSTR) );
500 else
501 lpwstr = NULL;
503 for(i=0; i<dwNumServiceArgs; i++)
504 lpwstr[i]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors[i]);
506 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
508 if(dwNumServiceArgs)
510 for(i=0; i<dwNumServiceArgs; i++)
511 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
512 HeapFree(GetProcessHeap(), 0, lpwstr);
515 return TRUE;
519 /******************************************************************************
520 * StartServiceW [ADVAPI32.198]
521 * Starts a service
523 * PARAMS
524 * hService [I] Handle of service
525 * dwNumServiceArgs [I] Number of arguments
526 * lpServiceArgVectors [I] Address of array of argument string pointers
528 * NOTES
530 * NT implements this function using an obscure RPC call...
532 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
533 * to get things like %SystemRoot%\\System32\\service.exe to load.
535 * Will only work for shared address space. How should the service
536 * args be transferred when address spaces are separated?
538 * Can only start one service at a time.
540 * Has no concept of priviledge.
542 * RETURNS STD
545 BOOL WINAPI
546 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
547 LPCWSTR *lpServiceArgVectors )
549 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;
556 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,
557 lpServiceArgVectors);
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);
565 TRACE("Starting service %s\n", debugstr_a(path) );
567 data = CreateSemaphoreA(NULL,1,1,"ADVAPI32_ServiceStartData");
568 if(data == ERROR_INVALID_HANDLE)
570 data = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
571 if(data == 0)
573 ERR("Couldn't create data semaphore\n");
574 return FALSE;
577 wait = CreateSemaphoreA(NULL,0,1,"ADVAPI32_WaitServiceStart");
579 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
580 if(wait == 0)
582 ERR("Couldn't create wait semaphore\n");
583 return FALSE;
588 * FIXME: lpServiceArgsVectors need to be stored and returned to
589 * the service when it calls StartServiceCtrlDispatcher
591 * Chuck these in a global (yuk) so we can pass them to
592 * another process - address space separation will break this.
595 r = WaitForSingleObject(data,INFINITE);
597 if( r == WAIT_FAILED)
598 return FALSE;
600 start_dwNumServiceArgs = dwNumServiceArgs;
601 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
603 ZeroMemory(&startupinfo,sizeof(STARTUPINFOA));
604 startupinfo.cb = sizeof(STARTUPINFOA);
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 */
617 if(r == FALSE)
619 ERR("Couldn't start process\n");
620 /* ReleaseSemaphore(data, 1, NULL);
621 return FALSE; */
624 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
625 r = WaitForSingleObject(wait,30000);
627 ReleaseSemaphore(data, 1, NULL);
629 if( r == WAIT_FAILED)
630 return FALSE;
632 return TRUE;
635 /******************************************************************************
636 * QueryServiceStatus [ADVAPI32.123]
638 * PARAMS
639 * hService []
640 * lpservicestatus []
643 BOOL WINAPI
644 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
646 LONG r;
647 DWORD type, val, size;
649 FIXME("(%x,%p) partial\n",hService,lpservicestatus);
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)
656 ERR("invalid Type\n");
657 return FALSE;
659 lpservicestatus->dwServiceType = val;
660 /* FIXME: how are these determined or read from the registry? */
661 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
662 lpservicestatus->dwCurrentState = 1;
663 lpservicestatus->dwControlsAccepted = 0;
664 lpservicestatus->dwWin32ExitCode = NO_ERROR;
665 lpservicestatus->dwServiceSpecificExitCode = 0;
666 lpservicestatus->dwCheckPoint = 0;
667 lpservicestatus->dwWaitHint = 0;
669 return TRUE;