Got rid of the Wine internal lstrcpy* functions and of winestring.h.
[wine/gsoc_dplay.git] / dlls / advapi32 / service.c
blob38adf80e7f4d6138b2b48805c6b0bbabaace4924
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 "heap.h"
15 #include "debugtools.h"
17 DEFAULT_DEBUG_CHANNEL(advapi);
19 static DWORD start_dwNumServiceArgs;
20 static LPWSTR *start_lpServiceArgVectors;
22 /******************************************************************************
23 * EnumServicesStatusA [ADVAPI32.@]
25 BOOL WINAPI
26 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
27 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
28 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
29 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
30 { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
31 dwServiceType, dwServiceState, lpServices, cbBufSize,
32 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
33 SetLastError (ERROR_ACCESS_DENIED);
34 return 0;
37 /******************************************************************************
38 * EnumServicesStatusW [ADVAPI32.@]
40 BOOL WINAPI
41 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
42 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
43 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
44 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
45 { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
46 dwServiceType, dwServiceState, lpServices, cbBufSize,
47 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
48 SetLastError (ERROR_ACCESS_DENIED);
49 return 0;
52 /******************************************************************************
53 * StartServiceCtrlDispatcherA [ADVAPI32.196]
55 BOOL WINAPI
56 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
58 LPSERVICE_MAIN_FUNCTIONA fpMain;
59 HANDLE wait;
60 DWORD dwNumServiceArgs ;
61 LPWSTR *lpArgVecW;
62 LPSTR *lpArgVecA;
63 int i;
65 TRACE("(%p)\n", servent);
66 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
67 if(wait == 0)
69 ERR("Couldn't find wait semaphore\n");
70 ERR("perhaps you need to start services using StartService\n");
71 return FALSE;
74 dwNumServiceArgs = start_dwNumServiceArgs;
75 lpArgVecW = start_lpServiceArgVectors;
77 ReleaseSemaphore(wait, 1, NULL);
79 /* Convert the Unicode arg vectors back to ASCII */
80 if(dwNumServiceArgs)
81 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
82 dwNumServiceArgs*sizeof(LPSTR) );
83 else
84 lpArgVecA = NULL;
86 for(i=0; i<dwNumServiceArgs; i++)
87 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
89 /* FIXME: should we blindly start all services? */
90 while (servent->lpServiceName) {
91 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
92 fpMain = servent->lpServiceProc;
94 /* try to start the service */
95 fpMain( dwNumServiceArgs, lpArgVecA);
97 servent++;
100 if(dwNumServiceArgs)
102 /* free arg strings */
103 for(i=0; i<dwNumServiceArgs; i++)
104 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
105 HeapFree(GetProcessHeap(), 0, lpArgVecA);
108 return TRUE;
111 /******************************************************************************
112 * StartServiceCtrlDispatcherW [ADVAPI32.197]
114 * PARAMS
115 * servent []
117 BOOL WINAPI
118 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
120 LPSERVICE_MAIN_FUNCTIONW fpMain;
121 HANDLE wait;
122 DWORD dwNumServiceArgs ;
123 LPWSTR *lpServiceArgVectors ;
125 TRACE("(%p)\n", servent);
126 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
127 if(wait == 0)
129 ERR("Couldn't find wait semaphore\n");
130 ERR("perhaps you need to start services using StartService\n");
131 return FALSE;
134 dwNumServiceArgs = start_dwNumServiceArgs;
135 lpServiceArgVectors = start_lpServiceArgVectors;
137 ReleaseSemaphore(wait, 1, NULL);
139 /* FIXME: should we blindly start all services? */
140 while (servent->lpServiceName) {
141 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
142 fpMain = servent->lpServiceProc;
144 /* try to start the service */
145 fpMain( dwNumServiceArgs, lpServiceArgVectors);
147 servent++;
150 return TRUE;
153 /******************************************************************************
154 * RegisterServiceCtrlHandlerA [ADVAPI32.176]
156 SERVICE_STATUS_HANDLE WINAPI
157 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
158 LPHANDLER_FUNCTION lpfHandler )
159 { FIXME("%s %p\n", lpServiceName, lpfHandler);
160 return 0xcacacafe;
163 /******************************************************************************
164 * RegisterServiceCtrlHandlerW [ADVAPI32.177]
166 * PARAMS
167 * lpServiceName []
168 * lpfHandler []
170 SERVICE_STATUS_HANDLE WINAPI
171 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
172 LPHANDLER_FUNCTION lpfHandler )
173 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
174 return 0xcacacafe;
177 /******************************************************************************
178 * SetServiceStatus [ADVAPI32.192]
180 * PARAMS
181 * hService []
182 * lpStatus []
184 BOOL WINAPI
185 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
186 { FIXME("%x %p\n",hService, lpStatus);
187 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
188 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
189 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
190 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
191 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
192 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
193 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
194 return TRUE;
197 /******************************************************************************
198 * OpenSCManagerA [ADVAPI32.110]
200 SC_HANDLE WINAPI
201 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
202 DWORD dwDesiredAccess )
204 LPWSTR lpMachineNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpMachineName);
205 LPWSTR lpDatabaseNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpDatabaseName);
206 DWORD ret = OpenSCManagerW(lpMachineNameW,lpDatabaseNameW,
207 dwDesiredAccess);
208 HeapFree(GetProcessHeap(),0,lpDatabaseNameW);
209 HeapFree(GetProcessHeap(),0,lpMachineNameW);
210 return ret;
213 /******************************************************************************
214 * OpenSCManagerW [ADVAPI32.111]
215 * Establishes a connection to the service control manager and opens database
217 * NOTES
218 * This should return a SC_HANDLE
220 * PARAMS
221 * lpMachineName [I] Pointer to machine name string
222 * lpDatabaseName [I] Pointer to database name string
223 * dwDesiredAccess [I] Type of access
225 * RETURNS
226 * Success: Handle to service control manager database
227 * Failure: NULL
229 SC_HANDLE WINAPI
230 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
231 DWORD dwDesiredAccess )
233 HKEY hKey;
234 LONG r;
236 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
237 debugstr_w(lpDatabaseName), dwDesiredAccess);
240 * FIXME: what is lpDatabaseName?
241 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
242 * docs, but what if it isn't?
245 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey);
246 if (r!=ERROR_SUCCESS)
247 return 0;
249 TRACE("returning %x\n",hKey);
251 return hKey;
255 /******************************************************************************
256 * AllocateLocallyUniqueId [ADVAPI32.12]
258 * PARAMS
259 * lpluid []
261 BOOL WINAPI
262 AllocateLocallyUniqueId( PLUID lpluid )
264 lpluid->s.LowPart = time(NULL);
265 lpluid->s.HighPart = 0;
266 return TRUE;
270 /******************************************************************************
271 * ControlService [ADVAPI32.23]
272 * Sends a control code to a Win32-based service.
274 * PARAMS
275 * hService []
276 * dwControl []
277 * lpServiceStatus []
279 * RETURNS STD
281 BOOL WINAPI
282 ControlService( SC_HANDLE hService, DWORD dwControl,
283 LPSERVICE_STATUS lpServiceStatus )
285 FIXME("(%d,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
286 return TRUE;
290 /******************************************************************************
291 * CloseServiceHandle [ADVAPI32.22]
292 * Close handle to service or service control manager
294 * PARAMS
295 * hSCObject [I] Handle to service or service control manager database
297 * RETURNS STD
299 BOOL WINAPI
300 CloseServiceHandle( SC_HANDLE hSCObject )
302 TRACE("(%x)\n", hSCObject);
304 RegCloseKey(hSCObject);
306 return TRUE;
310 /******************************************************************************
311 * OpenServiceA [ADVAPI32.112]
313 SC_HANDLE WINAPI
314 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
315 DWORD dwDesiredAccess )
317 LPWSTR lpServiceNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName);
318 DWORD ret;
320 if(lpServiceName)
321 TRACE("Request for service %s\n",lpServiceName);
322 else
323 return FALSE;
324 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
325 HeapFree(GetProcessHeap(),0,lpServiceNameW);
326 return ret;
330 /******************************************************************************
331 * OpenServiceW [ADVAPI32.113]
332 * Opens a handle to an existing service
334 * PARAMS
335 * hSCManager []
336 * lpServiceName []
337 * dwDesiredAccess []
339 * RETURNS
340 * Success: Handle to the service
341 * Failure: NULL
343 SC_HANDLE WINAPI
344 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
345 DWORD dwDesiredAccess)
347 const char *str = "System\\CurrentControlSet\\Services\\";
348 WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */
349 HKEY hKey;
350 long r;
352 TRACE("(%d,%p,%ld)\n",hSCManager, lpServiceName,
353 dwDesiredAccess);
355 MultiByteToWideChar( CP_ACP, 0, str, -1, lpServiceKey, sizeof(lpServiceKey)/sizeof(WCHAR) );
356 strcatW(lpServiceKey,lpServiceName);
358 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey));
360 /* FIXME: dwDesiredAccess may need some processing */
361 r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey );
362 if (r!=ERROR_SUCCESS)
363 return 0;
365 TRACE("returning %x\n",hKey);
367 return hKey;
370 /******************************************************************************
371 * CreateServiceW [ADVAPI32.29]
373 SC_HANDLE WINAPI
374 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
375 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
376 DWORD dwServiceType, DWORD dwStartType,
377 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
378 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
379 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
380 LPCWSTR lpPassword )
382 FIXME("(%u,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
383 return FALSE;
387 /******************************************************************************
388 * CreateServiceA [ADVAPI32.28]
390 SC_HANDLE WINAPI
391 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
392 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
393 DWORD dwServiceType, DWORD dwStartType,
394 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
395 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
396 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
397 LPCSTR lpPassword )
399 HKEY hKey;
400 LONG r;
401 DWORD dp;
403 TRACE("(%u,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
405 r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL,
406 REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp);
407 if (r!=ERROR_SUCCESS)
408 return 0;
409 if (dp != REG_CREATED_NEW_KEY)
410 return 0;
412 if(lpDisplayName)
414 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, strlen(lpDisplayName) );
415 if (r!=ERROR_SUCCESS)
416 return 0;
419 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
420 if (r!=ERROR_SUCCESS)
421 return 0;
423 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
424 if (r!=ERROR_SUCCESS)
425 return 0;
427 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
428 (LPVOID)&dwErrorControl, sizeof (DWORD) );
429 if (r!=ERROR_SUCCESS)
430 return 0;
432 if(lpBinaryPathName)
434 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
435 lpBinaryPathName,strlen(lpBinaryPathName)+1 );
436 if (r!=ERROR_SUCCESS)
437 return 0;
440 if(lpLoadOrderGroup)
442 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
443 lpLoadOrderGroup, strlen(lpLoadOrderGroup)+1 );
444 if (r!=ERROR_SUCCESS)
445 return 0;
448 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
449 (LPVOID)&dwErrorControl, sizeof (DWORD) );
450 if (r!=ERROR_SUCCESS)
451 return 0;
453 if(lpDependencies)
455 DWORD len = 0;
457 /* determine the length of a double null terminated multi string */
458 do {
459 len += (strlen(&lpDependencies[len])+1);
460 } while (lpDependencies[len++]);
462 /* fixme: this should be unicode */
463 r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ,
464 lpDependencies, len );
465 if (r!=ERROR_SUCCESS)
466 return 0;
469 if(lpPassword)
471 FIXME("Don't know how to add a Password for a service.\n");
474 if(lpServiceStartName)
476 FIXME("Don't know how to add a ServiceStartName for a service.\n");
479 return hKey;
483 /******************************************************************************
484 * DeleteService [ADVAPI32.31]
486 * PARAMS
487 * hService [I] Handle to service
489 * RETURNS STD
492 BOOL WINAPI
493 DeleteService( SC_HANDLE hService )
495 FIXME("(%d): stub\n",hService);
496 return TRUE;
500 /******************************************************************************
501 * StartServiceA [ADVAPI32.195]
504 BOOL WINAPI
505 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
506 LPCSTR *lpServiceArgVectors )
508 LPWSTR *lpwstr=NULL;
509 int i;
511 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
513 if(dwNumServiceArgs)
514 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
515 dwNumServiceArgs*sizeof(LPWSTR) );
516 else
517 lpwstr = NULL;
519 for(i=0; i<dwNumServiceArgs; i++)
520 lpwstr[i]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors[i]);
522 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
524 if(dwNumServiceArgs)
526 for(i=0; i<dwNumServiceArgs; i++)
527 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
528 HeapFree(GetProcessHeap(), 0, lpwstr);
531 return TRUE;
535 /******************************************************************************
536 * StartServiceW [ADVAPI32.198]
537 * Starts a service
539 * PARAMS
540 * hService [I] Handle of service
541 * dwNumServiceArgs [I] Number of arguments
542 * lpServiceArgVectors [I] Address of array of argument string pointers
544 * NOTES
546 * NT implements this function using an obscure RPC call...
548 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
549 * to get things like %SystemRoot%\\System32\\service.exe to load.
551 * Will only work for shared address space. How should the service
552 * args be transferred when address spaces are separated?
554 * Can only start one service at a time.
556 * Has no concept of priviledge.
558 * RETURNS STD
561 BOOL WINAPI
562 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
563 LPCWSTR *lpServiceArgVectors )
565 CHAR path[MAX_PATH],str[MAX_PATH];
566 DWORD type,size;
567 long r;
568 HANDLE data,wait;
569 PROCESS_INFORMATION procinfo;
570 STARTUPINFOA startupinfo;
572 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,
573 lpServiceArgVectors);
575 size = sizeof str;
576 r = RegQueryValueExA(hService, "ImagePath", NULL, &type, (LPVOID)str, &size);
577 if (r!=ERROR_SUCCESS)
578 return FALSE;
579 ExpandEnvironmentStringsA(str,path,sizeof path);
581 TRACE("Starting service %s\n", debugstr_a(path) );
583 data = CreateSemaphoreA(NULL,1,1,"ADVAPI32_ServiceStartData");
584 if(data == ERROR_INVALID_HANDLE)
586 data = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
587 if(data == 0)
589 ERR("Couldn't create data semaphore\n");
590 return FALSE;
593 wait = CreateSemaphoreA(NULL,0,1,"ADVAPI32_WaitServiceStart");
595 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
596 if(wait == 0)
598 ERR("Couldn't create wait semaphore\n");
599 return FALSE;
604 * FIXME: lpServiceArgsVectors need to be stored and returned to
605 * the service when it calls StartServiceCtrlDispatcher
607 * Chuck these in a global (yuk) so we can pass them to
608 * another process - address space separation will break this.
611 r = WaitForSingleObject(data,INFINITE);
613 if( r == WAIT_FAILED)
614 return FALSE;
616 start_dwNumServiceArgs = dwNumServiceArgs;
617 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
619 ZeroMemory(&startupinfo,sizeof(STARTUPINFOA));
620 startupinfo.cb = sizeof(STARTUPINFOA);
622 r = CreateProcessA(path,
623 NULL,
624 NULL, /* process security attribs */
625 NULL, /* thread security attribs */
626 FALSE, /* inherit handles */
627 0, /* creation flags */
628 NULL, /* environment */
629 NULL, /* current directory */
630 &startupinfo, /* startup info */
631 &procinfo); /* process info */
633 if(r == FALSE)
635 ERR("Couldn't start process\n");
636 /* ReleaseSemaphore(data, 1, NULL);
637 return FALSE; */
640 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
641 r = WaitForSingleObject(wait,30000);
643 ReleaseSemaphore(data, 1, NULL);
645 if( r == WAIT_FAILED)
646 return FALSE;
648 return TRUE;
651 /******************************************************************************
652 * QueryServiceStatus [ADVAPI32.123]
654 * PARAMS
655 * hService []
656 * lpservicestatus []
659 BOOL WINAPI
660 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
662 LONG r;
663 DWORD type, val, size;
665 FIXME("(%x,%p) partial\n",hService,lpservicestatus);
667 /* read the service type from the registry */
668 size = sizeof val;
669 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
670 if(type!=REG_DWORD)
672 ERR("invalid Type\n");
673 return FALSE;
675 lpservicestatus->dwServiceType = val;
676 /* FIXME: how are these determined or read from the registry? */
677 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
678 lpservicestatus->dwCurrentState = 1;
679 lpservicestatus->dwControlsAccepted = 0;
680 lpservicestatus->dwWin32ExitCode = NO_ERROR;
681 lpservicestatus->dwServiceSpecificExitCode = 0;
682 lpservicestatus->dwCheckPoint = 0;
683 lpservicestatus->dwWaitHint = 0;
685 return TRUE;