Fixed ToUnicode TRACE message.
[wine.git] / dlls / advapi32 / service.c
blobecb425fd54611de1aff3a707feb370f090ef6a0e
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 "wine/unicode.h"
14 #include "wine/winestring.h"
15 #include "heap.h"
16 #include "debugtools.h"
18 DEFAULT_DEBUG_CHANNEL(advapi);
20 static DWORD start_dwNumServiceArgs;
21 static LPWSTR *start_lpServiceArgVectors;
23 /******************************************************************************
24 * EnumServicesStatusA [ADVAPI32.@]
26 BOOL WINAPI
27 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
28 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
29 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
30 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
31 { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
32 dwServiceType, dwServiceState, lpServices, cbBufSize,
33 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
34 SetLastError (ERROR_ACCESS_DENIED);
35 return 0;
38 /******************************************************************************
39 * EnumServicesStatusW [ADVAPI32.@]
41 BOOL WINAPI
42 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
43 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
44 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
45 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
46 { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
47 dwServiceType, dwServiceState, lpServices, cbBufSize,
48 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
49 SetLastError (ERROR_ACCESS_DENIED);
50 return 0;
53 /******************************************************************************
54 * StartServiceCtrlDispatcherA [ADVAPI32.196]
56 BOOL WINAPI
57 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
59 LPSERVICE_MAIN_FUNCTIONA fpMain;
60 HANDLE wait;
61 DWORD dwNumServiceArgs ;
62 LPWSTR *lpArgVecW;
63 LPSTR *lpArgVecA;
64 int i;
66 TRACE("(%p)\n", servent);
67 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
68 if(wait == 0)
70 ERR("Couldn't find wait semaphore\n");
71 ERR("perhaps you need to start services using StartService\n");
72 return FALSE;
75 dwNumServiceArgs = start_dwNumServiceArgs;
76 lpArgVecW = start_lpServiceArgVectors;
78 ReleaseSemaphore(wait, 1, NULL);
80 /* Convert the Unicode arg vectors back to ASCII */
81 if(dwNumServiceArgs)
82 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
83 dwNumServiceArgs*sizeof(LPSTR) );
84 else
85 lpArgVecA = NULL;
87 for(i=0; i<dwNumServiceArgs; i++)
88 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
90 /* FIXME: should we blindly start all services? */
91 while (servent->lpServiceName) {
92 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
93 fpMain = servent->lpServiceProc;
95 /* try to start the service */
96 fpMain( dwNumServiceArgs, lpArgVecA);
98 servent++;
101 if(dwNumServiceArgs)
103 /* free arg strings */
104 for(i=0; i<dwNumServiceArgs; i++)
105 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
106 HeapFree(GetProcessHeap(), 0, lpArgVecA);
109 return TRUE;
112 /******************************************************************************
113 * StartServiceCtrlDispatcherW [ADVAPI32.197]
115 * PARAMS
116 * servent []
118 BOOL WINAPI
119 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
121 LPSERVICE_MAIN_FUNCTIONW fpMain;
122 HANDLE wait;
123 DWORD dwNumServiceArgs ;
124 LPWSTR *lpServiceArgVectors ;
126 TRACE("(%p)\n", servent);
127 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
128 if(wait == 0)
130 ERR("Couldn't find wait semaphore\n");
131 ERR("perhaps you need to start services using StartService\n");
132 return FALSE;
135 dwNumServiceArgs = start_dwNumServiceArgs;
136 lpServiceArgVectors = start_lpServiceArgVectors;
138 ReleaseSemaphore(wait, 1, NULL);
140 /* FIXME: should we blindly start all services? */
141 while (servent->lpServiceName) {
142 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
143 fpMain = servent->lpServiceProc;
145 /* try to start the service */
146 fpMain( dwNumServiceArgs, lpServiceArgVectors);
148 servent++;
151 return TRUE;
154 /******************************************************************************
155 * RegisterServiceCtrlHandlerA [ADVAPI32.176]
157 SERVICE_STATUS_HANDLE WINAPI
158 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
159 LPHANDLER_FUNCTION lpfHandler )
160 { FIXME("%s %p\n", lpServiceName, lpfHandler);
161 return 0xcacacafe;
164 /******************************************************************************
165 * RegisterServiceCtrlHandlerW [ADVAPI32.177]
167 * PARAMS
168 * lpServiceName []
169 * lpfHandler []
171 SERVICE_STATUS_HANDLE WINAPI
172 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
173 LPHANDLER_FUNCTION lpfHandler )
174 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
175 return 0xcacacafe;
178 /******************************************************************************
179 * SetServiceStatus [ADVAPI32.192]
181 * PARAMS
182 * hService []
183 * lpStatus []
185 BOOL WINAPI
186 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
187 { FIXME("%x %p\n",hService, lpStatus);
188 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
189 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
190 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
191 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
192 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
193 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
194 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
195 return TRUE;
198 /******************************************************************************
199 * OpenSCManagerA [ADVAPI32.110]
201 SC_HANDLE WINAPI
202 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
203 DWORD dwDesiredAccess )
205 LPWSTR lpMachineNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpMachineName);
206 LPWSTR lpDatabaseNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpDatabaseName);
207 DWORD ret = OpenSCManagerW(lpMachineNameW,lpDatabaseNameW,
208 dwDesiredAccess);
209 HeapFree(GetProcessHeap(),0,lpDatabaseNameW);
210 HeapFree(GetProcessHeap(),0,lpMachineNameW);
211 return ret;
214 /******************************************************************************
215 * OpenSCManagerW [ADVAPI32.111]
216 * Establishes a connection to the service control manager and opens database
218 * NOTES
219 * This should return a SC_HANDLE
221 * PARAMS
222 * lpMachineName [I] Pointer to machine name string
223 * lpDatabaseName [I] Pointer to database name string
224 * dwDesiredAccess [I] Type of access
226 * RETURNS
227 * Success: Handle to service control manager database
228 * Failure: NULL
230 SC_HANDLE WINAPI
231 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
232 DWORD dwDesiredAccess )
234 HKEY hKey;
235 LONG r;
237 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
238 debugstr_w(lpDatabaseName), dwDesiredAccess);
241 * FIXME: what is lpDatabaseName?
242 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
243 * docs, but what if it isn't?
246 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey);
247 if (r!=ERROR_SUCCESS)
248 return 0;
250 TRACE("returning %x\n",hKey);
252 return hKey;
256 /******************************************************************************
257 * AllocateLocallyUniqueId [ADVAPI32.12]
259 * PARAMS
260 * lpluid []
262 BOOL WINAPI
263 AllocateLocallyUniqueId( PLUID lpluid )
265 lpluid->s.LowPart = time(NULL);
266 lpluid->s.HighPart = 0;
267 return TRUE;
271 /******************************************************************************
272 * ControlService [ADVAPI32.23]
273 * Sends a control code to a Win32-based service.
275 * PARAMS
276 * hService []
277 * dwControl []
278 * lpServiceStatus []
280 * RETURNS STD
282 BOOL WINAPI
283 ControlService( SC_HANDLE hService, DWORD dwControl,
284 LPSERVICE_STATUS lpServiceStatus )
286 FIXME("(%d,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
287 return TRUE;
291 /******************************************************************************
292 * CloseServiceHandle [ADVAPI32.22]
293 * Close handle to service or service control manager
295 * PARAMS
296 * hSCObject [I] Handle to service or service control manager database
298 * RETURNS STD
300 BOOL WINAPI
301 CloseServiceHandle( SC_HANDLE hSCObject )
303 TRACE("(%x)\n", hSCObject);
305 RegCloseKey(hSCObject);
307 return TRUE;
311 /******************************************************************************
312 * OpenServiceA [ADVAPI32.112]
314 SC_HANDLE WINAPI
315 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
316 DWORD dwDesiredAccess )
318 LPWSTR lpServiceNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName);
319 DWORD ret;
321 if(lpServiceName)
322 TRACE("Request for service %s\n",lpServiceName);
323 else
324 return FALSE;
325 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
326 HeapFree(GetProcessHeap(),0,lpServiceNameW);
327 return ret;
331 /******************************************************************************
332 * OpenServiceW [ADVAPI32.113]
333 * Opens a handle to an existing service
335 * PARAMS
336 * hSCManager []
337 * lpServiceName []
338 * dwDesiredAccess []
340 * RETURNS
341 * Success: Handle to the service
342 * Failure: NULL
344 SC_HANDLE WINAPI
345 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
346 DWORD dwDesiredAccess)
348 const char *str = "System\\CurrentControlSet\\Services\\";
349 WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */
350 HKEY hKey;
351 long r;
353 TRACE("(%d,%p,%ld)\n",hSCManager, lpServiceName,
354 dwDesiredAccess);
356 lstrcpyAtoW(lpServiceKey,str);
357 strcatW(lpServiceKey,lpServiceName);
359 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey));
361 /* FIXME: dwDesiredAccess may need some processing */
362 r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey );
363 if (r!=ERROR_SUCCESS)
364 return 0;
366 TRACE("returning %x\n",hKey);
368 return hKey;
371 /******************************************************************************
372 * CreateServiceW [ADVAPI32.29]
374 SC_HANDLE WINAPI
375 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
376 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
377 DWORD dwServiceType, DWORD dwStartType,
378 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
379 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
380 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
381 LPCWSTR lpPassword )
383 FIXME("(%u,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
384 return FALSE;
388 /******************************************************************************
389 * CreateServiceA [ADVAPI32.28]
391 SC_HANDLE WINAPI
392 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
393 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
394 DWORD dwServiceType, DWORD dwStartType,
395 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
396 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
397 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
398 LPCSTR lpPassword )
400 HKEY hKey;
401 LONG r;
402 DWORD dp;
404 TRACE("(%u,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
406 r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL,
407 REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp);
408 if (r!=ERROR_SUCCESS)
409 return 0;
410 if (dp != REG_CREATED_NEW_KEY)
411 return 0;
413 if(lpDisplayName)
415 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, strlen(lpDisplayName) );
416 if (r!=ERROR_SUCCESS)
417 return 0;
420 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
421 if (r!=ERROR_SUCCESS)
422 return 0;
424 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
425 if (r!=ERROR_SUCCESS)
426 return 0;
428 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
429 (LPVOID)&dwErrorControl, sizeof (DWORD) );
430 if (r!=ERROR_SUCCESS)
431 return 0;
433 if(lpBinaryPathName)
435 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
436 lpBinaryPathName,strlen(lpBinaryPathName)+1 );
437 if (r!=ERROR_SUCCESS)
438 return 0;
441 if(lpLoadOrderGroup)
443 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
444 lpLoadOrderGroup, strlen(lpLoadOrderGroup)+1 );
445 if (r!=ERROR_SUCCESS)
446 return 0;
449 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
450 (LPVOID)&dwErrorControl, sizeof (DWORD) );
451 if (r!=ERROR_SUCCESS)
452 return 0;
454 if(lpDependencies)
456 DWORD len = 0;
458 /* determine the length of a double null terminated multi string */
459 do {
460 len += (strlen(&lpDependencies[len])+1);
461 } while (lpDependencies[len++]);
463 /* fixme: this should be unicode */
464 r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ,
465 lpDependencies, len );
466 if (r!=ERROR_SUCCESS)
467 return 0;
470 if(lpPassword)
472 FIXME("Don't know how to add a Password for a service.\n");
475 if(lpServiceStartName)
477 FIXME("Don't know how to add a ServiceStartName for a service.\n");
480 return hKey;
484 /******************************************************************************
485 * DeleteService [ADVAPI32.31]
487 * PARAMS
488 * hService [I] Handle to service
490 * RETURNS STD
493 BOOL WINAPI
494 DeleteService( SC_HANDLE hService )
496 FIXME("(%d): stub\n",hService);
497 return TRUE;
501 /******************************************************************************
502 * StartServiceA [ADVAPI32.195]
505 BOOL WINAPI
506 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
507 LPCSTR *lpServiceArgVectors )
509 LPWSTR *lpwstr=NULL;
510 int i;
512 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
514 if(dwNumServiceArgs)
515 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
516 dwNumServiceArgs*sizeof(LPWSTR) );
517 else
518 lpwstr = NULL;
520 for(i=0; i<dwNumServiceArgs; i++)
521 lpwstr[i]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors[i]);
523 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
525 if(dwNumServiceArgs)
527 for(i=0; i<dwNumServiceArgs; i++)
528 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
529 HeapFree(GetProcessHeap(), 0, lpwstr);
532 return TRUE;
536 /******************************************************************************
537 * StartServiceW [ADVAPI32.198]
538 * Starts a service
540 * PARAMS
541 * hService [I] Handle of service
542 * dwNumServiceArgs [I] Number of arguments
543 * lpServiceArgVectors [I] Address of array of argument string pointers
545 * NOTES
547 * NT implements this function using an obscure RPC call...
549 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
550 * to get things like %SystemRoot%\\System32\\service.exe to load.
552 * Will only work for shared address space. How should the service
553 * args be transferred when address spaces are separated?
555 * Can only start one service at a time.
557 * Has no concept of priviledge.
559 * RETURNS STD
562 BOOL WINAPI
563 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
564 LPCWSTR *lpServiceArgVectors )
566 CHAR path[MAX_PATH],str[MAX_PATH];
567 DWORD type,size;
568 long r;
569 HANDLE data,wait;
570 PROCESS_INFORMATION procinfo;
571 STARTUPINFOA startupinfo;
573 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,
574 lpServiceArgVectors);
576 size = sizeof str;
577 r = RegQueryValueExA(hService, "ImagePath", NULL, &type, (LPVOID)str, &size);
578 if (r!=ERROR_SUCCESS)
579 return FALSE;
580 ExpandEnvironmentStringsA(str,path,sizeof path);
582 TRACE("Starting service %s\n", debugstr_a(path) );
584 data = CreateSemaphoreA(NULL,1,1,"ADVAPI32_ServiceStartData");
585 if(data == ERROR_INVALID_HANDLE)
587 data = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
588 if(data == 0)
590 ERR("Couldn't create data semaphore\n");
591 return FALSE;
594 wait = CreateSemaphoreA(NULL,0,1,"ADVAPI32_WaitServiceStart");
596 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
597 if(wait == 0)
599 ERR("Couldn't create wait semaphore\n");
600 return FALSE;
605 * FIXME: lpServiceArgsVectors need to be stored and returned to
606 * the service when it calls StartServiceCtrlDispatcher
608 * Chuck these in a global (yuk) so we can pass them to
609 * another process - address space separation will break this.
612 r = WaitForSingleObject(data,INFINITE);
614 if( r == WAIT_FAILED)
615 return FALSE;
617 start_dwNumServiceArgs = dwNumServiceArgs;
618 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
620 ZeroMemory(&startupinfo,sizeof(STARTUPINFOA));
621 startupinfo.cb = sizeof(STARTUPINFOA);
623 r = CreateProcessA(path,
624 NULL,
625 NULL, /* process security attribs */
626 NULL, /* thread security attribs */
627 FALSE, /* inherit handles */
628 0, /* creation flags */
629 NULL, /* environment */
630 NULL, /* current directory */
631 &startupinfo, /* startup info */
632 &procinfo); /* process info */
634 if(r == FALSE)
636 ERR("Couldn't start process\n");
637 /* ReleaseSemaphore(data, 1, NULL);
638 return FALSE; */
641 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
642 r = WaitForSingleObject(wait,30000);
644 ReleaseSemaphore(data, 1, NULL);
646 if( r == WAIT_FAILED)
647 return FALSE;
649 return TRUE;
652 /******************************************************************************
653 * QueryServiceStatus [ADVAPI32.123]
655 * PARAMS
656 * hService []
657 * lpservicestatus []
660 BOOL WINAPI
661 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
663 LONG r;
664 DWORD type, val, size;
666 FIXME("(%x,%p) partial\n",hService,lpservicestatus);
668 /* read the service type from the registry */
669 size = sizeof val;
670 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
671 if(type!=REG_DWORD)
673 ERR("invalid Type\n");
674 return FALSE;
676 lpservicestatus->dwServiceType = val;
677 /* FIXME: how are these determined or read from the registry? */
678 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
679 lpservicestatus->dwCurrentState = 1;
680 lpservicestatus->dwControlsAccepted = 0;
681 lpservicestatus->dwWin32ExitCode = NO_ERROR;
682 lpservicestatus->dwServiceSpecificExitCode = 0;
683 lpservicestatus->dwCheckPoint = 0;
684 lpservicestatus->dwWaitHint = 0;
686 return TRUE;