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
28 #include "wine/unicode.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.@]
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("%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);
52 /******************************************************************************
53 * EnumServicesStatusW [ADVAPI32.@]
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("%x 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);
67 /******************************************************************************
68 * StartServiceCtrlDispatcherA [ADVAPI32.@]
71 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
73 LPSERVICE_MAIN_FUNCTIONA fpMain;
75 DWORD dwNumServiceArgs ;
80 TRACE("(%p)\n", servent);
81 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
84 ERR("Couldn't find wait semaphore\n");
85 ERR("perhaps you need to start services using StartService\n");
89 dwNumServiceArgs = start_dwNumServiceArgs;
90 lpArgVecW = start_lpServiceArgVectors;
92 ReleaseSemaphore(wait, 1, NULL);
94 /* Convert the Unicode arg vectors back to ASCII */
96 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
97 dwNumServiceArgs*sizeof(LPSTR) );
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);
117 /* free arg strings */
118 for(i=0; i<dwNumServiceArgs; i++)
119 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
120 HeapFree(GetProcessHeap(), 0, lpArgVecA);
126 /******************************************************************************
127 * StartServiceCtrlDispatcherW [ADVAPI32.@]
133 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
135 LPSERVICE_MAIN_FUNCTIONW fpMain;
137 DWORD dwNumServiceArgs ;
138 LPWSTR *lpServiceArgVectors ;
140 TRACE("(%p)\n", servent);
141 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
144 ERR("Couldn't find wait semaphore\n");
145 ERR("perhaps you need to start services using StartService\n");
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);
168 /******************************************************************************
169 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
171 SERVICE_STATUS_HANDLE WINAPI
172 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
173 LPHANDLER_FUNCTION lpfHandler )
174 { FIXME("%s %p\n", lpServiceName, lpfHandler);
178 /******************************************************************************
179 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
185 SERVICE_STATUS_HANDLE WINAPI
186 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
187 LPHANDLER_FUNCTION lpfHandler )
188 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
192 /******************************************************************************
193 * SetServiceStatus [ADVAPI32.@]
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);
212 /******************************************************************************
213 * OpenSCManagerA [ADVAPI32.@]
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,
223 HeapFree(GetProcessHeap(),0,lpDatabaseNameW);
224 HeapFree(GetProcessHeap(),0,lpMachineNameW);
228 /******************************************************************************
229 * OpenSCManagerW [ADVAPI32.@]
230 * Establishes a connection to the service control manager and opens database
233 * This should return a SC_HANDLE
236 * lpMachineName [I] Pointer to machine name string
237 * lpDatabaseName [I] Pointer to database name string
238 * dwDesiredAccess [I] Type of access
241 * Success: Handle to service control manager database
245 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
246 DWORD dwDesiredAccess )
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)
264 TRACE("returning %x\n",hKey);
270 /******************************************************************************
271 * AllocateLocallyUniqueId [ADVAPI32.@]
277 AllocateLocallyUniqueId( PLUID lpluid )
279 lpluid->LowPart = time(NULL);
280 lpluid->HighPart = 0;
285 /******************************************************************************
286 * ControlService [ADVAPI32.@]
287 * Sends a control code to a Win32-based service.
297 ControlService( SC_HANDLE hService, DWORD dwControl,
298 LPSERVICE_STATUS lpServiceStatus )
300 FIXME("(%d,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
305 /******************************************************************************
306 * CloseServiceHandle [ADVAPI32.@]
307 * Close handle to service or service control manager
310 * hSCObject [I] Handle to service or service control manager database
315 CloseServiceHandle( SC_HANDLE hSCObject )
317 TRACE("(%x)\n", hSCObject);
319 RegCloseKey(hSCObject);
325 /******************************************************************************
326 * OpenServiceA [ADVAPI32.@]
329 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
330 DWORD dwDesiredAccess )
332 LPWSTR lpServiceNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName);
336 TRACE("Request for service %s\n",lpServiceName);
339 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
340 HeapFree(GetProcessHeap(),0,lpServiceNameW);
345 /******************************************************************************
346 * OpenServiceW [ADVAPI32.@]
347 * Opens a handle to an existing service
355 * Success: Handle to the service
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 */
367 TRACE("(%d,%p,%ld)\n",hSCManager, lpServiceName,
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)
380 TRACE("returning %x\n",hKey);
385 /******************************************************************************
386 * CreateServiceW [ADVAPI32.@]
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,
397 FIXME("(%u,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
402 /******************************************************************************
403 * CreateServiceA [ADVAPI32.@]
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,
418 TRACE("(%u,%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)
424 if (dp != REG_CREATED_NEW_KEY)
429 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, strlen(lpDisplayName) );
430 if (r!=ERROR_SUCCESS)
434 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
435 if (r!=ERROR_SUCCESS)
438 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
439 if (r!=ERROR_SUCCESS)
442 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
443 (LPVOID)&dwErrorControl, sizeof (DWORD) );
444 if (r!=ERROR_SUCCESS)
449 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
450 lpBinaryPathName,strlen(lpBinaryPathName)+1 );
451 if (r!=ERROR_SUCCESS)
457 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
458 lpLoadOrderGroup, strlen(lpLoadOrderGroup)+1 );
459 if (r!=ERROR_SUCCESS)
463 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
464 (LPVOID)&dwErrorControl, sizeof (DWORD) );
465 if (r!=ERROR_SUCCESS)
472 /* determine the length of a double null terminated multi string */
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)
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");
498 /******************************************************************************
499 * DeleteService [ADVAPI32.@]
502 * hService [I] Handle to service
508 DeleteService( SC_HANDLE hService )
510 FIXME("(%d): stub\n",hService);
515 /******************************************************************************
516 * StartServiceA [ADVAPI32.@]
520 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
521 LPCSTR *lpServiceArgVectors )
526 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
529 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
530 dwNumServiceArgs*sizeof(LPWSTR) );
534 for(i=0; i<dwNumServiceArgs; i++)
535 lpwstr[i]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors[i]);
537 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
541 for(i=0; i<dwNumServiceArgs; i++)
542 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
543 HeapFree(GetProcessHeap(), 0, lpwstr);
550 /******************************************************************************
551 * StartServiceW [ADVAPI32.@]
555 * hService [I] Handle of service
556 * dwNumServiceArgs [I] Number of arguments
557 * lpServiceArgVectors [I] Address of array of argument string pointers
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.
577 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
578 LPCWSTR *lpServiceArgVectors )
580 CHAR path[MAX_PATH],str[MAX_PATH];
584 PROCESS_INFORMATION procinfo;
585 STARTUPINFOA startupinfo;
587 TRACE("(%d,%ld,%p)\n",hService,dwNumServiceArgs,
588 lpServiceArgVectors);
591 r = RegQueryValueExA(hService, "ImagePath", NULL, &type, (LPVOID)str, &size);
592 if (r!=ERROR_SUCCESS)
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 == ERROR_INVALID_HANDLE)
601 data = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
604 ERR("Couldn't create data semaphore\n");
608 wait = CreateSemaphoreA(NULL,0,1,"ADVAPI32_WaitServiceStart");
610 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
613 ERR("Couldn't create wait semaphore\n");
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)
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,
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 */
651 ERR("Couldn't start process\n");
652 /* ReleaseSemaphore(data, 1, NULL);
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)
667 /******************************************************************************
668 * QueryServiceStatus [ADVAPI32.@]
676 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
679 DWORD type, val, size;
681 FIXME("(%x,%p) partial\n",hService,lpservicestatus);
683 /* read the service type from the registry */
685 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
688 ERR("invalid Type\n");
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;