blob: 82701e4579009cb4c7be546a990bb4075ac7592b [file] [log] [blame]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +00001/*
2 * Win32 advapi functions
3 *
4 * Copyright 1995 Sven Verdoolaege
Alexandre Julliard0799c1a2002-03-09 23:29:33 +00005 *
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.
10 *
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.
15 *
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
Juergen Schmiedf7b0de31999-01-03 12:48:29 +000019 */
20
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000021#include <stdarg.h>
James Juranf4d5fef2001-01-26 20:43:40 +000022#include <string.h>
Juergen Schmiedf7b0de31999-01-03 12:48:29 +000023#include <time.h>
Patrik Stridvall4a739731999-07-04 11:01:21 +000024
Jim Aston2e1cafa1999-03-14 16:35:05 +000025#include "windef.h"
Alexandre Julliarde37c6e12003-09-05 23:08:26 +000026#include "winbase.h"
Patrik Stridvall4a739731999-07-04 11:01:21 +000027#include "winsvc.h"
Marcus Meissner317af321999-02-17 13:51:06 +000028#include "winerror.h"
Michael McCormack75a84131999-11-21 00:58:14 +000029#include "winreg.h"
Alexandre Julliardc7e7df82000-08-14 14:41:19 +000030#include "wine/unicode.h"
Marcus Meissner317af321999-02-17 13:51:06 +000031#include "heap.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000032#include "wine/debug.h"
Matthew Davison6f2a0712003-01-20 23:23:12 +000033#include "winternl.h"
Juergen Schmiedf7b0de31999-01-03 12:48:29 +000034
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000035WINE_DEFAULT_DEBUG_CHANNEL(advapi);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000036
Michael McCormack0c0f7d31999-12-04 04:03:45 +000037static DWORD start_dwNumServiceArgs;
38static LPWSTR *start_lpServiceArgVectors;
39
Alexandre Julliardb10dcfe2003-10-10 00:05:49 +000040static const WCHAR _ServiceStartDataW[] = {'A','D','V','A','P','I','_','S',
41 'e','r','v','i','c','e','S','t',
42 'a','r','t','D','a','t','a',0};
Aric Stewart3dc71b62003-12-13 03:25:37 +000043static const WCHAR szServiceManagerKey[] = { 'S','y','s','t','e','m','\\',
44 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
45 'S','e','r','v','i','c','e','s','\\',0 };
46
Alexandre Julliardb10dcfe2003-10-10 00:05:49 +000047
Matthew Beckere905f3c1999-01-28 13:46:25 +000048/******************************************************************************
Patrik Stridvall54fe8382000-04-06 20:21:16 +000049 * EnumServicesStatusA [ADVAPI32.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +000050 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000051BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +000052EnumServicesStatusA( SC_HANDLE hSCManager, DWORD dwServiceType,
Patrik Stridvall54fe8382000-04-06 20:21:16 +000053 DWORD dwServiceState, LPENUM_SERVICE_STATUSA lpServices,
54 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
55 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
Michael Stefaniuccbacde52002-10-25 19:17:33 +000056{ FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
Patrik Stridvall54fe8382000-04-06 20:21:16 +000057 dwServiceType, dwServiceState, lpServices, cbBufSize,
58 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
59 SetLastError (ERROR_ACCESS_DENIED);
François Gouget97ad5a72001-01-02 20:20:34 +000060 return FALSE;
Patrik Stridvall54fe8382000-04-06 20:21:16 +000061}
62
63/******************************************************************************
64 * EnumServicesStatusW [ADVAPI32.@]
65 */
66BOOL WINAPI
67EnumServicesStatusW( SC_HANDLE hSCManager, DWORD dwServiceType,
68 DWORD dwServiceState, LPENUM_SERVICE_STATUSW lpServices,
69 DWORD cbBufSize, LPDWORD pcbBytesNeeded,
70 LPDWORD lpServicesReturned, LPDWORD lpResumeHandle )
Michael Stefaniuccbacde52002-10-25 19:17:33 +000071{ FIXME("%p type=%lx state=%lx %p %lx %p %p %p\n", hSCManager,
Juergen Schmiedf7b0de31999-01-03 12:48:29 +000072 dwServiceType, dwServiceState, lpServices, cbBufSize,
73 pcbBytesNeeded, lpServicesReturned, lpResumeHandle);
74 SetLastError (ERROR_ACCESS_DENIED);
François Gouget97ad5a72001-01-02 20:20:34 +000075 return FALSE;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +000076}
Matthew Beckere905f3c1999-01-28 13:46:25 +000077
78/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +000079 * StartServiceCtrlDispatcherA [ADVAPI32.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +000080 */
Alexandre Julliarda3960291999-02-26 11:11:13 +000081BOOL WINAPI
82StartServiceCtrlDispatcherA( LPSERVICE_TABLE_ENTRYA servent )
Vincent Béron9a624912002-05-31 23:06:46 +000083{
Michael McCormack0c0f7d31999-12-04 04:03:45 +000084 LPSERVICE_MAIN_FUNCTIONA fpMain;
85 HANDLE wait;
86 DWORD dwNumServiceArgs ;
87 LPWSTR *lpArgVecW;
88 LPSTR *lpArgVecA;
89 int i;
Vincent Béron9a624912002-05-31 23:06:46 +000090
Michael McCormack0c0f7d31999-12-04 04:03:45 +000091 TRACE("(%p)\n", servent);
Alexandre Julliardb10dcfe2003-10-10 00:05:49 +000092 wait = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW);
Michael McCormack0c0f7d31999-12-04 04:03:45 +000093 if(wait == 0)
94 {
95 ERR("Couldn't find wait semaphore\n");
96 ERR("perhaps you need to start services using StartService\n");
97 return FALSE;
98 }
Juergen Schmiedf7b0de31999-01-03 12:48:29 +000099
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000100 dwNumServiceArgs = start_dwNumServiceArgs;
101 lpArgVecW = start_lpServiceArgVectors;
102
103 ReleaseSemaphore(wait, 1, NULL);
104
105 /* Convert the Unicode arg vectors back to ASCII */
106 if(dwNumServiceArgs)
Vincent Béron9a624912002-05-31 23:06:46 +0000107 lpArgVecA = (LPSTR*) HeapAlloc( GetProcessHeap(), 0,
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000108 dwNumServiceArgs*sizeof(LPSTR) );
109 else
110 lpArgVecA = NULL;
111
112 for(i=0; i<dwNumServiceArgs; i++)
113 lpArgVecA[i]=HEAP_strdupWtoA(GetProcessHeap(), 0, lpArgVecW[i]);
114
115 /* FIXME: should we blindly start all services? */
Vincent Béron9a624912002-05-31 23:06:46 +0000116 while (servent->lpServiceName) {
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000117 TRACE("%s at %p)\n", debugstr_a(servent->lpServiceName),servent);
118 fpMain = servent->lpServiceProc;
119
120 /* try to start the service */
121 fpMain( dwNumServiceArgs, lpArgVecA);
122
123 servent++;
124 }
125
126 if(dwNumServiceArgs)
127 {
128 /* free arg strings */
129 for(i=0; i<dwNumServiceArgs; i++)
130 HeapFree(GetProcessHeap(), 0, lpArgVecA[i]);
131 HeapFree(GetProcessHeap(), 0, lpArgVecA);
132 }
133
134 return TRUE;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000135}
136
Matthew Beckere905f3c1999-01-28 13:46:25 +0000137/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000138 * StartServiceCtrlDispatcherW [ADVAPI32.@]
Matthew Beckere905f3c1999-01-28 13:46:25 +0000139 *
140 * PARAMS
141 * servent []
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000142 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000143BOOL WINAPI
144StartServiceCtrlDispatcherW( LPSERVICE_TABLE_ENTRYW servent )
Vincent Béron9a624912002-05-31 23:06:46 +0000145{
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000146 LPSERVICE_MAIN_FUNCTIONW fpMain;
147 HANDLE wait;
148 DWORD dwNumServiceArgs ;
149 LPWSTR *lpServiceArgVectors ;
Vincent Béron9a624912002-05-31 23:06:46 +0000150
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000151 TRACE("(%p)\n", servent);
Matthew Davison620323e2003-01-24 00:45:51 +0000152 wait = OpenSemaphoreW(SEMAPHORE_ALL_ACCESS, FALSE, _ServiceStartDataW);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000153 if(wait == 0)
154 {
155 ERR("Couldn't find wait semaphore\n");
156 ERR("perhaps you need to start services using StartService\n");
157 return FALSE;
158 }
159
160 dwNumServiceArgs = start_dwNumServiceArgs;
161 lpServiceArgVectors = start_lpServiceArgVectors;
162
163 ReleaseSemaphore(wait, 1, NULL);
164
165 /* FIXME: should we blindly start all services? */
Vincent Béron9a624912002-05-31 23:06:46 +0000166 while (servent->lpServiceName) {
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000167 TRACE("%s at %p)\n", debugstr_w(servent->lpServiceName),servent);
168 fpMain = servent->lpServiceProc;
169
170 /* try to start the service */
171 fpMain( dwNumServiceArgs, lpServiceArgVectors);
172
173 servent++;
174 }
175
176 return TRUE;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000177}
178
Matthew Becker6d594451999-01-30 12:54:32 +0000179/******************************************************************************
Uwe Bonnes574d4a92003-01-14 19:31:44 +0000180 * LockServiceDatabase [ADVAPI32.@]
181 */
182LPVOID WINAPI LockServiceDatabase (SC_HANDLE hSCManager)
183{
184 FIXME("%p\n",hSCManager);
185 return (SC_HANDLE)0xcacacafe;
186}
187
188/******************************************************************************
189 * UnlockServiceDatabase [ADVAPI32.@]
190 */
191BOOL WINAPI UnlockServiceDatabase (LPVOID ScLock)
192{
193 FIXME(": %p\n",ScLock);
194 return TRUE;
195}
196
197/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000198 * RegisterServiceCtrlHandlerA [ADVAPI32.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000199 */
Matthew Beckere905f3c1999-01-28 13:46:25 +0000200SERVICE_STATUS_HANDLE WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000201RegisterServiceCtrlHandlerA( LPCSTR lpServiceName,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000202 LPHANDLER_FUNCTION lpfHandler )
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000203{ FIXME("%s %p\n", lpServiceName, lpfHandler);
Vincent Béron9a624912002-05-31 23:06:46 +0000204 return 0xcacacafe;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000205}
Matthew Beckere905f3c1999-01-28 13:46:25 +0000206
207/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000208 * RegisterServiceCtrlHandlerW [ADVAPI32.@]
Matthew Beckere905f3c1999-01-28 13:46:25 +0000209 *
210 * PARAMS
211 * lpServiceName []
212 * lpfHandler []
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000213 */
Matthew Beckere905f3c1999-01-28 13:46:25 +0000214SERVICE_STATUS_HANDLE WINAPI
Vincent Béron9a624912002-05-31 23:06:46 +0000215RegisterServiceCtrlHandlerW( LPCWSTR lpServiceName,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000216 LPHANDLER_FUNCTION lpfHandler )
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000217{ FIXME("%s %p\n", debugstr_w(lpServiceName), lpfHandler);
Vincent Béron9a624912002-05-31 23:06:46 +0000218 return 0xcacacafe;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000219}
Matthew Beckere905f3c1999-01-28 13:46:25 +0000220
221/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000222 * SetServiceStatus [ADVAPI32.@]
Matthew Beckere905f3c1999-01-28 13:46:25 +0000223 *
224 * PARAMS
225 * hService []
226 * lpStatus []
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000227 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000228BOOL WINAPI
Matthew Beckere905f3c1999-01-28 13:46:25 +0000229SetServiceStatus( SERVICE_STATUS_HANDLE hService, LPSERVICE_STATUS lpStatus )
François Gouget97ad5a72001-01-02 20:20:34 +0000230{ FIXME("0x%lx %p\n",hService, lpStatus);
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000231 TRACE("\tType:%lx\n",lpStatus->dwServiceType);
232 TRACE("\tState:%lx\n",lpStatus->dwCurrentState);
233 TRACE("\tControlAccepted:%lx\n",lpStatus->dwControlsAccepted);
234 TRACE("\tExitCode:%lx\n",lpStatus->dwWin32ExitCode);
235 TRACE("\tServiceExitCode:%lx\n",lpStatus->dwServiceSpecificExitCode);
236 TRACE("\tCheckPoint:%lx\n",lpStatus->dwCheckPoint);
237 TRACE("\tWaitHint:%lx\n",lpStatus->dwWaitHint);
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000238 return TRUE;
239}
240
241/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000242 * OpenSCManagerA [ADVAPI32.@]
Jon Griffiths50ce0842004-04-23 21:32:34 +0000243 *
244 * Establish a connection to the service control manager and open its database.
245 *
246 * PARAMS
247 * lpMachineName [I] Pointer to machine name string
248 * lpDatabaseName [I] Pointer to database name string
249 * dwDesiredAccess [I] Type of access
250 *
251 * RETURNS
252 * Success: A Handle to the service control manager database
253 * Failure: NULL
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000254 */
Jon Griffiths50ce0842004-04-23 21:32:34 +0000255SC_HANDLE WINAPI OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
256 DWORD dwDesiredAccess )
Vincent Béron9a624912002-05-31 23:06:46 +0000257{
Matthew Davison6f2a0712003-01-20 23:23:12 +0000258 UNICODE_STRING lpMachineNameW;
259 UNICODE_STRING lpDatabaseNameW;
260 SC_HANDLE ret;
261
262 RtlCreateUnicodeStringFromAsciiz (&lpMachineNameW,lpMachineName);
263 RtlCreateUnicodeStringFromAsciiz (&lpDatabaseNameW,lpDatabaseName);
264 ret = OpenSCManagerW(lpMachineNameW.Buffer,lpDatabaseNameW.Buffer, dwDesiredAccess);
265 RtlFreeUnicodeString(&lpDatabaseNameW);
266 RtlFreeUnicodeString(&lpMachineNameW);
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000267 return ret;
268}
269
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000270/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000271 * OpenSCManagerW [ADVAPI32.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000272 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000273 * See OpenSCManagerA.
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000274 */
Jon Griffiths50ce0842004-04-23 21:32:34 +0000275SC_HANDLE WINAPI OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
276 DWORD dwDesiredAccess )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000277{
Mike McCormack9b513ad2003-12-02 03:48:53 +0000278 HKEY hReg, hKey = NULL;
Michael McCormack75a84131999-11-21 00:58:14 +0000279 LONG r;
280
Vincent Béron9a624912002-05-31 23:06:46 +0000281 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000282 debugstr_w(lpDatabaseName), dwDesiredAccess);
Michael McCormack75a84131999-11-21 00:58:14 +0000283
284 /*
285 * FIXME: what is lpDatabaseName?
286 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
287 * docs, but what if it isn't?
288 */
289
Mike McCormack9b513ad2003-12-02 03:48:53 +0000290 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
291 if (r==ERROR_SUCCESS)
292 {
Aric Stewart3dc71b62003-12-13 03:25:37 +0000293 r = RegOpenKeyExW(hReg, szServiceManagerKey,0, dwDesiredAccess, &hKey );
Mike McCormack9b513ad2003-12-02 03:48:53 +0000294 RegCloseKey( hReg );
295 }
Michael McCormack75a84131999-11-21 00:58:14 +0000296
Mike McCormack9b513ad2003-12-02 03:48:53 +0000297 TRACE("returning %p\n", hKey);
Michael McCormack75a84131999-11-21 00:58:14 +0000298
299 return hKey;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000300}
301
302
Matthew Beckere905f3c1999-01-28 13:46:25 +0000303/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000304 * AllocateLocallyUniqueId [ADVAPI32.@]
Matthew Beckere905f3c1999-01-28 13:46:25 +0000305 *
306 * PARAMS
307 * lpluid []
308 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000309BOOL WINAPI
Juergen Schmied1ed51af1999-02-12 17:47:07 +0000310AllocateLocallyUniqueId( PLUID lpluid )
Matthew Beckere905f3c1999-01-28 13:46:25 +0000311{
Francois Gougetea31cf02001-11-20 18:52:20 +0000312 lpluid->LowPart = time(NULL);
313 lpluid->HighPart = 0;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000314 return TRUE;
315}
316
317
318/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000319 * ControlService [ADVAPI32.@]
Jon Griffiths50ce0842004-04-23 21:32:34 +0000320 *
321 * Send a control code to a service.
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000322 *
Matthew Beckere905f3c1999-01-28 13:46:25 +0000323 * PARAMS
Jon Griffiths50ce0842004-04-23 21:32:34 +0000324 * hService [I] Handle of the service control manager database
325 * dwControl [I] Control code to send (SERVICE_CONTROL_* flags from "winsvc.h")
326 * lpServiceStatus [O] Destination for the status of the service, if available
Matthew Beckere905f3c1999-01-28 13:46:25 +0000327 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000328 * RETURNS
329 * Success: TRUE.
330 * Failure: FALSE.
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000331 */
Jon Griffiths50ce0842004-04-23 21:32:34 +0000332BOOL WINAPI ControlService( SC_HANDLE hService, DWORD dwControl,
333 LPSERVICE_STATUS lpServiceStatus )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000334{
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000335 FIXME("(%p,%ld,%p): stub\n",hService,dwControl,lpServiceStatus);
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000336 return TRUE;
337}
338
339
340/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000341 * CloseServiceHandle [ADVAPI32.@]
Jon Griffiths50ce0842004-04-23 21:32:34 +0000342 *
343 * Close a handle to a service or the service control manager database.
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000344 *
345 * PARAMS
Matthew Beckere905f3c1999-01-28 13:46:25 +0000346 * hSCObject [I] Handle to service or service control manager database
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000347 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000348 * RETURNS
349 * Success: TRUE
350 * Failure: FALSE
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000351 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000352BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000353CloseServiceHandle( SC_HANDLE hSCObject )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000354{
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000355 TRACE("(%p)\n", hSCObject);
Michael McCormack75a84131999-11-21 00:58:14 +0000356
357 RegCloseKey(hSCObject);
Vincent Béron9a624912002-05-31 23:06:46 +0000358
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000359 return TRUE;
360}
361
362
363/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000364 * OpenServiceA [ADVAPI32.@]
Jon Griffiths50ce0842004-04-23 21:32:34 +0000365 *
366 * Open a handle to a service.
367 *
368 * PARAMS
369 * hSCManager [I] Handle of the service control manager database
370 * lpServiceName [I] Name of the service to open
371 * dwDesiredAccess [I] Access required to the service
372 *
373 * RETURNS
374 * Success: Handle to the service
375 * Failure: NULL
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000376 */
Jon Griffiths50ce0842004-04-23 21:32:34 +0000377SC_HANDLE WINAPI OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
378 DWORD dwDesiredAccess )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000379{
Matthew Davison6f2a0712003-01-20 23:23:12 +0000380 UNICODE_STRING lpServiceNameW;
François Gouget97ad5a72001-01-02 20:20:34 +0000381 SC_HANDLE ret;
Matthew Davison6f2a0712003-01-20 23:23:12 +0000382 RtlCreateUnicodeStringFromAsciiz (&lpServiceNameW,lpServiceName);
Michael McCormack75a84131999-11-21 00:58:14 +0000383 if(lpServiceName)
384 TRACE("Request for service %s\n",lpServiceName);
385 else
386 return FALSE;
Matthew Davison6f2a0712003-01-20 23:23:12 +0000387 ret = OpenServiceW( hSCManager, lpServiceNameW.Buffer, dwDesiredAccess);
388 RtlFreeUnicodeString(&lpServiceNameW);
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000389 return ret;
390}
391
392
393/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000394 * OpenServiceW [ADVAPI32.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000395 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000396 * See OpenServiceA.
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000397 */
Jon Griffiths50ce0842004-04-23 21:32:34 +0000398SC_HANDLE WINAPI OpenServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
399 DWORD dwDesiredAccess)
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000400{
Michael McCormack75a84131999-11-21 00:58:14 +0000401 HKEY hKey;
402 long r;
403
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000404 TRACE("(%p,%p,%ld)\n",hSCManager, lpServiceName,
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000405 dwDesiredAccess);
Michael McCormack75a84131999-11-21 00:58:14 +0000406
Alexandre Julliardbea945e2004-04-12 22:18:39 +0000407 r = RegOpenKeyExW(hSCManager, lpServiceName, 0, KEY_ALL_ACCESS, &hKey );
Michael McCormack75a84131999-11-21 00:58:14 +0000408 if (r!=ERROR_SUCCESS)
409 return 0;
410
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000411 TRACE("returning %p\n",hKey);
Michael McCormack75a84131999-11-21 00:58:14 +0000412
413 return hKey;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000414}
415
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000416/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000417 * CreateServiceW [ADVAPI32.@]
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000418 */
419SC_HANDLE WINAPI
Peter Hunnisett565b0082000-09-19 02:43:00 +0000420CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
Vincent Béron9a624912002-05-31 23:06:46 +0000421 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
422 DWORD dwServiceType, DWORD dwStartType,
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000423 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
Vincent Béron9a624912002-05-31 23:06:46 +0000424 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
425 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000426 LPCWSTR lpPassword )
427{
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000428 HKEY hKey;
429 LONG r;
430 DWORD dp;
Francois Gouget6a6c85c2004-04-19 20:12:14 +0000431 static const WCHAR szDisplayName[] = { 'D','i','s','p','l','a','y','N','a','m','e', 0 };
432 static const WCHAR szType[] = {'T','y','p','e',0};
433 static const WCHAR szStart[] = {'S','t','a','r','t',0};
434 static const WCHAR szError[] = {'E','r','r','o','r','C','o','n','t','r','o','l', 0};
435 static const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
436 static const WCHAR szGroup[] = {'G','r','o','u','p',0};
437 static const WCHAR szDependencies[] = { 'D','e','p','e','n','d','e','n','c','i','e','s',0};
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000438
Mike McCormack9b513ad2003-12-02 03:48:53 +0000439 FIXME("%p %s %s\n", hSCManager,
440 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000441
Mike McCormack9b513ad2003-12-02 03:48:53 +0000442 r = RegCreateKeyExW(hSCManager, lpServiceName, 0, NULL,
Aric Stewart3dc71b62003-12-13 03:25:37 +0000443 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000444 if (r!=ERROR_SUCCESS)
445 return 0;
Aric Stewart3dc71b62003-12-13 03:25:37 +0000446
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000447 if (dp != REG_CREATED_NEW_KEY)
448 return 0;
449
450 if(lpDisplayName)
451 {
Mike McCormack9b513ad2003-12-02 03:48:53 +0000452 r = RegSetValueExW(hKey, szDisplayName, 0, REG_SZ, (LPBYTE)lpDisplayName,
453 (strlenW(lpDisplayName)+1)*sizeof(WCHAR) );
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000454 if (r!=ERROR_SUCCESS)
455 return 0;
456 }
457
Mike McCormack9b513ad2003-12-02 03:48:53 +0000458 r = RegSetValueExW(hKey, szType, 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000459 if (r!=ERROR_SUCCESS)
460 return 0;
461
Mike McCormack9b513ad2003-12-02 03:48:53 +0000462 r = RegSetValueExW(hKey, szStart, 0, REG_DWORD, (LPVOID)&dwStartType, sizeof (DWORD) );
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000463 if (r!=ERROR_SUCCESS)
464 return 0;
465
Mike McCormack9b513ad2003-12-02 03:48:53 +0000466 r = RegSetValueExW(hKey, szError, 0, REG_DWORD,
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000467 (LPVOID)&dwErrorControl, sizeof (DWORD) );
468 if (r!=ERROR_SUCCESS)
469 return 0;
470
471 if(lpBinaryPathName)
472 {
Mike McCormack9b513ad2003-12-02 03:48:53 +0000473 r = RegSetValueExW(hKey, szImagePath, 0, REG_SZ, (LPBYTE)lpBinaryPathName,
474 (strlenW(lpBinaryPathName)+1)*sizeof(WCHAR) );
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000475 if (r!=ERROR_SUCCESS)
476 return 0;
477 }
478
479 if(lpLoadOrderGroup)
480 {
Mike McCormack9b513ad2003-12-02 03:48:53 +0000481 r = RegSetValueExW(hKey, szGroup, 0, REG_SZ, (LPBYTE)lpLoadOrderGroup,
482 (strlenW(lpLoadOrderGroup)+1)*sizeof(WCHAR) );
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000483 if (r!=ERROR_SUCCESS)
484 return 0;
485 }
486
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000487 if(lpDependencies)
488 {
Vincent Béron9a624912002-05-31 23:06:46 +0000489 DWORD len = 0;
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000490
491 /* determine the length of a double null terminated multi string */
492 do {
Mike McCormack9b513ad2003-12-02 03:48:53 +0000493 len += (strlenW(&lpDependencies[len])+1);
Vincent Béron9a624912002-05-31 23:06:46 +0000494 } while (lpDependencies[len++]);
495
Mike McCormack9b513ad2003-12-02 03:48:53 +0000496 r = RegSetValueExW(hKey, szDependencies, 0, REG_MULTI_SZ,
497 (LPBYTE)lpDependencies, len );
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000498 if (r!=ERROR_SUCCESS)
499 return 0;
500 }
501
502 if(lpPassword)
503 {
504 FIXME("Don't know how to add a Password for a service.\n");
505 }
506
507 if(lpServiceStartName)
508 {
509 FIXME("Don't know how to add a ServiceStartName for a service.\n");
510 }
511
512 return hKey;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000513}
514
515
Mike McCormack9b513ad2003-12-02 03:48:53 +0000516static inline LPWSTR SERV_dup( LPCSTR str )
517{
518 UINT len;
519 LPWSTR wstr;
520
521 if( !str )
522 return NULL;
523 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
524 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
525 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
526 return wstr;
527}
528
529static inline LPWSTR SERV_dupmulti( LPCSTR str )
530{
531 UINT len = 0, n = 0;
532 LPWSTR wstr;
533
Huw Davies28c2ea02003-12-11 04:26:20 +0000534 if( !str )
535 return NULL;
Mike McCormack9b513ad2003-12-02 03:48:53 +0000536 do {
537 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
538 n += (strlen( &str[n] ) + 1);
539 } while (str[n]);
540 len++;
541 n++;
542
543 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
544 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
545 return wstr;
546}
547
548static inline VOID SERV_free( LPWSTR wstr )
549{
550 HeapFree( GetProcessHeap(), 0, wstr );
551}
552
553/******************************************************************************
554 * CreateServiceA [ADVAPI32.@]
555 */
556SC_HANDLE WINAPI
557CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
558 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
559 DWORD dwServiceType, DWORD dwStartType,
560 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
561 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
562 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
563 LPCSTR lpPassword )
564{
565 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
566 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
567 SC_HANDLE r;
568
569 TRACE("%p %s %s\n", hSCManager,
570 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
571
572 lpServiceNameW = SERV_dup( lpServiceName );
573 lpDisplayNameW = SERV_dup( lpDisplayName );
574 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
575 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
576 lpDependenciesW = SERV_dupmulti( lpDependencies );
577 lpServiceStartNameW = SERV_dup( lpServiceStartName );
578 lpPasswordW = SERV_dup( lpPassword );
579
580 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
581 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
582 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
583 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
584
585 SERV_free( lpServiceNameW );
586 SERV_free( lpDisplayNameW );
587 SERV_free( lpBinaryPathNameW );
588 SERV_free( lpLoadOrderGroupW );
589 SERV_free( lpDependenciesW );
590 SERV_free( lpServiceStartNameW );
591 SERV_free( lpPasswordW );
592
593 return r;
594}
595
596
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000597/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000598 * DeleteService [ADVAPI32.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000599 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000600 * Delete a service from the service control manager database.
601 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000602 * PARAMS
Jon Griffiths50ce0842004-04-23 21:32:34 +0000603 * hService [I] Handle of the service to delete
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000604 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000605 * RETURNS
606 * Success: TRUE
607 * Failure: FALSE
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000608 */
Jon Griffiths50ce0842004-04-23 21:32:34 +0000609BOOL WINAPI DeleteService( SC_HANDLE hService )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000610{
Aric Stewart3dc71b62003-12-13 03:25:37 +0000611 WCHAR valname[MAX_PATH+1];
612 INT index = 0;
613 LONG rc;
614 DWORD value = 0x1;
615 DWORD size;
616 HKEY hKey;
617
618 static const WCHAR szDeleted[] = {'D','e','l','e','t','e','d',0};
619
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000620 FIXME("(%p): stub\n",hService);
Aric Stewart3dc71b62003-12-13 03:25:37 +0000621
622 size = MAX_PATH+1;
623 /* Clean out the values */
624 rc = RegEnumValueW(hService, index, valname,&size,0,0,0,0);
625 while (rc == ERROR_SUCCESS)
626 {
627 RegDeleteValueW(hService,valname);
628 index++;
629 size = MAX_PATH+1;
630 rc = RegEnumValueW(hService, index, valname, &size,0,0,0,0);
631 }
632
633 /* tag for deletion */
634 RegSetValueExW(hService, szDeleted, 0, REG_DWORD, (LPVOID)&value,
635 sizeof (DWORD) );
636
637 RegCloseKey(hService);
638
639 /* find and delete the key */
640 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szServiceManagerKey,0,
641 KEY_ALL_ACCESS, &hKey );
642 index = 0;
643 size = MAX_PATH+1;
644 rc = RegEnumKeyExW(hKey,0, valname, &size, 0, 0, 0, 0);
645 while (rc == ERROR_SUCCESS)
646 {
647 HKEY checking;
648 rc = RegOpenKeyExW(hKey,valname,0,KEY_ALL_ACCESS,&checking);
649 if (rc == ERROR_SUCCESS)
650 {
651 DWORD deleted = 0;
652 DWORD size = sizeof(DWORD);
653 rc = RegQueryValueExW(checking, szDeleted , NULL, NULL,
654 (LPVOID)&deleted, &size);
655 if (deleted)
656 {
657 RegDeleteValueW(checking,szDeleted);
658 RegDeleteKeyW(hKey,valname);
659 }
660 else
661 index ++;
662 RegCloseKey(checking);
663 }
664 size = MAX_PATH+1;
665 rc = RegEnumKeyExW(hKey, index, valname, &size, 0, 0, 0, 0);
666 }
667 RegCloseKey(hKey);
668
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000669 return TRUE;
670}
671
672
673/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000674 * StartServiceA [ADVAPI32.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000675 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000676 * Start a service
677 *
678 * PARAMS
679 * hService [I] Handle of service
680 * dwNumServiceArgs [I] Number of arguments
681 * lpServiceArgVectors [I] Address of array of argument strings
682 *
683 * NOTES
684 * - NT implements this function using an obscure RPC call.
685 * - You might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
686 * to get things like "%SystemRoot%\\System32\\service.exe" to load.
687 * - This will only work for shared address space. How should the service
688 * args be transferred when address spaces are separated?
689 * - Can only start one service at a time.
690 * - Has no concept of privilege.
691 *
692 * RETURNS
693 * Success: TRUE.
694 * Failure: FALSE
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000695 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000696BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000697StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000698 LPCSTR *lpServiceArgVectors )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000699{
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000700 LPWSTR *lpwstr=NULL;
Matthew Davison60009b92003-01-23 23:07:38 +0000701 UNICODE_STRING usBuffer;
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000702 int i;
703
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000704 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000705
706 if(dwNumServiceArgs)
Vincent Béron9a624912002-05-31 23:06:46 +0000707 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000708 dwNumServiceArgs*sizeof(LPWSTR) );
709 else
710 lpwstr = NULL;
711
712 for(i=0; i<dwNumServiceArgs; i++)
Matthew Davison60009b92003-01-23 23:07:38 +0000713 {
714 RtlCreateUnicodeStringFromAsciiz (&usBuffer,lpServiceArgVectors[i]);
715 lpwstr[i]=usBuffer.Buffer;
716 }
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000717
Andreas Mohr7fb732e1999-12-12 00:47:51 +0000718 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000719
720 if(dwNumServiceArgs)
721 {
722 for(i=0; i<dwNumServiceArgs; i++)
723 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
724 HeapFree(GetProcessHeap(), 0, lpwstr);
725 }
726
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000727 return TRUE;
728}
729
730
731/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000732 * StartServiceW [ADVAPI32.@]
Jon Griffiths50ce0842004-04-23 21:32:34 +0000733 *
734 * See StartServiceA.
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000735 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000736BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000737StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000738 LPCWSTR *lpServiceArgVectors )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000739{
Matthew Davison620323e2003-01-24 00:45:51 +0000740 static const WCHAR _WaitServiceStartW[] = {'A','D','V','A','P','I','_','W',
741 'a','i','t','S','e','r','v','i',
742 'c','e','S','t','a','r','t',0};
743 static const WCHAR _ImagePathW[] = {'I','m','a','g','e','P','a','t','h',0};
744
745 WCHAR path[MAX_PATH],str[MAX_PATH];
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000746 DWORD type,size;
747 long r;
748 HANDLE data,wait;
749 PROCESS_INFORMATION procinfo;
Matthew Davison620323e2003-01-24 00:45:51 +0000750 STARTUPINFOW startupinfo;
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000751 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000752 lpServiceArgVectors);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000753
Francois Gouget95918362003-06-18 19:45:22 +0000754 size = sizeof(str);
Matthew Davison620323e2003-01-24 00:45:51 +0000755 r = RegQueryValueExW(hService, _ImagePathW, NULL, &type, (LPVOID)str, &size);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000756 if (r!=ERROR_SUCCESS)
757 return FALSE;
Francois Gouget95918362003-06-18 19:45:22 +0000758 ExpandEnvironmentStringsW(str,path,sizeof(path));
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000759
Matthew Davison620323e2003-01-24 00:45:51 +0000760 TRACE("Starting service %s\n", debugstr_w(path) );
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000761
Matthew Davison620323e2003-01-24 00:45:51 +0000762 data = CreateSemaphoreW(NULL,1,1,_ServiceStartDataW);
Alexandre Julliard73755972002-07-31 19:26:03 +0000763 if (!data)
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000764 {
Alexandre Julliardb10dcfe2003-10-10 00:05:49 +0000765 ERR("Couldn't create data semaphore\n");
766 return FALSE;
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000767 }
Matthew Davison620323e2003-01-24 00:45:51 +0000768 wait = CreateSemaphoreW(NULL,0,1,_WaitServiceStartW);
Alexandre Julliardb10dcfe2003-10-10 00:05:49 +0000769 if (!wait)
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000770 {
Alexandre Julliardb10dcfe2003-10-10 00:05:49 +0000771 ERR("Couldn't create wait semaphore\n");
772 return FALSE;
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000773 }
774
Vincent Béron9a624912002-05-31 23:06:46 +0000775 /*
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000776 * FIXME: lpServiceArgsVectors need to be stored and returned to
777 * the service when it calls StartServiceCtrlDispatcher
778 *
779 * Chuck these in a global (yuk) so we can pass them to
780 * another process - address space separation will break this.
781 */
Vincent Béron9a624912002-05-31 23:06:46 +0000782
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000783 r = WaitForSingleObject(data,INFINITE);
784
785 if( r == WAIT_FAILED)
786 return FALSE;
787
Andreas Mohr18a9d742001-01-17 21:52:42 +0000788 FIXME("problematic because of address space separation.\n");
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000789 start_dwNumServiceArgs = dwNumServiceArgs;
Andreas Mohr7fb732e1999-12-12 00:47:51 +0000790 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000791
Matthew Davison620323e2003-01-24 00:45:51 +0000792 ZeroMemory(&startupinfo,sizeof(STARTUPINFOW));
793 startupinfo.cb = sizeof(STARTUPINFOW);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000794
Matthew Davison620323e2003-01-24 00:45:51 +0000795 r = CreateProcessW(path,
Vincent Béron9a624912002-05-31 23:06:46 +0000796 NULL,
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000797 NULL, /* process security attribs */
798 NULL, /* thread security attribs */
799 FALSE, /* inherit handles */
800 0, /* creation flags */
801 NULL, /* environment */
802 NULL, /* current directory */
803 &startupinfo, /* startup info */
804 &procinfo); /* process info */
805
806 if(r == FALSE)
807 {
808 ERR("Couldn't start process\n");
809 /* ReleaseSemaphore(data, 1, NULL);
810 return FALSE; */
811 }
812
813 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
814 r = WaitForSingleObject(wait,30000);
Vincent Béron9a624912002-05-31 23:06:46 +0000815
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000816 ReleaseSemaphore(data, 1, NULL);
817
818 if( r == WAIT_FAILED)
819 return FALSE;
820
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000821 return TRUE;
822}
823
824/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000825 * QueryServiceStatus [ADVAPI32.@]
Matthew Beckere905f3c1999-01-28 13:46:25 +0000826 *
827 * PARAMS
828 * hService []
829 * lpservicestatus []
Vincent Béron9a624912002-05-31 23:06:46 +0000830 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000831 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000832BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000833QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
Matthew Beckere905f3c1999-01-28 13:46:25 +0000834{
Michael McCormack75a84131999-11-21 00:58:14 +0000835 LONG r;
836 DWORD type, val, size;
837
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000838 FIXME("(%p,%p) partial\n",hService,lpservicestatus);
Michael McCormack75a84131999-11-21 00:58:14 +0000839
840 /* read the service type from the registry */
Francois Gouget95918362003-06-18 19:45:22 +0000841 size = sizeof(val);
Michael McCormack75a84131999-11-21 00:58:14 +0000842 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
843 if(type!=REG_DWORD)
844 {
845 ERR("invalid Type\n");
846 return FALSE;
847 }
848 lpservicestatus->dwServiceType = val;
Michael McCormack75a84131999-11-21 00:58:14 +0000849 /* FIXME: how are these determined or read from the registry? */
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000850 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
851 lpservicestatus->dwCurrentState = 1;
Michael McCormack75a84131999-11-21 00:58:14 +0000852 lpservicestatus->dwControlsAccepted = 0;
853 lpservicestatus->dwWin32ExitCode = NO_ERROR;
854 lpservicestatus->dwServiceSpecificExitCode = 0;
855 lpservicestatus->dwCheckPoint = 0;
856 lpservicestatus->dwWaitHint = 0;
857
858 return TRUE;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000859}
Steve Lustbaderf1e1fd02002-11-25 20:50:53 +0000860
861/******************************************************************************
862 * QueryServiceStatusEx [ADVAPI32.@]
863 *
Jon Griffiths50ce0842004-04-23 21:32:34 +0000864 * Get information about a service.
865 *
Steve Lustbaderf1e1fd02002-11-25 20:50:53 +0000866 * PARAMS
Jon Griffiths50ce0842004-04-23 21:32:34 +0000867 * hService [I] Handle to service to get information about
868 * InfoLevel [I] Level of information to get
869 * lpBuffer [O] Destination for requested information
870 * cbBufSize [I] Size of lpBuffer in bytes
871 * pcbBytesNeeded [O] Destination for number of bytes needed, if cbBufSize is too small
872 *
873 * RETURNS
874 * Success: TRUE
875 * FAILURE: FALSE
876 */
Steve Lustbaderf1e1fd02002-11-25 20:50:53 +0000877BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
878 LPBYTE lpBuffer, DWORD cbBufSize,
879 LPDWORD pcbBytesNeeded)
880{
881 FIXME("stub\n");
882 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
883 return FALSE;
884}
Mike McCormack9b513ad2003-12-02 03:48:53 +0000885
886/******************************************************************************
887 * QueryServiceConfigA [ADVAPI32.@]
888 */
889BOOL WINAPI
890QueryServiceConfigA( SC_HANDLE hService,
891 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
892 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
893{
894 FIXME("%p %p %ld %p\n", hService, lpServiceConfig,
895 cbBufSize, pcbBytesNeeded);
896 return FALSE;
897}
898
899/******************************************************************************
900 * QueryServiceConfigW [ADVAPI32.@]
901 */
902BOOL WINAPI
903QueryServiceConfigW( SC_HANDLE hService,
904 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
905 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
906{
Francois Gouget6a6c85c2004-04-19 20:12:14 +0000907 static const WCHAR szDisplayName[] = {
Mike McCormack9b513ad2003-12-02 03:48:53 +0000908 'D','i','s','p','l','a','y','N','a','m','e', 0 };
Francois Gouget6a6c85c2004-04-19 20:12:14 +0000909 static const WCHAR szType[] = {'T','y','p','e',0};
910 static const WCHAR szStart[] = {'S','t','a','r','t',0};
911 static const WCHAR szError[] = {
Mike McCormack9b513ad2003-12-02 03:48:53 +0000912 'E','r','r','o','r','C','o','n','t','r','o','l', 0};
Francois Gouget6a6c85c2004-04-19 20:12:14 +0000913 static const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
914 static const WCHAR szGroup[] = {'G','r','o','u','p',0};
915 static const WCHAR szDependencies[] = {
Mike McCormack9b513ad2003-12-02 03:48:53 +0000916 'D','e','p','e','n','d','e','n','c','i','e','s',0};
917 LONG r;
918 DWORD type, val, sz, total, n;
919 LPBYTE p;
920
921 TRACE("%p %p %ld %p\n", hService, lpServiceConfig,
922 cbBufSize, pcbBytesNeeded);
923
924 /* calculate the size required first */
925 total = sizeof (QUERY_SERVICE_CONFIGW);
926
927 sz = 0;
928 r = RegQueryValueExW( hService, szImagePath, 0, &type, NULL, &sz );
929 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
930 total += sz;
931
932 sz = 0;
933 r = RegQueryValueExW( hService, szGroup, 0, &type, NULL, &sz );
934 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
935 total += sz;
936
937 sz = 0;
938 r = RegQueryValueExW( hService, szDependencies, 0, &type, NULL, &sz );
939 if( ( r == ERROR_SUCCESS ) && ( type == REG_MULTI_SZ ) )
940 total += sz;
941
942 sz = 0;
943 r = RegQueryValueExW( hService, szStart, 0, &type, NULL, &sz );
944 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
945 total += sz;
946
947 sz = 0;
948 r = RegQueryValueExW( hService, szDisplayName, 0, &type, NULL, &sz );
949 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
950 total += sz;
951
952 /* if there's not enough memory, return an error */
953 if( total > *pcbBytesNeeded )
954 {
955 *pcbBytesNeeded = total;
956 SetLastError( ERROR_INSUFFICIENT_BUFFER );
957 return FALSE;
958 }
959
960 *pcbBytesNeeded = total;
961 ZeroMemory( lpServiceConfig, total );
962
963 sz = sizeof val;
964 r = RegQueryValueExW( hService, szType, 0, &type, (LPBYTE)&val, &sz );
965 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
966 lpServiceConfig->dwServiceType = val;
967
968 sz = sizeof val;
969 r = RegQueryValueExW( hService, szStart, 0, &type, (LPBYTE)&val, &sz );
970 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
971 lpServiceConfig->dwStartType = val;
972
973 sz = sizeof val;
974 r = RegQueryValueExW( hService, szError, 0, &type, (LPBYTE)&val, &sz );
975 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
976 lpServiceConfig->dwErrorControl = val;
977
978 /* now do the strings */
979 p = (LPBYTE) &lpServiceConfig[1];
980 n = total - sizeof (QUERY_SERVICE_CONFIGW);
981
982 sz = n;
983 r = RegQueryValueExW( hService, szImagePath, 0, &type, p, &sz );
984 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
985 {
986 lpServiceConfig->lpBinaryPathName = (LPWSTR) p;
987 p += sz;
988 n -= sz;
989 }
990
991 sz = n;
992 r = RegQueryValueExW( hService, szGroup, 0, &type, p, &sz );
993 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
994 {
995 lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p;
996 p += sz;
997 n -= sz;
998 }
999
1000 sz = n;
1001 r = RegQueryValueExW( hService, szDependencies, 0, &type, p, &sz );
1002 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
1003 {
1004 lpServiceConfig->lpDependencies = (LPWSTR) p;
1005 p += sz;
1006 n -= sz;
1007 }
1008
1009 if( n < 0 )
1010 ERR("Buffer overflow!\n");
1011
1012 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1013 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1014
1015 return TRUE;
1016}
1017
1018/******************************************************************************
1019 * ChangeServiceConfigW [ADVAPI32.@]
1020 */
1021BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1022 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1023 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1024 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1025{
1026 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1027 hService, dwServiceType, dwStartType, dwErrorControl,
1028 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1029 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1030 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1031 return TRUE;
1032}
1033
1034/******************************************************************************
1035 * ChangeServiceConfigA [ADVAPI32.@]
1036 */
1037BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
1038 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1039 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
1040 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
1041{
1042 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1043 hService, dwServiceType, dwStartType, dwErrorControl,
1044 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
1045 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
1046 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
1047 return TRUE;
1048}
Aric Stewart3dc71b62003-12-13 03:25:37 +00001049
1050/******************************************************************************
1051 * ChangeServiceConfig2A [ADVAPI32.@]
1052 */
1053BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
1054 LPVOID lpInfo)
1055{
1056 FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo);
1057 return TRUE;
1058}
1059
1060/******************************************************************************
1061 * ChangeServiceConfig2W [ADVAPI32.@]
1062 */
1063BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
1064 LPVOID lpInfo)
1065{
1066 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
1067 {
1068 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1069 LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo;
1070 if (sd->lpDescription)
1071 {
1072 TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
1073 if (sd->lpDescription[0] == 0)
1074 RegDeleteValueW(hService,szDescription);
1075 else
1076 RegSetValueExW(hService, szDescription, 0, REG_SZ,
1077 (LPVOID)sd->lpDescription,
1078 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
1079 }
1080 }
1081 else
1082 FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo);
1083 return TRUE;
1084}