Spelling fixes.
[wine.git] / dlls / advapi32 / service.c
blob13b78aa2b54aad3174325de4d2a880950f3924b0
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.@]
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 * EnumServicesStatusW [ADVAPI32.@]
39 BOOL WINAPI
40 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
41 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
42 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
43 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
44 { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
45 dwServiceType, dwServiceState, lpServices, cbBufSize,
46 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
47 SetLastError (ERROR_ACCESS_DENIED);
48 return 0;
51 /******************************************************************************
52 * StartServiceCtrlDispatcherA [ADVAPI32.196]
54 BOOL WINAPI
55 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
57 LPSERVICE_MAIN_FUNCTIONA fpMain;
58 HANDLE wait;
59 DWORD dwNumServiceArgs ;
60 LPWSTR *lpArgVecW;
61 LPSTR *lpArgVecA;
62 int i;
64 TRACE("(%p)\n", servent);
65 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
66 if(wait == 0)
68 ERR("Couldn't find wait semaphore\n");
69 ERR("perhaps you need to start services using StartService\n");
70 return FALSE;
73 dwNumServiceArgs = start_dwNumServiceArgs;
74 lpArgVecW = start_lpServiceArgVectors;
76 ReleaseSemaphore(wait, 1, NULL);
78 /* Convert the Unicode arg vectors back to ASCII */
79 if(dwNumServiceArgs)
80 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
81 dwNumServiceArgs*sizeof(LPSTR) );
82 else
83 lpArgVecA = NULL;
85 for(i=0; i<dwNumServiceArgs; i++)
86 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
88 /* FIXME: should we blindly start all services? */
89 while (servent->lpServiceName) {
90 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
91 fpMain = servent->lpServiceProc;
93 /* try to start the service */
94 fpMain( dwNumServiceArgs, lpArgVecA);
96 servent++;
99 if(dwNumServiceArgs)
101 /* free arg strings */
102 for(i=0; i<dwNumServiceArgs; i++)
103 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
104 HeapFree(GetProcessHeap(), 0, lpArgVecA);
107 return TRUE;
110 /******************************************************************************
111 * StartServiceCtrlDispatcherW [ADVAPI32.197]
113 * PARAMS
114 * servent []
116 BOOL WINAPI
117 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
119 LPSERVICE_MAIN_FUNCTIONW fpMain;
120 HANDLE wait;
121 DWORD dwNumServiceArgs ;
122 LPWSTR *lpServiceArgVectors ;
124 TRACE("(%p)\n", servent);
125 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
126 if(wait == 0)
128 ERR("Couldn't find wait semaphore\n");
129 ERR("perhaps you need to start services using StartService\n");
130 return FALSE;
133 dwNumServiceArgs = start_dwNumServiceArgs;
134 lpServiceArgVectors = start_lpServiceArgVectors;
136 ReleaseSemaphore(wait, 1, NULL);
138 /* FIXME: should we blindly start all services? */
139 while (servent->lpServiceName) {
140 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
141 fpMain = servent->lpServiceProc;
143 /* try to start the service */
144 fpMain( dwNumServiceArgs, lpServiceArgVectors);
146 servent++;
149 return TRUE;
152 /******************************************************************************
153 * RegisterServiceCtrlHandlerA [ADVAPI32.176]
155 SERVICE_STATUS_HANDLE WINAPI
156 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
157 LPHANDLER_FUNCTION lpfHandler )
158 { FIXME("%s %p\n", lpServiceName, lpfHandler);
159 return 0xcacacafe;
162 /******************************************************************************
163 * RegisterServiceCtrlHandlerW [ADVAPI32.177]
165 * PARAMS
166 * lpServiceName []
167 * lpfHandler []
169 SERVICE_STATUS_HANDLE WINAPI
170 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
171 LPHANDLER_FUNCTION lpfHandler )
172 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
173 return 0xcacacafe;
176 /******************************************************************************
177 * SetServiceStatus [ADVAPI32.192]
179 * PARAMS
180 * hService []
181 * lpStatus []
183 BOOL WINAPI
184 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
185 { FIXME("%lx %p\n",hService, lpStatus);
186 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
187 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
188 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
189 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
190 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
191 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
192 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
193 return TRUE;
196 /******************************************************************************
197 * OpenSCManagerA [ADVAPI32.110]
199 SC_HANDLE WINAPI
200 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
201 DWORD dwDesiredAccess )
203 LPWSTR lpMachineNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpMachineName);
204 LPWSTR lpDatabaseNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpDatabaseName);
205 DWORD ret = OpenSCManagerW(lpMachineNameW,lpDatabaseNameW,
206 dwDesiredAccess);
207 HeapFree(GetProcessHeap(),0,lpDatabaseNameW);
208 HeapFree(GetProcessHeap(),0,lpMachineNameW);
209 return ret;
212 /******************************************************************************
213 * OpenSCManagerW [ADVAPI32.111]
214 * Establishes a connection to the service control manager and opens database
216 * NOTES
217 * This should return a SC_HANDLE
219 * PARAMS
220 * lpMachineName [I] Pointer to machine name string
221 * lpDatabaseName [I] Pointer to database name string
222 * dwDesiredAccess [I] Type of access
224 * RETURNS
225 * Success: Handle to service control manager database
226 * Failure: NULL
228 SC_HANDLE WINAPI
229 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
230 DWORD dwDesiredAccess )
232 HKEY hKey;
233 LONG r;
235 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
236 debugstr_w(lpDatabaseName), dwDesiredAccess);
239 * FIXME: what is lpDatabaseName?
240 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
241 * docs, but what if it isn't?
244 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey);
245 if (r!=ERROR_SUCCESS)
246 return 0;
248 TRACE("returning %x\n",hKey);
250 return hKey;
254 /******************************************************************************
255 * AllocateLocallyUniqueId [ADVAPI32.12]
257 * PARAMS
258 * lpluid []
260 BOOL WINAPI
261 AllocateLocallyUniqueId( PLUID lpluid )
263 lpluid->s.LowPart = time(NULL);
264 lpluid->s.HighPart = 0;
265 return TRUE;
269 /******************************************************************************
270 * ControlService [ADVAPI32.23]
271 * Sends a control code to a Win32-based service.
273 * PARAMS
274 * hService []
275 * dwControl []
276 * lpServiceStatus []
278 * RETURNS STD
280 BOOL WINAPI
281 ControlService( SC_HANDLE hService, DWORD dwControl,
282 LPSERVICE_STATUS lpServiceStatus )
284 FIXME("(%d,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
285 return TRUE;
289 /******************************************************************************
290 * CloseServiceHandle [ADVAPI32.22]
291 * Close handle to service or service control manager
293 * PARAMS
294 * hSCObject [I] Handle to service or service control manager database
296 * RETURNS STD
298 BOOL WINAPI
299 CloseServiceHandle( SC_HANDLE hSCObject )
301 TRACE("(%x)\n", hSCObject);
303 RegCloseKey(hSCObject);
305 return TRUE;
309 /******************************************************************************
310 * OpenServiceA [ADVAPI32.112]
312 SC_HANDLE WINAPI
313 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
314 DWORD dwDesiredAccess )
316 LPWSTR lpServiceNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName);
317 DWORD ret;
319 if(lpServiceName)
320 TRACE("Request for service %s\n",lpServiceName);
321 else
322 return FALSE;
323 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
324 HeapFree(GetProcessHeap(),0,lpServiceNameW);
325 return ret;
329 /******************************************************************************
330 * OpenServiceW [ADVAPI32.113]
331 * Opens a handle to an existing service
333 * PARAMS
334 * hSCManager []
335 * lpServiceName []
336 * dwDesiredAccess []
338 * RETURNS
339 * Success: Handle to the service
340 * Failure: NULL
342 SC_HANDLE WINAPI
343 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
344 DWORD dwDesiredAccess)
346 const char *str = "System\\CurrentControlSet\\Services\\";
347 WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */
348 HKEY hKey;
349 long r;
351 TRACE("(%d,%p,%ld)\n",hSCManager, lpServiceName,
352 dwDesiredAccess);
354 lstrcpyAtoW(lpServiceKey,str);
355 lstrcatW(lpServiceKey,lpServiceName);
357 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey));
359 /* FIXME: dwDesiredAccess may need some processing */
360 r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey );
361 if (r!=ERROR_SUCCESS)
362 return 0;
364 TRACE("returning %x\n",hKey);
366 return hKey;
369 /******************************************************************************
370 * CreateServiceW [ADVAPI32.29]
372 SC_HANDLE WINAPI
373 CreateServiceW( DWORD hSCManager, LPCWSTR lpServiceName,
374 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
375 DWORD dwServiceType, DWORD dwStartType,
376 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
377 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
378 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
379 LPCWSTR lpPassword )
381 FIXME("(%ld,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
382 return FALSE;
386 /******************************************************************************
387 * CreateServiceA [ADVAPI32.28]
389 SC_HANDLE WINAPI
390 CreateServiceA( DWORD hSCManager, LPCSTR lpServiceName,
391 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
392 DWORD dwServiceType, DWORD dwStartType,
393 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
394 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
395 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
396 LPCSTR lpPassword )
398 HKEY hKey;
399 LONG r;
400 DWORD dp;
402 TRACE("(%ld,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
404 r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL,
405 REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp);
406 if (r!=ERROR_SUCCESS)
407 return 0;
408 if (dp != REG_CREATED_NEW_KEY)
409 return 0;
411 if(lpDisplayName)
413 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, lstrlenA(lpDisplayName) );
414 if (r!=ERROR_SUCCESS)
415 return 0;
418 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
419 if (r!=ERROR_SUCCESS)
420 return 0;
422 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
423 if (r!=ERROR_SUCCESS)
424 return 0;
426 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
427 (LPVOID)&dwErrorControl, sizeof (DWORD) );
428 if (r!=ERROR_SUCCESS)
429 return 0;
431 if(lpBinaryPathName)
433 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
434 lpBinaryPathName,lstrlenA(lpBinaryPathName)+1 );
435 if (r!=ERROR_SUCCESS)
436 return 0;
439 if(lpLoadOrderGroup)
441 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
442 lpLoadOrderGroup, lstrlenA(lpLoadOrderGroup)+1 );
443 if (r!=ERROR_SUCCESS)
444 return 0;
447 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
448 (LPVOID)&dwErrorControl, sizeof (DWORD) );
449 if (r!=ERROR_SUCCESS)
450 return 0;
452 if(lpDependencies)
454 DWORD len = 0;
456 /* determine the length of a double null terminated multi string */
457 do {
458 len += (lstrlenA(&lpDependencies[len])+1);
459 } while (lpDependencies[len++]);
461 /* fixme: this should be unicode */
462 r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ,
463 lpDependencies, len );
464 if (r!=ERROR_SUCCESS)
465 return 0;
468 if(lpPassword)
470 FIXME("Don't know how to add a Password for a service.\n");
473 if(lpServiceStartName)
475 FIXME("Don't know how to add a ServiceStartName for a service.\n");
478 return hKey;
482 /******************************************************************************
483 * DeleteService [ADVAPI32.31]
485 * PARAMS
486 * hService [I] Handle to service
488 * RETURNS STD
491 BOOL WINAPI
492 DeleteService( SC_HANDLE hService )
494 FIXME("(%d): stub\n",hService);
495 return TRUE;
499 /******************************************************************************
500 * StartServiceA [ADVAPI32.195]
503 BOOL WINAPI
504 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
505 LPCSTR *lpServiceArgVectors )
507 LPWSTR *lpwstr=NULL;
508 int i;
510 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
512 if(dwNumServiceArgs)
513 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
514 dwNumServiceArgs*sizeof(LPWSTR) );
515 else
516 lpwstr = NULL;
518 for(i=0; i<dwNumServiceArgs; i++)
519 lpwstr[i]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors[i]);
521 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
523 if(dwNumServiceArgs)
525 for(i=0; i<dwNumServiceArgs; i++)
526 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
527 HeapFree(GetProcessHeap(), 0, lpwstr);
530 return TRUE;
534 /******************************************************************************
535 * StartServiceW [ADVAPI32.198]
536 * Starts a service
538 * PARAMS
539 * hService [I] Handle of service
540 * dwNumServiceArgs [I] Number of arguments
541 * lpServiceArgVectors [I] Address of array of argument string pointers
543 * NOTES
545 * NT implements this function using an obscure RPC call...
547 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
548 * to get things like %SystemRoot%\\System32\\service.exe to load.
550 * Will only work for shared address space. How should the service
551 * args be transferred when address spaces are separated?
553 * Can only start one service at a time.
555 * Has no concept of priviledge.
557 * RETURNS STD
560 BOOL WINAPI
561 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
562 LPCWSTR *lpServiceArgVectors )
564 CHAR path[MAX_PATH],str[MAX_PATH];
565 DWORD type,size;
566 long r;
567 HANDLE data,wait;
568 PROCESS_INFORMATION procinfo;
569 STARTUPINFOA startupinfo;
571 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,
572 lpServiceArgVectors);
574 size = sizeof str;
575 r = RegQueryValueExA(hService, "ImagePath", NULL, &type, (LPVOID)str, &size);
576 if (r!=ERROR_SUCCESS)
577 return FALSE;
578 ExpandEnvironmentStringsA(str,path,sizeof path);
580 TRACE("Starting service %s\n", debugstr_a(path) );
582 data = CreateSemaphoreA(NULL,1,1,"ADVAPI32_ServiceStartData");
583 if(data == ERROR_INVALID_HANDLE)
585 data = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
586 if(data == 0)
588 ERR("Couldn't create data semaphore\n");
589 return FALSE;
592 wait = CreateSemaphoreA(NULL,0,1,"ADVAPI32_WaitServiceStart");
594 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
595 if(wait == 0)
597 ERR("Couldn't create wait semaphore\n");
598 return FALSE;
603 * FIXME: lpServiceArgsVectors need to be stored and returned to
604 * the service when it calls StartServiceCtrlDispatcher
606 * Chuck these in a global (yuk) so we can pass them to
607 * another process - address space separation will break this.
610 r = WaitForSingleObject(data,INFINITE);
612 if( r == WAIT_FAILED)
613 return FALSE;
615 start_dwNumServiceArgs = dwNumServiceArgs;
616 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
618 ZeroMemory(&startupinfo,sizeof(STARTUPINFOA));
619 startupinfo.cb = sizeof(STARTUPINFOA);
621 r = CreateProcessA(path,
622 NULL,
623 NULL, /* process security attribs */
624 NULL, /* thread security attribs */
625 FALSE, /* inherit handles */
626 0, /* creation flags */
627 NULL, /* environment */
628 NULL, /* current directory */
629 &startupinfo, /* startup info */
630 &procinfo); /* process info */
632 if(r == FALSE)
634 ERR("Couldn't start process\n");
635 /* ReleaseSemaphore(data, 1, NULL);
636 return FALSE; */
639 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
640 r = WaitForSingleObject(wait,30000);
642 ReleaseSemaphore(data, 1, NULL);
644 if( r == WAIT_FAILED)
645 return FALSE;
647 return TRUE;
650 /******************************************************************************
651 * QueryServiceStatus [ADVAPI32.123]
653 * PARAMS
654 * hService []
655 * lpservicestatus []
658 BOOL WINAPI
659 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
661 LONG r;
662 DWORD type, val, size;
664 FIXME("(%x,%p) partial\n",hService,lpservicestatus);
666 /* read the service type from the registry */
667 size = sizeof val;
668 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
669 if(type!=REG_DWORD)
671 ERR("invalid Type\n");
672 return FALSE;
674 lpservicestatus->dwServiceType = val;
675 /* FIXME: how are these determined or read from the registry? */
676 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
677 lpservicestatus->dwCurrentState = 1;
678 lpservicestatus->dwControlsAccepted = 0;
679 lpservicestatus->dwWin32ExitCode = NO_ERROR;
680 lpservicestatus->dwServiceSpecificExitCode = 0;
681 lpservicestatus->dwCheckPoint = 0;
682 lpservicestatus->dwWaitHint = 0;
684 return TRUE;