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("%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);
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("%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);
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 * LockServiceDatabase [ADVAPI32.@]
171 LPVOID WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
173 FIXME("%p\n",hSCManager);
174 return (SC_HANDLE)0xcacacafe;
177 /******************************************************************************
178 * UnlockServiceDatabase [ADVAPI32.@]
180 BOOL WINAPI UnlockServiceDatabase (LPVOID ScLock)
182 FIXME(": %p\n",ScLock);
186 /******************************************************************************
187 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
189 SERVICE_STATUS_HANDLE WINAPI
190 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
191 LPHANDLER_FUNCTION lpfHandler )
192 { FIXME("%s %p\n", lpServiceName, lpfHandler);
196 /******************************************************************************
197 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
203 SERVICE_STATUS_HANDLE WINAPI
204 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
205 LPHANDLER_FUNCTION lpfHandler )
206 { FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
210 /******************************************************************************
211 * SetServiceStatus [ADVAPI32.@]
218 SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
219 { FIXME("0x%lx %p\n",hService, lpStatus);
220 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
221 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
222 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
223 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
224 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
225 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
226 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
230 /******************************************************************************
231 * OpenSCManagerA [ADVAPI32.@]
234 OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
235 DWORD dwDesiredAccess )
237 LPWSTR lpMachineNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpMachineName);
238 LPWSTR lpDatabaseNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpDatabaseName);
239 SC_HANDLE ret = OpenSCManagerW(lpMachineNameW,lpDatabaseNameW,
241 HeapFree(GetProcessHeap(),0,lpDatabaseNameW);
242 HeapFree(GetProcessHeap(),0,lpMachineNameW);
246 /******************************************************************************
247 * OpenSCManagerW [ADVAPI32.@]
248 * Establishes a connection to the service control manager and opens database
251 * This should return a SC_HANDLE
254 * lpMachineName [I] Pointer to machine name string
255 * lpDatabaseName [I] Pointer to database name string
256 * dwDesiredAccess [I] Type of access
259 * Success: Handle to service control manager database
263 OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
264 DWORD dwDesiredAccess )
269 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
270 debugstr_w(lpDatabaseName), dwDesiredAccess);
273 * FIXME: what is lpDatabaseName?
274 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
275 * docs, but what if it isn't?
278 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hKey);
279 if (r!=ERROR_SUCCESS)
282 TRACE("returning %p\n",hKey);
288 /******************************************************************************
289 * AllocateLocallyUniqueId [ADVAPI32.@]
295 AllocateLocallyUniqueId( PLUID lpluid )
297 lpluid->LowPart = time(NULL);
298 lpluid->HighPart = 0;
303 /******************************************************************************
304 * ControlService [ADVAPI32.@]
305 * Sends a control code to a Win32-based service.
315 ControlService( SC_HANDLE hService, DWORD dwControl,
316 LPSERVICE_STATUS lpServiceStatus )
318 FIXME("(%p,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
323 /******************************************************************************
324 * CloseServiceHandle [ADVAPI32.@]
325 * Close handle to service or service control manager
328 * hSCObject [I] Handle to service or service control manager database
333 CloseServiceHandle( SC_HANDLE hSCObject )
335 TRACE("(%p)\n", hSCObject);
337 RegCloseKey(hSCObject);
343 /******************************************************************************
344 * OpenServiceA [ADVAPI32.@]
347 OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
348 DWORD dwDesiredAccess )
350 LPWSTR lpServiceNameW = HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName);
354 TRACE("Request for service %s\n",lpServiceName);
357 ret = OpenServiceW( hSCManager, lpServiceNameW, dwDesiredAccess);
358 HeapFree(GetProcessHeap(),0,lpServiceNameW);
363 /******************************************************************************
364 * OpenServiceW [ADVAPI32.@]
365 * Opens a handle to an existing service
373 * Success: Handle to the service
377 OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
378 DWORD dwDesiredAccess)
380 const char *str = "System\\CurrentControlSet\\Services\\";
381 WCHAR lpServiceKey[80]; /* FIXME: this should be dynamically allocated */
385 TRACE("(%p,%p,%ld)\n",hSCManager, lpServiceName,
388 MultiByteToWideChar( CP_ACP, 0, str, -1, lpServiceKey, sizeof(lpServiceKey)/sizeof(WCHAR) );
389 strcatW(lpServiceKey,lpServiceName);
391 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey));
393 /* FIXME: dwDesiredAccess may need some processing */
394 r = RegOpenKeyExW(hSCManager, lpServiceKey, 0, dwDesiredAccess, &hKey );
395 if (r!=ERROR_SUCCESS)
398 TRACE("returning %p\n",hKey);
403 /******************************************************************************
404 * CreateServiceW [ADVAPI32.@]
407 CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
408 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
409 DWORD dwServiceType, DWORD dwStartType,
410 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
411 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
412 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
415 FIXME("(%p,%s,%s,...)\n", hSCManager, debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
420 /******************************************************************************
421 * CreateServiceA [ADVAPI32.@]
424 CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
425 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
426 DWORD dwServiceType, DWORD dwStartType,
427 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
428 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
429 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
436 TRACE("(%p,%s,%s,...)\n", hSCManager, debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
438 r = RegCreateKeyExA(hSCManager, lpServiceName, 0, NULL,
439 REG_OPTION_NON_VOLATILE, dwDesiredAccess, NULL, &hKey, &dp);
440 if (r!=ERROR_SUCCESS)
442 if (dp != REG_CREATED_NEW_KEY)
447 r = RegSetValueExA(hKey, "DisplayName", 0, REG_SZ, lpDisplayName, strlen(lpDisplayName) );
448 if (r!=ERROR_SUCCESS)
452 r = RegSetValueExA(hKey, "Type", 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
453 if (r!=ERROR_SUCCESS)
456 r = RegSetValueExA(hKey, "Start", 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
457 if (r!=ERROR_SUCCESS)
460 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
461 (LPVOID)&dwErrorControl, sizeof (DWORD) );
462 if (r!=ERROR_SUCCESS)
467 r = RegSetValueExA(hKey, "ImagePath", 0, REG_SZ,
468 lpBinaryPathName,strlen(lpBinaryPathName)+1 );
469 if (r!=ERROR_SUCCESS)
475 r = RegSetValueExA(hKey, "Group", 0, REG_SZ,
476 lpLoadOrderGroup, strlen(lpLoadOrderGroup)+1 );
477 if (r!=ERROR_SUCCESS)
481 r = RegSetValueExA(hKey, "ErrorControl", 0, REG_DWORD,
482 (LPVOID)&dwErrorControl, sizeof (DWORD) );
483 if (r!=ERROR_SUCCESS)
490 /* determine the length of a double null terminated multi string */
492 len += (strlen(&lpDependencies[len])+1);
493 } while (lpDependencies[len++]);
495 /* FIXME: this should be unicode */
496 r = RegSetValueExA(hKey, "Dependencies", 0, REG_MULTI_SZ,
497 lpDependencies, len );
498 if (r!=ERROR_SUCCESS)
504 FIXME("Don't know how to add a Password for a service.\n");
507 if(lpServiceStartName)
509 FIXME("Don't know how to add a ServiceStartName for a service.\n");
516 /******************************************************************************
517 * DeleteService [ADVAPI32.@]
520 * hService [I] Handle to service
526 DeleteService( SC_HANDLE hService )
528 FIXME("(%p): stub\n",hService);
533 /******************************************************************************
534 * StartServiceA [ADVAPI32.@]
538 StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
539 LPCSTR *lpServiceArgVectors )
544 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
547 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
548 dwNumServiceArgs*sizeof(LPWSTR) );
552 for(i=0; i<dwNumServiceArgs; i++)
553 lpwstr[i]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors[i]);
555 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
559 for(i=0; i<dwNumServiceArgs; i++)
560 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
561 HeapFree(GetProcessHeap(), 0, lpwstr);
568 /******************************************************************************
569 * StartServiceW [ADVAPI32.@]
573 * hService [I] Handle of service
574 * dwNumServiceArgs [I] Number of arguments
575 * lpServiceArgVectors [I] Address of array of argument string pointers
579 * NT implements this function using an obscure RPC call...
581 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
582 * to get things like %SystemRoot%\\System32\\service.exe to load.
584 * Will only work for shared address space. How should the service
585 * args be transferred when address spaces are separated?
587 * Can only start one service at a time.
589 * Has no concept of privilege.
595 StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
596 LPCWSTR *lpServiceArgVectors )
598 CHAR path[MAX_PATH],str[MAX_PATH];
602 PROCESS_INFORMATION procinfo;
603 STARTUPINFOA startupinfo;
605 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,
606 lpServiceArgVectors);
609 r = RegQueryValueExA(hService, "ImagePath", NULL, &type, (LPVOID)str, &size);
610 if (r!=ERROR_SUCCESS)
612 ExpandEnvironmentStringsA(str,path,sizeof path);
614 TRACE("Starting service %s\n", debugstr_a(path) );
616 data = CreateSemaphoreA(NULL,1,1,"ADVAPI32_ServiceStartData");
619 data = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
622 ERR("Couldn't create data semaphore\n");
626 wait = CreateSemaphoreA(NULL,0,1,"ADVAPI32_WaitServiceStart");
628 wait = OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, FALSE, "ADVAPI32_ServiceStartData");
631 ERR("Couldn't create wait semaphore\n");
637 * FIXME: lpServiceArgsVectors need to be stored and returned to
638 * the service when it calls StartServiceCtrlDispatcher
640 * Chuck these in a global (yuk) so we can pass them to
641 * another process - address space separation will break this.
644 r = WaitForSingleObject(data,INFINITE);
646 if( r == WAIT_FAILED)
649 FIXME("problematic because of address space separation.\n");
650 start_dwNumServiceArgs = dwNumServiceArgs;
651 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
653 ZeroMemory(&startupinfo,sizeof(STARTUPINFOA));
654 startupinfo.cb = sizeof(STARTUPINFOA);
656 r = CreateProcessA(path,
658 NULL, /* process security attribs */
659 NULL, /* thread security attribs */
660 FALSE, /* inherit handles */
661 0, /* creation flags */
662 NULL, /* environment */
663 NULL, /* current directory */
664 &startupinfo, /* startup info */
665 &procinfo); /* process info */
669 ERR("Couldn't start process\n");
670 /* ReleaseSemaphore(data, 1, NULL);
674 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
675 r = WaitForSingleObject(wait,30000);
677 ReleaseSemaphore(data, 1, NULL);
679 if( r == WAIT_FAILED)
685 /******************************************************************************
686 * QueryServiceStatus [ADVAPI32.@]
694 QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
697 DWORD type, val, size;
699 FIXME("(%p,%p) partial\n",hService,lpservicestatus);
701 /* read the service type from the registry */
703 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
706 ERR("invalid Type\n");
709 lpservicestatus->dwServiceType = val;
710 /* FIXME: how are these determined or read from the registry? */
711 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
712 lpservicestatus->dwCurrentState = 1;
713 lpservicestatus->dwControlsAccepted = 0;
714 lpservicestatus->dwWin32ExitCode = NO_ERROR;
715 lpservicestatus->dwServiceSpecificExitCode = 0;
716 lpservicestatus->dwCheckPoint = 0;
717 lpservicestatus->dwWaitHint = 0;
722 /******************************************************************************
723 * QueryServiceStatusEx [ADVAPI32.@]
726 * hService [handle to service]
727 * InfoLevel [information level]
729 * cbBufSize [size of buffer]
730 * pcbBytesNeeded [bytes needed]
732 BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
733 LPBYTE lpBuffer, DWORD cbBufSize,
734 LPDWORD pcbBytesNeeded)
737 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);