2 * Win32 advapi functions
4 * Copyright 1995 Sven Verdoolaege
14 #include "debugtools.h"
16 DEFAULT_DEBUG_CHANNEL(advapi
)
18 static DWORD start_dwNumServiceArgs
;
19 static LPWSTR
*start_lpServiceArgVectors
;
21 /******************************************************************************
22 * EnumServicesStatusA [ADVAPI32.@]
25 EnumServicesStatusA( SC_HANDLE hSCManager
, DWORD dwServiceType
,
26 DWORD dwServiceState
, LPENUM_SERVICE_STATUSA lpServices
,
27 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
,
28 LPDWORD lpServicesReturned
, LPDWORD lpResumeHandle
)
29 { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager
,
30 dwServiceType
, dwServiceState
, lpServices
, cbBufSize
,
31 pcbBytesNeeded
, lpServicesReturned
, lpResumeHandle
);
32 SetLastError (ERROR_ACCESS_DENIED
);
36 /******************************************************************************
37 * EnumServicesStatusW [ADVAPI32.@]
40 EnumServicesStatusW( SC_HANDLE hSCManager
, DWORD dwServiceType
,
41 DWORD dwServiceState
, LPENUM_SERVICE_STATUSW lpServices
,
42 DWORD cbBufSize
, LPDWORD pcbBytesNeeded
,
43 LPDWORD lpServicesReturned
, LPDWORD lpResumeHandle
)
44 { FIXME("%x type=%lx state=%lx %p %lx %p %p %p\n", hSCManager
,
45 dwServiceType
, dwServiceState
, lpServices
, cbBufSize
,
46 pcbBytesNeeded
, lpServicesReturned
, lpResumeHandle
);
47 SetLastError (ERROR_ACCESS_DENIED
);
51 /******************************************************************************
52 * StartServiceCtrlDispatcherA [ADVAPI32.196]
55 StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent
)
57 LPSERVICE_MAIN_FUNCTIONA fpMain
;
59 DWORD dwNumServiceArgs
;
64 TRACE("(%p)\n", servent
);
65 wait
= OpenSemaphoreA(SEMAPHORE_ALL_ACCESS
, FALSE
, "ADVAPI32_ServiceStartData");
68 ERR("Couldn't find wait semaphore\n");
69 ERR("perhaps you need to start services using StartService\n");
73 dwNumServiceArgs
= start_dwNumServiceArgs
;
74 lpArgVecW
= start_lpServiceArgVectors
;
76 ReleaseSemaphore(wait
, 1, NULL
);
78 /* Convert the Unicode arg vectors back to ASCII */
80 lpArgVecA
= (LPSTR
*) HeapAlloc( GetProcessHeap(), 0,
81 dwNumServiceArgs
*sizeof(LPSTR
) );
85 for(i
=0; i
<dwNumServiceArgs
; i
++)
86 lpArgVecA
[i
]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW
[i
]);
88 /* FIXME: should we blindly start all services? */
89 while (servent
->lpServiceName
) {
90 TRACE("%s at %p)\n", debugstr_a(servent
->lpServiceName
),servent
);
91 fpMain
= servent
->lpServiceProc
;
93 /* try to start the service */
94 fpMain( dwNumServiceArgs
, lpArgVecA
);
101 /* free arg strings */
102 for(i
=0; i
<dwNumServiceArgs
; i
++)
103 HeapFree(GetProcessHeap(), 0, lpArgVecA
[i
]);
104 HeapFree(GetProcessHeap(), 0, lpArgVecA
);
110 /******************************************************************************
111 * StartServiceCtrlDispatcherW [ADVAPI32.197]
117 StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent
)
119 LPSERVICE_MAIN_FUNCTIONW fpMain
;
121 DWORD dwNumServiceArgs
;
122 LPWSTR
*lpServiceArgVectors
;
124 TRACE("(%p)\n", servent
);
125 wait
= OpenSemaphoreA(SEMAPHORE_ALL_ACCESS
, FALSE
, "ADVAPI32_ServiceStartData");
128 ERR("Couldn't find wait semaphore\n");
129 ERR("perhaps you need to start services using StartService\n");
133 dwNumServiceArgs
= start_dwNumServiceArgs
;
134 lpServiceArgVectors
= start_lpServiceArgVectors
;
136 ReleaseSemaphore(wait
, 1, NULL
);
138 /* FIXME: should we blindly start all services? */
139 while (servent
->lpServiceName
) {
140 TRACE("%s at %p)\n", debugstr_w(servent
->lpServiceName
),servent
);
141 fpMain
= servent
->lpServiceProc
;
143 /* try to start the service */
144 fpMain( dwNumServiceArgs
, lpServiceArgVectors
);
152 /******************************************************************************
153 * RegisterServiceCtrlHandlerA [ADVAPI32.176]
155 SERVICE_STATUS_HANDLE WINAPI
156 RegisterServiceCtrlHandlerA( LPCSTR lpServiceName
,
157 LPHANDLER_FUNCTION lpfHandler
)
158 { FIXME("%s %p\n", lpServiceName
, lpfHandler
);
162 /******************************************************************************
163 * RegisterServiceCtrlHandlerW [ADVAPI32.177]
169 SERVICE_STATUS_HANDLE WINAPI
170 RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName
,
171 LPHANDLER_FUNCTION lpfHandler
)
172 { FIXME("%s %p\n", debugstr_w(lpServiceName
), lpfHandler
);
176 /******************************************************************************
177 * SetServiceStatus [ADVAPI32.192]
184 SetServiceStatus( SERVICE_STATUS_HANDLE hService
, LPSERVICE_STATUS lpStatus
)
185 { FIXME("%lx %p\n",hService
, lpStatus
);
186 TRACE("\tType:%lx\n",lpStatus
->dwServiceType
);
187 TRACE("\tState:%lx\n",lpStatus
->dwCurrentState
);
188 TRACE("\tControlAccepted:%lx\n",lpStatus
->dwControlsAccepted
);
189 TRACE("\tExitCode:%lx\n",lpStatus
->dwWin32ExitCode
);
190 TRACE("\tServiceExitCode:%lx\n",lpStatus
->dwServiceSpecificExitCode
);
191 TRACE("\tCheckPoint:%lx\n",lpStatus
->dwCheckPoint
);
192 TRACE("\tWaitHint:%lx\n",lpStatus
->dwWaitHint
);
196 /******************************************************************************
197 * OpenSCManagerA [ADVAPI32.110]
200 OpenSCManagerA( LPCSTR lpMachineName
, LPCSTR lpDatabaseName
,
201 DWORD dwDesiredAccess
)
203 LPWSTR lpMachineNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpMachineName
);
204 LPWSTR lpDatabaseNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpDatabaseName
);
205 DWORD ret
= OpenSCManagerW(lpMachineNameW
,lpDatabaseNameW
,
207 HeapFree(GetProcessHeap(),0,lpDatabaseNameW
);
208 HeapFree(GetProcessHeap(),0,lpMachineNameW
);
212 /******************************************************************************
213 * OpenSCManagerW [ADVAPI32.111]
214 * Establishes a connection to the service control manager and opens database
217 * This should return a SC_HANDLE
220 * lpMachineName [I] Pointer to machine name string
221 * lpDatabaseName [I] Pointer to database name string
222 * dwDesiredAccess [I] Type of access
225 * Success: Handle to service control manager database
229 OpenSCManagerW( LPCWSTR lpMachineName
, LPCWSTR lpDatabaseName
,
230 DWORD dwDesiredAccess
)
235 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName
),
236 debugstr_w(lpDatabaseName
), dwDesiredAccess
);
239 * FIXME: what is lpDatabaseName?
240 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
241 * docs, but what if it isn't?
244 r
= RegConnectRegistryW(lpMachineName
,HKEY_LOCAL_MACHINE
,&hKey
);
245 if (r
!=ERROR_SUCCESS
)
248 TRACE("returning %x\n",hKey
);
254 /******************************************************************************
255 * AllocateLocallyUniqueId [ADVAPI32.12]
261 AllocateLocallyUniqueId( PLUID lpluid
)
263 lpluid
->s
.LowPart
= time(NULL
);
264 lpluid
->s
.HighPart
= 0;
269 /******************************************************************************
270 * ControlService [ADVAPI32.23]
271 * Sends a control code to a Win32-based service.
281 ControlService( SC_HANDLE hService
, DWORD dwControl
,
282 LPSERVICE_STATUS lpServiceStatus
)
284 FIXME("(%d,%ld,%p): stub\n",hService
,dwControl
,lpServiceStatus
);
289 /******************************************************************************
290 * CloseServiceHandle [ADVAPI32.22]
291 * Close handle to service or service control manager
294 * hSCObject [I] Handle to service or service control manager database
299 CloseServiceHandle( SC_HANDLE hSCObject
)
301 TRACE("(%x)\n", hSCObject
);
303 RegCloseKey(hSCObject
);
309 /******************************************************************************
310 * OpenServiceA [ADVAPI32.112]
313 OpenServiceA( SC_HANDLE hSCManager
, LPCSTR lpServiceName
,
314 DWORD dwDesiredAccess
)
316 LPWSTR lpServiceNameW
= HEAP_strdupAtoW(GetProcessHeap(),0,lpServiceName
);
320 TRACE("Request for service %s\n",lpServiceName
);
323 ret
= OpenServiceW( hSCManager
, lpServiceNameW
, dwDesiredAccess
);
324 HeapFree(GetProcessHeap(),0,lpServiceNameW
);
329 /******************************************************************************
330 * OpenServiceW [ADVAPI32.113]
331 * Opens a handle to an existing service
339 * Success: Handle to the service
343 OpenServiceW(SC_HANDLE hSCManager
, LPCWSTR lpServiceName
,
344 DWORD dwDesiredAccess
)
346 const char *str
= "System\\CurrentControlSet\\Services\\";
347 WCHAR lpServiceKey
[80]; /* FIXME: this should be dynamically allocated */
351 TRACE("(%d,%p,%ld)\n",hSCManager
, lpServiceName
,
354 lstrcpyAtoW(lpServiceKey
,str
);
355 lstrcatW(lpServiceKey
,lpServiceName
);
357 TRACE("Opening reg key %s\n", debugstr_w(lpServiceKey
));
359 /* FIXME: dwDesiredAccess may need some processing */
360 r
= RegOpenKeyExW(hSCManager
, lpServiceKey
, 0, dwDesiredAccess
, &hKey
);
361 if (r
!=ERROR_SUCCESS
)
364 TRACE("returning %x\n",hKey
);
369 /******************************************************************************
370 * CreateServiceW [ADVAPI32.29]
373 CreateServiceW( DWORD hSCManager
, LPCWSTR lpServiceName
,
374 LPCWSTR lpDisplayName
, DWORD dwDesiredAccess
,
375 DWORD dwServiceType
, DWORD dwStartType
,
376 DWORD dwErrorControl
, LPCWSTR lpBinaryPathName
,
377 LPCWSTR lpLoadOrderGroup
, LPDWORD lpdwTagId
,
378 LPCWSTR lpDependencies
, LPCWSTR lpServiceStartName
,
381 FIXME("(%ld,%s,%s,...)\n", hSCManager
, debugstr_w(lpServiceName
), debugstr_w(lpDisplayName
));
386 /******************************************************************************
387 * CreateServiceA [ADVAPI32.28]
390 CreateServiceA( DWORD hSCManager
, LPCSTR lpServiceName
,
391 LPCSTR lpDisplayName
, DWORD dwDesiredAccess
,
392 DWORD dwServiceType
, DWORD dwStartType
,
393 DWORD dwErrorControl
, LPCSTR lpBinaryPathName
,
394 LPCSTR lpLoadOrderGroup
, LPDWORD lpdwTagId
,
395 LPCSTR lpDependencies
, LPCSTR lpServiceStartName
,
402 TRACE("(%ld,%s,%s,...)\n", hSCManager
, debugstr_a(lpServiceName
), debugstr_a(lpDisplayName
));
404 r
= RegCreateKeyExA(hSCManager
, lpServiceName
, 0, NULL
,
405 REG_OPTION_NON_VOLATILE
, dwDesiredAccess
, NULL
, &hKey
, &dp
);
406 if (r
!=ERROR_SUCCESS
)
408 if (dp
!= REG_CREATED_NEW_KEY
)
413 r
= RegSetValueExA(hKey
, "DisplayName", 0, REG_SZ
, lpDisplayName
, lstrlenA(lpDisplayName
) );
414 if (r
!=ERROR_SUCCESS
)
418 r
= RegSetValueExA(hKey
, "Type", 0, REG_DWORD
, (LPVOID
)&dwServiceType
, sizeof (DWORD
) );
419 if (r
!=ERROR_SUCCESS
)
422 r
= RegSetValueExA(hKey
, "Start", 0, REG_DWORD
, (LPVOID
)&dwStartType
, sizeof (DWORD
) );
423 if (r
!=ERROR_SUCCESS
)
426 r
= RegSetValueExA(hKey
, "ErrorControl", 0, REG_DWORD
,
427 (LPVOID
)&dwErrorControl
, sizeof (DWORD
) );
428 if (r
!=ERROR_SUCCESS
)
433 r
= RegSetValueExA(hKey
, "ImagePath", 0, REG_SZ
,
434 lpBinaryPathName
,lstrlenA(lpBinaryPathName
)+1 );
435 if (r
!=ERROR_SUCCESS
)
441 r
= RegSetValueExA(hKey
, "Group", 0, REG_SZ
,
442 lpLoadOrderGroup
, lstrlenA(lpLoadOrderGroup
)+1 );
443 if (r
!=ERROR_SUCCESS
)
447 r
= RegSetValueExA(hKey
, "ErrorControl", 0, REG_DWORD
,
448 (LPVOID
)&dwErrorControl
, sizeof (DWORD
) );
449 if (r
!=ERROR_SUCCESS
)
456 /* determine the length of a double null terminated multi string */
458 len
+= (lstrlenA(&lpDependencies
[len
])+1);
459 } while (lpDependencies
[len
++]);
461 /* fixme: this should be unicode */
462 r
= RegSetValueExA(hKey
, "Dependencies", 0, REG_MULTI_SZ
,
463 lpDependencies
, len
);
464 if (r
!=ERROR_SUCCESS
)
470 FIXME("Don't know how to add a Password for a service.\n");
473 if(lpServiceStartName
)
475 FIXME("Don't know how to add a ServiceStartName for a service.\n");
482 /******************************************************************************
483 * DeleteService [ADVAPI32.31]
486 * hService [I] Handle to service
492 DeleteService( SC_HANDLE hService
)
494 FIXME("(%d): stub\n",hService
);
499 /******************************************************************************
500 * StartServiceA [ADVAPI32.195]
504 StartServiceA( SC_HANDLE hService
, DWORD dwNumServiceArgs
,
505 LPCSTR
*lpServiceArgVectors
)
510 TRACE("(%d,%ld,%p)\n",hService
,dwNumServiceArgs
,lpServiceArgVectors
);
513 lpwstr
= (LPWSTR
*) HeapAlloc( GetProcessHeap(), 0,
514 dwNumServiceArgs
*sizeof(LPWSTR
) );
518 for(i
=0; i
<dwNumServiceArgs
; i
++)
519 lpwstr
[i
]=HEAP_strdupAtoW(GetProcessHeap(), 0, lpServiceArgVectors
[i
]);
521 StartServiceW(hService
, dwNumServiceArgs
, (LPCWSTR
*)lpwstr
);
525 for(i
=0; i
<dwNumServiceArgs
; i
++)
526 HeapFree(GetProcessHeap(), 0, lpwstr
[i
]);
527 HeapFree(GetProcessHeap(), 0, lpwstr
);
534 /******************************************************************************
535 * StartServiceW [ADVAPI32.198]
539 * hService [I] Handle of service
540 * dwNumServiceArgs [I] Number of arguments
541 * lpServiceArgVectors [I] Address of array of argument string pointers
545 * NT implements this function using an obscure RPC call...
547 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
548 * to get things like %SystemRoot%\\System32\\service.exe to load.
550 * Will only work for shared address space. How should the service
551 * args be transferred when address spaces are separated?
553 * Can only start one service at a time.
555 * Has no concept of priviledge.
561 StartServiceW( SC_HANDLE hService
, DWORD dwNumServiceArgs
,
562 LPCWSTR
*lpServiceArgVectors
)
564 CHAR path
[MAX_PATH
],str
[MAX_PATH
];
568 PROCESS_INFORMATION procinfo
;
569 STARTUPINFOA startupinfo
;
571 TRACE("(%d,%ld,%p)\n",hService
,dwNumServiceArgs
,
572 lpServiceArgVectors
);
575 r
= RegQueryValueExA(hService
, "ImagePath", NULL
, &type
, (LPVOID
)str
, &size
);
576 if (r
!=ERROR_SUCCESS
)
578 ExpandEnvironmentStringsA(str
,path
,sizeof path
);
580 TRACE("Starting service %s\n", debugstr_a(path
) );
582 data
= CreateSemaphoreA(NULL
,1,1,"ADVAPI32_ServiceStartData");
583 if(data
== ERROR_INVALID_HANDLE
)
585 data
= OpenSemaphoreA(SEMAPHORE_ALL_ACCESS
, FALSE
, "ADVAPI32_ServiceStartData");
588 ERR("Couldn't create data semaphore\n");
592 wait
= CreateSemaphoreA(NULL
,0,1,"ADVAPI32_WaitServiceStart");
594 wait
= OpenSemaphoreA(SEMAPHORE_ALL_ACCESS
, FALSE
, "ADVAPI32_ServiceStartData");
597 ERR("Couldn't create wait semaphore\n");
603 * FIXME: lpServiceArgsVectors need to be stored and returned to
604 * the service when it calls StartServiceCtrlDispatcher
606 * Chuck these in a global (yuk) so we can pass them to
607 * another process - address space separation will break this.
610 r
= WaitForSingleObject(data
,INFINITE
);
612 if( r
== WAIT_FAILED
)
615 start_dwNumServiceArgs
= dwNumServiceArgs
;
616 start_lpServiceArgVectors
= (LPWSTR
*)lpServiceArgVectors
;
618 ZeroMemory(&startupinfo
,sizeof(STARTUPINFOA
));
619 startupinfo
.cb
= sizeof(STARTUPINFOA
);
621 r
= CreateProcessA(path
,
623 NULL
, /* process security attribs */
624 NULL
, /* thread security attribs */
625 FALSE
, /* inherit handles */
626 0, /* creation flags */
627 NULL
, /* environment */
628 NULL
, /* current directory */
629 &startupinfo
, /* startup info */
630 &procinfo
); /* process info */
634 ERR("Couldn't start process\n");
635 /* ReleaseSemaphore(data, 1, NULL);
639 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
640 r
= WaitForSingleObject(wait
,30000);
642 ReleaseSemaphore(data
, 1, NULL
);
644 if( r
== WAIT_FAILED
)
650 /******************************************************************************
651 * QueryServiceStatus [ADVAPI32.123]
659 QueryServiceStatus( SC_HANDLE hService
, LPSERVICE_STATUS lpservicestatus
)
662 DWORD type
, val
, size
;
664 FIXME("(%x,%p) partial\n",hService
,lpservicestatus
);
666 /* read the service type from the registry */
668 r
= RegQueryValueExA(hService
, "Type", NULL
, &type
, (LPBYTE
)&val
, &size
);
671 ERR("invalid Type\n");
674 lpservicestatus
->dwServiceType
= val
;
675 /* FIXME: how are these determined or read from the registry? */
676 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
677 lpservicestatus
->dwCurrentState
= 1;
678 lpservicestatus
->dwControlsAccepted
= 0;
679 lpservicestatus
->dwWin32ExitCode
= NO_ERROR
;
680 lpservicestatus
->dwServiceSpecificExitCode
= 0;
681 lpservicestatus
->dwCheckPoint
= 0;
682 lpservicestatus
->dwWaitHint
= 0;