Mark immutable objects as const. Fix inconsistent *-style.
[wine/multimedia.git] / dlls / advapi32 / service.c
blob146ac86c007e18f095589d67bde58918fffb3a4d
1 /*
2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 #include <string.h>
22 #include <time.h>
24 #include "windef.h"
25 #include "winsvc.h"
26 #include "winerror.h"
27 #include "winreg.h"
28 #include "wine/unicode.h"
29 #include "heap.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
34 static DWORD start_dwNumServiceArgs;
35 static LPWSTR *start_lpServiceArgVectors;
37 /******************************************************************************
38 * EnumServicesStatusA [ADVAPI32.@]
40 BOOL WINAPI
41 EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
42 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
43 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
44 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
45 { FIXME("%p 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 FALSE;
52 /******************************************************************************
53 * EnumServicesStatusW [ADVAPI32.@]
55 BOOL WINAPI
56 EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
57 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
58 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
59 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
60 { FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
61 dwServiceType, dwServiceState, lpServices, cbBufSize,
62 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
63 SetLastError (ERROR_ACCESS_DENIED);
64 return FALSE;
67 /******************************************************************************
68 * StartServiceCtrlDispatcherA [ADVAPI32.@]
70 BOOL WINAPI
71 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
73 LPSERVICE_MAIN_FUNCTIONA fpMain;
74 HANDLE wait;
75 DWORD dwNumServiceArgs ;
76 LPWSTR *lpArgVecW;
77 LPSTR *lpArgVecA;
78 int i;
80 TRACE("(%p)\n", servent);
81 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
82 if(wait == 0)
84 ERR("Couldn't find wait semaphore\n");
85 ERR("perhaps you need to start services using StartService\n");
86 return FALSE;
89 dwNumServiceArgs = start_dwNumServiceArgs;
90 lpArgVecW = start_lpServiceArgVectors;
92 ReleaseSemaphore(wait, 1, NULL);
94 /* Convert the Unicode arg vectors back to ASCII */
95 if(dwNumServiceArgs)
96 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
97 dwNumServiceArgs*sizeof(LPSTR) );
98 else
99 lpArgVecA = NULL;
101 for(i=0; i<dwNumServiceArgs; i++)
102 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
104 /* FIXME: should we blindly start all services? */
105 while (servent->lpServiceName) {
106 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
107 fpMain = servent->lpServiceProc;
109 /* try to start the service */
110 fpMain( dwNumServiceArgs, lpArgVecA);
112 servent++;
115 if(dwNumServiceArgs)
117 /* free arg strings */
118 for(i=0; i<dwNumServiceArgs; i++)
119 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
120 HeapFree(GetProcessHeap(), 0, lpArgVecA);
123 return TRUE;
126 /******************************************************************************
127 * StartServiceCtrlDispatcherW [ADVAPI32.@]
129 * PARAMS
130 * servent []
132 BOOL WINAPI
133 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
135 LPSERVICE_MAIN_FUNCTIONW fpMain;
136 HANDLE wait;
137 DWORD dwNumServiceArgs ;
138 LPWSTR *lpServiceArgVectors ;
140 TRACE("(%p)\n", servent);
141 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
142 if(wait == 0)
144 ERR("Couldn't find wait semaphore\n");
145 ERR("perhaps you need to start services using StartService\n");
146 return FALSE;
149 dwNumServiceArgs = start_dwNumServiceArgs;
150 lpServiceArgVectors = start_lpServiceArgVectors;
152 ReleaseSemaphore(wait, 1, NULL);
154 /* FIXME: should we blindly start all services? */
155 while (servent->lpServiceName) {
156 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
157 fpMain = servent->lpServiceProc;
159 /* try to start the service */
160 fpMain( dwNumServiceArgs, lpServiceArgVectors);
162 servent++;
165 return TRUE;
168 /******************************************************************************
169 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
171 SERVICE_STATUS_HANDLE WINAPI
172 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
173 LPHANDLER_FUNCTION lpfHandler )
174 { FIXME("%s %p\n", lpServiceName, lpfHandler);
175 return 0xcacacafe;
178 /******************************************************************************
179 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
181 * PARAMS
182 * lpServiceName []
183 * lpfHandler []
185 SERVICE_STATUS_HANDLE WINAPI
186 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
187 LPHANDLER_FUNCTION lpfHandler )
188 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
189 return 0xcacacafe;
192 /******************************************************************************
193 * SetServiceStatus [ADVAPI32.@]
195 * PARAMS
196 * hService []
197 * lpStatus []
199 BOOL WINAPI
200 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
201 { FIXME("0x%lx %p\n",hService, lpStatus);
202 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
203 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
204 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
205 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
206 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
207 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
208 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
209 return TRUE;
212 /******************************************************************************
213 * OpenSCManagerA [ADVAPI32.@]
215 SC_HANDLE WINAPI
216 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
217 DWORD dwDesiredAccess )
219 LPWSTR lpMachineNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpMachineName);
220 LPWSTR lpDatabaseNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpDatabaseName);
221 SC_HANDLE ret = OpenSCManagerW(lpMachineNameW,lpDatabaseNameW,
222 dwDesiredAccess);
223 HeapFree(GetProcessHeap(),0,lpDatabaseNameW);
224 HeapFree(GetProcessHeap(),0,lpMachineNameW);
225 return ret;
228 /******************************************************************************
229 * OpenSCManagerW [ADVAPI32.@]
230 * Establishes a connection to the service control manager and opens database
232 * NOTES
233 * This should return a SC_HANDLE
235 * PARAMS
236 * lpMachineName [I] Pointer to machine name string
237 * lpDatabaseName [I] Pointer to database name string
238 * dwDesiredAccess [I] Type of access
240 * RETURNS
241 * Success: Handle to service control manager database
242 * Failure: NULL
244 SC_HANDLE WINAPI
245 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
246 DWORD dwDesiredAccess )
248 HKEY hKey;
249 LONG r;
251 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
252 debugstr_w(lpDatabaseName), dwDesiredAccess);
255 * FIXME: what is lpDatabaseName?
256 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
257 * docs, but what if it isn't?
260 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey);
261 if (r!=ERROR_SUCCESS)
262 return 0;
264 TRACE("returning %p\n",hKey);
266 return hKey;
270 /******************************************************************************
271 * AllocateLocallyUniqueId [ADVAPI32.@]
273 * PARAMS
274 * lpluid []
276 BOOL WINAPI
277 AllocateLocallyUniqueId( PLUID lpluid )
279 lpluid->LowPart = time(NULL);
280 lpluid->HighPart = 0;
281 return TRUE;
285 /******************************************************************************
286 * ControlService [ADVAPI32.@]
287 * Sends a control code to a Win32-based service.
289 * PARAMS
290 * hService []
291 * dwControl []
292 * lpServiceStatus []
294 * RETURNS STD
296 BOOL WINAPI
297 ControlService( SC_HANDLE hService, DWORD dwControl,
298 LPSERVICE_STATUS lpServiceStatus )
300 FIXME("(%p,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
301 return TRUE;
305 /******************************************************************************
306 * CloseServiceHandle [ADVAPI32.@]
307 * Close handle to service or service control manager
309 * PARAMS
310 * hSCObject [I] Handle to service or service control manager database
312 * RETURNS STD
314 BOOL WINAPI
315 CloseServiceHandle( SC_HANDLE hSCObject )
317 TRACE("(%p)\n", hSCObject);
319 RegCloseKey(hSCObject);
321 return TRUE;
325 /******************************************************************************
326 * OpenServiceA [ADVAPI32.@]
328 SC_HANDLE WINAPI
329 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
330 DWORD dwDesiredAccess )
332 LPWSTR lpServiceNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName);
333 SC_HANDLE ret;
335 if(lpServiceName)
336 TRACE("Request for service %s\n",lpServiceName);
337 else
338 return FALSE;
339 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
340 HeapFree(GetProcessHeap(),0,lpServiceNameW);
341 return ret;
345 /******************************************************************************
346 * OpenServiceW [ADVAPI32.@]
347 * Opens a handle to an existing service
349 * PARAMS
350 * hSCManager []
351 * lpServiceName []
352 * dwDesiredAccess []
354 * RETURNS
355 * Success: Handle to the service
356 * Failure: NULL
358 SC_HANDLE WINAPI
359 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
360 DWORD dwDesiredAccess)
362 const char *str = "System\\CurrentControlSet\\Services\\";
363 WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */
364 HKEY hKey;
365 long r;
367 TRACE("(%p,%p,%ld)\n",hSCManager, lpServiceName,
368 dwDesiredAccess);
370 MultiByteToWideChar( CP_ACP, 0, str, -1, lpServiceKey, sizeof(lpServiceKey)/sizeof(WCHAR) );
371 strcatW(lpServiceKey,lpServiceName);
373 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey));
375 /* FIXME: dwDesiredAccess may need some processing */
376 r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey );
377 if (r!=ERROR_SUCCESS)
378 return 0;
380 TRACE("returning %p\n",hKey);
382 return hKey;
385 /******************************************************************************
386 * CreateServiceW [ADVAPI32.@]
388 SC_HANDLE WINAPI
389 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
390 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
391 DWORD dwServiceType, DWORD dwStartType,
392 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
393 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
394 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
395 LPCWSTR lpPassword )
397 FIXME("(%p,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
398 return 0;
402 /******************************************************************************
403 * CreateServiceA [ADVAPI32.@]
405 SC_HANDLE WINAPI
406 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
407 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
408 DWORD dwServiceType, DWORD dwStartType,
409 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
410 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
411 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
412 LPCSTR lpPassword )
414 HKEY hKey;
415 LONG r;
416 DWORD dp;
418 TRACE("(%p,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
420 r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL,
421 REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp);
422 if (r!=ERROR_SUCCESS)
423 return 0;
424 if (dp != REG_CREATED_NEW_KEY)
425 return 0;
427 if(lpDisplayName)
429 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, strlen(lpDisplayName) );
430 if (r!=ERROR_SUCCESS)
431 return 0;
434 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
435 if (r!=ERROR_SUCCESS)
436 return 0;
438 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
439 if (r!=ERROR_SUCCESS)
440 return 0;
442 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
443 (LPVOID)&dwErrorControl, sizeof (DWORD) );
444 if (r!=ERROR_SUCCESS)
445 return 0;
447 if(lpBinaryPathName)
449 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
450 lpBinaryPathName,strlen(lpBinaryPathName)+1 );
451 if (r!=ERROR_SUCCESS)
452 return 0;
455 if(lpLoadOrderGroup)
457 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
458 lpLoadOrderGroup, strlen(lpLoadOrderGroup)+1 );
459 if (r!=ERROR_SUCCESS)
460 return 0;
463 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
464 (LPVOID)&dwErrorControl, sizeof (DWORD) );
465 if (r!=ERROR_SUCCESS)
466 return 0;
468 if(lpDependencies)
470 DWORD len = 0;
472 /* determine the length of a double null terminated multi string */
473 do {
474 len += (strlen(&lpDependencies[len])+1);
475 } while (lpDependencies[len++]);
477 /* FIXME: this should be unicode */
478 r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ,
479 lpDependencies, len );
480 if (r!=ERROR_SUCCESS)
481 return 0;
484 if(lpPassword)
486 FIXME("Don't know how to add a Password for a service.\n");
489 if(lpServiceStartName)
491 FIXME("Don't know how to add a ServiceStartName for a service.\n");
494 return hKey;
498 /******************************************************************************
499 * DeleteService [ADVAPI32.@]
501 * PARAMS
502 * hService [I] Handle to service
504 * RETURNS STD
507 BOOL WINAPI
508 DeleteService( SC_HANDLE hService )
510 FIXME("(%p): stub\n",hService);
511 return TRUE;
515 /******************************************************************************
516 * StartServiceA [ADVAPI32.@]
519 BOOL WINAPI
520 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
521 LPCSTR *lpServiceArgVectors )
523 LPWSTR *lpwstr=NULL;
524 int i;
526 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
528 if(dwNumServiceArgs)
529 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
530 dwNumServiceArgs*sizeof(LPWSTR) );
531 else
532 lpwstr = NULL;
534 for(i=0; i<dwNumServiceArgs; i++)
535 lpwstr[i]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors[i]);
537 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
539 if(dwNumServiceArgs)
541 for(i=0; i<dwNumServiceArgs; i++)
542 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
543 HeapFree(GetProcessHeap(), 0, lpwstr);
546 return TRUE;
550 /******************************************************************************
551 * StartServiceW [ADVAPI32.@]
552 * Starts a service
554 * PARAMS
555 * hService [I] Handle of service
556 * dwNumServiceArgs [I] Number of arguments
557 * lpServiceArgVectors [I] Address of array of argument string pointers
559 * NOTES
561 * NT implements this function using an obscure RPC call...
563 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
564 * to get things like %SystemRoot%\\System32\\service.exe to load.
566 * Will only work for shared address space. How should the service
567 * args be transferred when address spaces are separated?
569 * Can only start one service at a time.
571 * Has no concept of privilege.
573 * RETURNS STD
576 BOOL WINAPI
577 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
578 LPCWSTR *lpServiceArgVectors )
580 CHAR path[MAX_PATH],str[MAX_PATH];
581 DWORD type,size;
582 long r;
583 HANDLE data,wait;
584 PROCESS_INFORMATION procinfo;
585 STARTUPINFOA startupinfo;
587 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,
588 lpServiceArgVectors);
590 size = sizeof str;
591 r = RegQueryValueExA(hService, "ImagePath", NULL, &type, (LPVOID)str, &size);
592 if (r!=ERROR_SUCCESS)
593 return FALSE;
594 ExpandEnvironmentStringsA(str,path,sizeof path);
596 TRACE("Starting service %s\n", debugstr_a(path) );
598 data = CreateSemaphoreA(NULL,1,1,"ADVAPI32_ServiceStartData");
599 if (!data)
601 data = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
602 if(data == 0)
604 ERR("Couldn't create data semaphore\n");
605 return FALSE;
608 wait = CreateSemaphoreA(NULL,0,1,"ADVAPI32_WaitServiceStart");
610 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
611 if(wait == 0)
613 ERR("Couldn't create wait semaphore\n");
614 return FALSE;
619 * FIXME: lpServiceArgsVectors need to be stored and returned to
620 * the service when it calls StartServiceCtrlDispatcher
622 * Chuck these in a global (yuk) so we can pass them to
623 * another process - address space separation will break this.
626 r = WaitForSingleObject(data,INFINITE);
628 if( r == WAIT_FAILED)
629 return FALSE;
631 FIXME("problematic because of address space separation.\n");
632 start_dwNumServiceArgs = dwNumServiceArgs;
633 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
635 ZeroMemory(&startupinfo,sizeof(STARTUPINFOA));
636 startupinfo.cb = sizeof(STARTUPINFOA);
638 r = CreateProcessA(path,
639 NULL,
640 NULL, /* process security attribs */
641 NULL, /* thread security attribs */
642 FALSE, /* inherit handles */
643 0, /* creation flags */
644 NULL, /* environment */
645 NULL, /* current directory */
646 &startupinfo, /* startup info */
647 &procinfo); /* process info */
649 if(r == FALSE)
651 ERR("Couldn't start process\n");
652 /* ReleaseSemaphore(data, 1, NULL);
653 return FALSE; */
656 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
657 r = WaitForSingleObject(wait,30000);
659 ReleaseSemaphore(data, 1, NULL);
661 if( r == WAIT_FAILED)
662 return FALSE;
664 return TRUE;
667 /******************************************************************************
668 * QueryServiceStatus [ADVAPI32.@]
670 * PARAMS
671 * hService []
672 * lpservicestatus []
675 BOOL WINAPI
676 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
678 LONG r;
679 DWORD type, val, size;
681 FIXME("(%p,%p) partial\n",hService,lpservicestatus);
683 /* read the service type from the registry */
684 size = sizeof val;
685 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
686 if(type!=REG_DWORD)
688 ERR("invalid Type\n");
689 return FALSE;
691 lpservicestatus->dwServiceType = val;
692 /* FIXME: how are these determined or read from the registry? */
693 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
694 lpservicestatus->dwCurrentState = 1;
695 lpservicestatus->dwControlsAccepted = 0;
696 lpservicestatus->dwWin32ExitCode = NO_ERROR;
697 lpservicestatus->dwServiceSpecificExitCode = 0;
698 lpservicestatus->dwCheckPoint = 0;
699 lpservicestatus->dwWaitHint = 0;
701 return TRUE;