blob: 63470576c95448b2465e097ac0d50c71134b574c [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.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000243 */
Patrik Stridvall4a739731999-07-04 11:01:21 +0000244SC_HANDLE WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +0000245OpenSCManagerA( LPCSTR lpMachineName, LPCSTR lpDatabaseName,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000246 DWORD dwDesiredAccess )
Vincent Béron9a624912002-05-31 23:06:46 +0000247{
Matthew Davison6f2a0712003-01-20 23:23:12 +0000248 UNICODE_STRING lpMachineNameW;
249 UNICODE_STRING lpDatabaseNameW;
250 SC_HANDLE ret;
251
252 RtlCreateUnicodeStringFromAsciiz (&lpMachineNameW,lpMachineName);
253 RtlCreateUnicodeStringFromAsciiz (&lpDatabaseNameW,lpDatabaseName);
254 ret = OpenSCManagerW(lpMachineNameW.Buffer,lpDatabaseNameW.Buffer, dwDesiredAccess);
255 RtlFreeUnicodeString(&lpDatabaseNameW);
256 RtlFreeUnicodeString(&lpMachineNameW);
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000257 return ret;
258}
259
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000260/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000261 * OpenSCManagerW [ADVAPI32.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000262 * Establishes a connection to the service control manager and opens database
263 *
264 * NOTES
Matthew Beckere905f3c1999-01-28 13:46:25 +0000265 * This should return a SC_HANDLE
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000266 *
267 * PARAMS
Matthew Beckere905f3c1999-01-28 13:46:25 +0000268 * lpMachineName [I] Pointer to machine name string
269 * lpDatabaseName [I] Pointer to database name string
270 * dwDesiredAccess [I] Type of access
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000271 *
272 * RETURNS
Matthew Beckere905f3c1999-01-28 13:46:25 +0000273 * Success: Handle to service control manager database
274 * Failure: NULL
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000275 */
Patrik Stridvall4a739731999-07-04 11:01:21 +0000276SC_HANDLE WINAPI
Alexandre Julliarda3960291999-02-26 11:11:13 +0000277OpenSCManagerW( LPCWSTR lpMachineName, LPCWSTR lpDatabaseName,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000278 DWORD dwDesiredAccess )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000279{
Mike McCormack9b513ad2003-12-02 03:48:53 +0000280 HKEY hReg, hKey = NULL;
Michael McCormack75a84131999-11-21 00:58:14 +0000281 LONG r;
282
Vincent Béron9a624912002-05-31 23:06:46 +0000283 TRACE("(%s,%s,0x%08lx)\n", debugstr_w(lpMachineName),
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000284 debugstr_w(lpDatabaseName), dwDesiredAccess);
Michael McCormack75a84131999-11-21 00:58:14 +0000285
286 /*
287 * FIXME: what is lpDatabaseName?
288 * It should be set to "SERVICES_ACTIVE_DATABASE" according to
289 * docs, but what if it isn't?
290 */
291
Mike McCormack9b513ad2003-12-02 03:48:53 +0000292 r = RegConnectRegistryW(lpMachineName,HKEY_LOCAL_MACHINE,&hReg);
293 if (r==ERROR_SUCCESS)
294 {
Aric Stewart3dc71b62003-12-13 03:25:37 +0000295 r = RegOpenKeyExW(hReg, szServiceManagerKey,0, dwDesiredAccess, &hKey );
Mike McCormack9b513ad2003-12-02 03:48:53 +0000296 RegCloseKey( hReg );
297 }
Michael McCormack75a84131999-11-21 00:58:14 +0000298
Mike McCormack9b513ad2003-12-02 03:48:53 +0000299 TRACE("returning %p\n", hKey);
Michael McCormack75a84131999-11-21 00:58:14 +0000300
301 return hKey;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000302}
303
304
Matthew Beckere905f3c1999-01-28 13:46:25 +0000305/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000306 * AllocateLocallyUniqueId [ADVAPI32.@]
Matthew Beckere905f3c1999-01-28 13:46:25 +0000307 *
308 * PARAMS
309 * lpluid []
310 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000311BOOL WINAPI
Juergen Schmied1ed51af1999-02-12 17:47:07 +0000312AllocateLocallyUniqueId( PLUID lpluid )
Matthew Beckere905f3c1999-01-28 13:46:25 +0000313{
Francois Gougetea31cf02001-11-20 18:52:20 +0000314 lpluid->LowPart = time(NULL);
315 lpluid->HighPart = 0;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000316 return TRUE;
317}
318
319
320/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000321 * ControlService [ADVAPI32.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000322 * Sends a control code to a Win32-based service.
323 *
Matthew Beckere905f3c1999-01-28 13:46:25 +0000324 * PARAMS
325 * hService []
326 * dwControl []
327 * lpServiceStatus []
328 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000329 * RETURNS STD
330 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000331BOOL WINAPI
Vincent Béron9a624912002-05-31 23:06:46 +0000332ControlService( SC_HANDLE hService, DWORD dwControl,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000333 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.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000342 * Close handle to service or service control manager
343 *
344 * PARAMS
Matthew Beckere905f3c1999-01-28 13:46:25 +0000345 * hSCObject [I] Handle to service or service control manager database
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000346 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000347 * RETURNS STD
348 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000349BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000350CloseServiceHandle( SC_HANDLE hSCObject )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000351{
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000352 TRACE("(%p)\n", hSCObject);
Michael McCormack75a84131999-11-21 00:58:14 +0000353
354 RegCloseKey(hSCObject);
Vincent Béron9a624912002-05-31 23:06:46 +0000355
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000356 return TRUE;
357}
358
359
360/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000361 * OpenServiceA [ADVAPI32.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000362 */
Patrik Stridvall4a739731999-07-04 11:01:21 +0000363SC_HANDLE WINAPI
Vincent Béron9a624912002-05-31 23:06:46 +0000364OpenServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000365 DWORD dwDesiredAccess )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000366{
Matthew Davison6f2a0712003-01-20 23:23:12 +0000367 UNICODE_STRING lpServiceNameW;
François Gouget97ad5a72001-01-02 20:20:34 +0000368 SC_HANDLE ret;
Matthew Davison6f2a0712003-01-20 23:23:12 +0000369 RtlCreateUnicodeStringFromAsciiz (&lpServiceNameW,lpServiceName);
Michael McCormack75a84131999-11-21 00:58:14 +0000370 if(lpServiceName)
371 TRACE("Request for service %s\n",lpServiceName);
372 else
373 return FALSE;
Matthew Davison6f2a0712003-01-20 23:23:12 +0000374 ret = OpenServiceW( hSCManager, lpServiceNameW.Buffer, dwDesiredAccess);
375 RtlFreeUnicodeString(&lpServiceNameW);
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000376 return ret;
377}
378
379
380/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000381 * OpenServiceW [ADVAPI32.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000382 * Opens a handle to an existing service
383 *
Matthew Beckere905f3c1999-01-28 13:46:25 +0000384 * PARAMS
385 * hSCManager []
386 * lpServiceName []
387 * dwDesiredAccess []
388 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000389 * RETURNS
390 * Success: Handle to the service
391 * Failure: NULL
392 */
Patrik Stridvall4a739731999-07-04 11:01:21 +0000393SC_HANDLE WINAPI
394OpenServiceW(SC_HANDLE hSCManager, LPCWSTR lpServiceName,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000395 DWORD dwDesiredAccess)
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000396{
Michael McCormack75a84131999-11-21 00:58:14 +0000397 HKEY hKey;
398 long r;
399
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000400 TRACE("(%p,%p,%ld)\n",hSCManager, lpServiceName,
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000401 dwDesiredAccess);
Michael McCormack75a84131999-11-21 00:58:14 +0000402
Alexandre Julliardbea945e2004-04-12 22:18:39 +0000403 r = RegOpenKeyExW(hSCManager, lpServiceName, 0, KEY_ALL_ACCESS, &hKey );
Michael McCormack75a84131999-11-21 00:58:14 +0000404 if (r!=ERROR_SUCCESS)
405 return 0;
406
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000407 TRACE("returning %p\n",hKey);
Michael McCormack75a84131999-11-21 00:58:14 +0000408
409 return hKey;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000410}
411
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000412/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000413 * CreateServiceW [ADVAPI32.@]
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000414 */
415SC_HANDLE WINAPI
Peter Hunnisett565b0082000-09-19 02:43:00 +0000416CreateServiceW( SC_HANDLE hSCManager, LPCWSTR lpServiceName,
Vincent Béron9a624912002-05-31 23:06:46 +0000417 LPCWSTR lpDisplayName, DWORD dwDesiredAccess,
418 DWORD dwServiceType, DWORD dwStartType,
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000419 DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
Vincent Béron9a624912002-05-31 23:06:46 +0000420 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
421 LPCWSTR lpDependencies, LPCWSTR lpServiceStartName,
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000422 LPCWSTR lpPassword )
423{
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000424 HKEY hKey;
425 LONG r;
426 DWORD dp;
Mike McCormack9b513ad2003-12-02 03:48:53 +0000427 const WCHAR szDisplayName[] = { 'D','i','s','p','l','a','y','N','a','m','e', 0 };
428 const WCHAR szType[] = {'T','y','p','e',0};
429 const WCHAR szStart[] = {'S','t','a','r','t',0};
430 const WCHAR szError[] = {'E','r','r','o','r','C','o','n','t','r','o','l', 0};
431 const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
432 const WCHAR szGroup[] = {'G','r','o','u','p',0};
433 const WCHAR szDependencies[] = { 'D','e','p','e','n','d','e','n','c','i','e','s',0};
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000434
Mike McCormack9b513ad2003-12-02 03:48:53 +0000435 FIXME("%p %s %s\n", hSCManager,
436 debugstr_w(lpServiceName), debugstr_w(lpDisplayName));
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000437
Mike McCormack9b513ad2003-12-02 03:48:53 +0000438 r = RegCreateKeyExW(hSCManager, lpServiceName, 0, NULL,
Aric Stewart3dc71b62003-12-13 03:25:37 +0000439 REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hKey, &dp);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000440 if (r!=ERROR_SUCCESS)
441 return 0;
Aric Stewart3dc71b62003-12-13 03:25:37 +0000442
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000443 if (dp != REG_CREATED_NEW_KEY)
444 return 0;
445
446 if(lpDisplayName)
447 {
Mike McCormack9b513ad2003-12-02 03:48:53 +0000448 r = RegSetValueExW(hKey, szDisplayName, 0, REG_SZ, (LPBYTE)lpDisplayName,
449 (strlenW(lpDisplayName)+1)*sizeof(WCHAR) );
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000450 if (r!=ERROR_SUCCESS)
451 return 0;
452 }
453
Mike McCormack9b513ad2003-12-02 03:48:53 +0000454 r = RegSetValueExW(hKey, szType, 0, REG_DWORD, (LPVOID)&dwServiceType, sizeof (DWORD) );
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000455 if (r!=ERROR_SUCCESS)
456 return 0;
457
Mike McCormack9b513ad2003-12-02 03:48:53 +0000458 r = RegSetValueExW(hKey, szStart, 0, REG_DWORD, (LPVOID)&dwStartType, 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, szError, 0, REG_DWORD,
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000463 (LPVOID)&dwErrorControl, sizeof (DWORD) );
464 if (r!=ERROR_SUCCESS)
465 return 0;
466
467 if(lpBinaryPathName)
468 {
Mike McCormack9b513ad2003-12-02 03:48:53 +0000469 r = RegSetValueExW(hKey, szImagePath, 0, REG_SZ, (LPBYTE)lpBinaryPathName,
470 (strlenW(lpBinaryPathName)+1)*sizeof(WCHAR) );
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000471 if (r!=ERROR_SUCCESS)
472 return 0;
473 }
474
475 if(lpLoadOrderGroup)
476 {
Mike McCormack9b513ad2003-12-02 03:48:53 +0000477 r = RegSetValueExW(hKey, szGroup, 0, REG_SZ, (LPBYTE)lpLoadOrderGroup,
478 (strlenW(lpLoadOrderGroup)+1)*sizeof(WCHAR) );
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000479 if (r!=ERROR_SUCCESS)
480 return 0;
481 }
482
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000483 if(lpDependencies)
484 {
Vincent Béron9a624912002-05-31 23:06:46 +0000485 DWORD len = 0;
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000486
487 /* determine the length of a double null terminated multi string */
488 do {
Mike McCormack9b513ad2003-12-02 03:48:53 +0000489 len += (strlenW(&lpDependencies[len])+1);
Vincent Béron9a624912002-05-31 23:06:46 +0000490 } while (lpDependencies[len++]);
491
Mike McCormack9b513ad2003-12-02 03:48:53 +0000492 r = RegSetValueExW(hKey, szDependencies, 0, REG_MULTI_SZ,
493 (LPBYTE)lpDependencies, len );
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000494 if (r!=ERROR_SUCCESS)
495 return 0;
496 }
497
498 if(lpPassword)
499 {
500 FIXME("Don't know how to add a Password for a service.\n");
501 }
502
503 if(lpServiceStartName)
504 {
505 FIXME("Don't know how to add a ServiceStartName for a service.\n");
506 }
507
508 return hKey;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000509}
510
511
Mike McCormack9b513ad2003-12-02 03:48:53 +0000512static inline LPWSTR SERV_dup( LPCSTR str )
513{
514 UINT len;
515 LPWSTR wstr;
516
517 if( !str )
518 return NULL;
519 len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
520 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
521 MultiByteToWideChar( CP_ACP, 0, str, -1, wstr, len );
522 return wstr;
523}
524
525static inline LPWSTR SERV_dupmulti( LPCSTR str )
526{
527 UINT len = 0, n = 0;
528 LPWSTR wstr;
529
Huw Davies28c2ea02003-12-11 04:26:20 +0000530 if( !str )
531 return NULL;
Mike McCormack9b513ad2003-12-02 03:48:53 +0000532 do {
533 len += MultiByteToWideChar( CP_ACP, 0, &str[n], -1, NULL, 0 );
534 n += (strlen( &str[n] ) + 1);
535 } while (str[n]);
536 len++;
537 n++;
538
539 wstr = HeapAlloc( GetProcessHeap(), 0, len*sizeof (WCHAR) );
540 MultiByteToWideChar( CP_ACP, 0, str, n, wstr, len );
541 return wstr;
542}
543
544static inline VOID SERV_free( LPWSTR wstr )
545{
546 HeapFree( GetProcessHeap(), 0, wstr );
547}
548
549/******************************************************************************
550 * CreateServiceA [ADVAPI32.@]
551 */
552SC_HANDLE WINAPI
553CreateServiceA( SC_HANDLE hSCManager, LPCSTR lpServiceName,
554 LPCSTR lpDisplayName, DWORD dwDesiredAccess,
555 DWORD dwServiceType, DWORD dwStartType,
556 DWORD dwErrorControl, LPCSTR lpBinaryPathName,
557 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId,
558 LPCSTR lpDependencies, LPCSTR lpServiceStartName,
559 LPCSTR lpPassword )
560{
561 LPWSTR lpServiceNameW, lpDisplayNameW, lpBinaryPathNameW,
562 lpLoadOrderGroupW, lpDependenciesW, lpServiceStartNameW, lpPasswordW;
563 SC_HANDLE r;
564
565 TRACE("%p %s %s\n", hSCManager,
566 debugstr_a(lpServiceName), debugstr_a(lpDisplayName));
567
568 lpServiceNameW = SERV_dup( lpServiceName );
569 lpDisplayNameW = SERV_dup( lpDisplayName );
570 lpBinaryPathNameW = SERV_dup( lpBinaryPathName );
571 lpLoadOrderGroupW = SERV_dup( lpLoadOrderGroup );
572 lpDependenciesW = SERV_dupmulti( lpDependencies );
573 lpServiceStartNameW = SERV_dup( lpServiceStartName );
574 lpPasswordW = SERV_dup( lpPassword );
575
576 r = CreateServiceW( hSCManager, lpServiceNameW, lpDisplayNameW,
577 dwDesiredAccess, dwServiceType, dwStartType, dwErrorControl,
578 lpBinaryPathNameW, lpLoadOrderGroupW, lpdwTagId,
579 lpDependenciesW, lpServiceStartNameW, lpPasswordW );
580
581 SERV_free( lpServiceNameW );
582 SERV_free( lpDisplayNameW );
583 SERV_free( lpBinaryPathNameW );
584 SERV_free( lpLoadOrderGroupW );
585 SERV_free( lpDependenciesW );
586 SERV_free( lpServiceStartNameW );
587 SERV_free( lpPasswordW );
588
589 return r;
590}
591
592
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000593/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000594 * DeleteService [ADVAPI32.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000595 *
596 * PARAMS
597 * hService [I] Handle to service
598 *
599 * RETURNS STD
600 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000601 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000602BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000603DeleteService( SC_HANDLE hService )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000604{
Aric Stewart3dc71b62003-12-13 03:25:37 +0000605 WCHAR valname[MAX_PATH+1];
606 INT index = 0;
607 LONG rc;
608 DWORD value = 0x1;
609 DWORD size;
610 HKEY hKey;
611
612 static const WCHAR szDeleted[] = {'D','e','l','e','t','e','d',0};
613
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000614 FIXME("(%p): stub\n",hService);
Aric Stewart3dc71b62003-12-13 03:25:37 +0000615
616 size = MAX_PATH+1;
617 /* Clean out the values */
618 rc = RegEnumValueW(hService, index, valname,&size,0,0,0,0);
619 while (rc == ERROR_SUCCESS)
620 {
621 RegDeleteValueW(hService,valname);
622 index++;
623 size = MAX_PATH+1;
624 rc = RegEnumValueW(hService, index, valname, &size,0,0,0,0);
625 }
626
627 /* tag for deletion */
628 RegSetValueExW(hService, szDeleted, 0, REG_DWORD, (LPVOID)&value,
629 sizeof (DWORD) );
630
631 RegCloseKey(hService);
632
633 /* find and delete the key */
634 rc = RegOpenKeyExW(HKEY_LOCAL_MACHINE, szServiceManagerKey,0,
635 KEY_ALL_ACCESS, &hKey );
636 index = 0;
637 size = MAX_PATH+1;
638 rc = RegEnumKeyExW(hKey,0, valname, &size, 0, 0, 0, 0);
639 while (rc == ERROR_SUCCESS)
640 {
641 HKEY checking;
642 rc = RegOpenKeyExW(hKey,valname,0,KEY_ALL_ACCESS,&checking);
643 if (rc == ERROR_SUCCESS)
644 {
645 DWORD deleted = 0;
646 DWORD size = sizeof(DWORD);
647 rc = RegQueryValueExW(checking, szDeleted , NULL, NULL,
648 (LPVOID)&deleted, &size);
649 if (deleted)
650 {
651 RegDeleteValueW(checking,szDeleted);
652 RegDeleteKeyW(hKey,valname);
653 }
654 else
655 index ++;
656 RegCloseKey(checking);
657 }
658 size = MAX_PATH+1;
659 rc = RegEnumKeyExW(hKey, index, valname, &size, 0, 0, 0, 0);
660 }
661 RegCloseKey(hKey);
662
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000663 return TRUE;
664}
665
666
667/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000668 * StartServiceA [ADVAPI32.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000669 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000670 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000671BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000672StartServiceA( SC_HANDLE hService, DWORD dwNumServiceArgs,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000673 LPCSTR *lpServiceArgVectors )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000674{
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000675 LPWSTR *lpwstr=NULL;
Matthew Davison60009b92003-01-23 23:07:38 +0000676 UNICODE_STRING usBuffer;
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000677 int i;
678
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000679 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,lpServiceArgVectors);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000680
681 if(dwNumServiceArgs)
Vincent Béron9a624912002-05-31 23:06:46 +0000682 lpwstr = (LPWSTR*) HeapAlloc( GetProcessHeap(), 0,
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000683 dwNumServiceArgs*sizeof(LPWSTR) );
684 else
685 lpwstr = NULL;
686
687 for(i=0; i<dwNumServiceArgs; i++)
Matthew Davison60009b92003-01-23 23:07:38 +0000688 {
689 RtlCreateUnicodeStringFromAsciiz (&usBuffer,lpServiceArgVectors[i]);
690 lpwstr[i]=usBuffer.Buffer;
691 }
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000692
Andreas Mohr7fb732e1999-12-12 00:47:51 +0000693 StartServiceW(hService, dwNumServiceArgs, (LPCWSTR *)lpwstr);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000694
695 if(dwNumServiceArgs)
696 {
697 for(i=0; i<dwNumServiceArgs; i++)
698 HeapFree(GetProcessHeap(), 0, lpwstr[i]);
699 HeapFree(GetProcessHeap(), 0, lpwstr);
700 }
701
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000702 return TRUE;
703}
704
705
706/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000707 * StartServiceW [ADVAPI32.@]
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000708 * Starts a service
709 *
710 * PARAMS
Matthew Beckere905f3c1999-01-28 13:46:25 +0000711 * hService [I] Handle of service
712 * dwNumServiceArgs [I] Number of arguments
713 * lpServiceArgVectors [I] Address of array of argument string pointers
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000714 *
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000715 * NOTES
716 *
717 * NT implements this function using an obscure RPC call...
718 *
719 * Might need to do a "setenv SystemRoot \\WINNT" in your .cshrc
720 * to get things like %SystemRoot%\\System32\\service.exe to load.
721 *
722 * Will only work for shared address space. How should the service
723 * args be transferred when address spaces are separated?
724 *
725 * Can only start one service at a time.
726 *
Francois Gouget3bb9a362001-10-22 19:04:32 +0000727 * Has no concept of privilege.
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000728 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000729 * RETURNS STD
730 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000731 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000732BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000733StartServiceW( SC_HANDLE hService, DWORD dwNumServiceArgs,
Matthew Beckere905f3c1999-01-28 13:46:25 +0000734 LPCWSTR *lpServiceArgVectors )
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000735{
Matthew Davison620323e2003-01-24 00:45:51 +0000736 static const WCHAR _WaitServiceStartW[] = {'A','D','V','A','P','I','_','W',
737 'a','i','t','S','e','r','v','i',
738 'c','e','S','t','a','r','t',0};
739 static const WCHAR _ImagePathW[] = {'I','m','a','g','e','P','a','t','h',0};
740
741 WCHAR path[MAX_PATH],str[MAX_PATH];
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000742 DWORD type,size;
743 long r;
744 HANDLE data,wait;
745 PROCESS_INFORMATION procinfo;
Matthew Davison620323e2003-01-24 00:45:51 +0000746 STARTUPINFOW startupinfo;
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000747 TRACE("(%p,%ld,%p)\n",hService,dwNumServiceArgs,
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000748 lpServiceArgVectors);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000749
Francois Gouget95918362003-06-18 19:45:22 +0000750 size = sizeof(str);
Matthew Davison620323e2003-01-24 00:45:51 +0000751 r = RegQueryValueExW(hService, _ImagePathW, NULL, &type, (LPVOID)str, &size);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000752 if (r!=ERROR_SUCCESS)
753 return FALSE;
Francois Gouget95918362003-06-18 19:45:22 +0000754 ExpandEnvironmentStringsW(str,path,sizeof(path));
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000755
Matthew Davison620323e2003-01-24 00:45:51 +0000756 TRACE("Starting service %s\n", debugstr_w(path) );
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000757
Matthew Davison620323e2003-01-24 00:45:51 +0000758 data = CreateSemaphoreW(NULL,1,1,_ServiceStartDataW);
Alexandre Julliard73755972002-07-31 19:26:03 +0000759 if (!data)
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000760 {
Alexandre Julliardb10dcfe2003-10-10 00:05:49 +0000761 ERR("Couldn't create data semaphore\n");
762 return FALSE;
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000763 }
Matthew Davison620323e2003-01-24 00:45:51 +0000764 wait = CreateSemaphoreW(NULL,0,1,_WaitServiceStartW);
Alexandre Julliardb10dcfe2003-10-10 00:05:49 +0000765 if (!wait)
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000766 {
Alexandre Julliardb10dcfe2003-10-10 00:05:49 +0000767 ERR("Couldn't create wait semaphore\n");
768 return FALSE;
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000769 }
770
Vincent Béron9a624912002-05-31 23:06:46 +0000771 /*
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000772 * FIXME: lpServiceArgsVectors need to be stored and returned to
773 * the service when it calls StartServiceCtrlDispatcher
774 *
775 * Chuck these in a global (yuk) so we can pass them to
776 * another process - address space separation will break this.
777 */
Vincent Béron9a624912002-05-31 23:06:46 +0000778
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000779 r = WaitForSingleObject(data,INFINITE);
780
781 if( r == WAIT_FAILED)
782 return FALSE;
783
Andreas Mohr18a9d742001-01-17 21:52:42 +0000784 FIXME("problematic because of address space separation.\n");
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000785 start_dwNumServiceArgs = dwNumServiceArgs;
Andreas Mohr7fb732e1999-12-12 00:47:51 +0000786 start_lpServiceArgVectors = (LPWSTR *)lpServiceArgVectors;
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000787
Matthew Davison620323e2003-01-24 00:45:51 +0000788 ZeroMemory(&startupinfo,sizeof(STARTUPINFOW));
789 startupinfo.cb = sizeof(STARTUPINFOW);
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000790
Matthew Davison620323e2003-01-24 00:45:51 +0000791 r = CreateProcessW(path,
Vincent Béron9a624912002-05-31 23:06:46 +0000792 NULL,
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000793 NULL, /* process security attribs */
794 NULL, /* thread security attribs */
795 FALSE, /* inherit handles */
796 0, /* creation flags */
797 NULL, /* environment */
798 NULL, /* current directory */
799 &startupinfo, /* startup info */
800 &procinfo); /* process info */
801
802 if(r == FALSE)
803 {
804 ERR("Couldn't start process\n");
805 /* ReleaseSemaphore(data, 1, NULL);
806 return FALSE; */
807 }
808
809 /* docs for StartServiceCtrlDispatcher say this should be 30 sec */
810 r = WaitForSingleObject(wait,30000);
Vincent Béron9a624912002-05-31 23:06:46 +0000811
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000812 ReleaseSemaphore(data, 1, NULL);
813
814 if( r == WAIT_FAILED)
815 return FALSE;
816
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000817 return TRUE;
818}
819
820/******************************************************************************
Patrik Stridvalld0a41772001-02-14 23:11:17 +0000821 * QueryServiceStatus [ADVAPI32.@]
Matthew Beckere905f3c1999-01-28 13:46:25 +0000822 *
823 * PARAMS
824 * hService []
825 * lpservicestatus []
Vincent Béron9a624912002-05-31 23:06:46 +0000826 *
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000827 */
Alexandre Julliarda3960291999-02-26 11:11:13 +0000828BOOL WINAPI
Patrik Stridvall4a739731999-07-04 11:01:21 +0000829QueryServiceStatus( SC_HANDLE hService, LPSERVICE_STATUS lpservicestatus )
Matthew Beckere905f3c1999-01-28 13:46:25 +0000830{
Michael McCormack75a84131999-11-21 00:58:14 +0000831 LONG r;
832 DWORD type, val, size;
833
Michael Stefaniuccbacde52002-10-25 19:17:33 +0000834 FIXME("(%p,%p) partial\n",hService,lpservicestatus);
Michael McCormack75a84131999-11-21 00:58:14 +0000835
836 /* read the service type from the registry */
Francois Gouget95918362003-06-18 19:45:22 +0000837 size = sizeof(val);
Michael McCormack75a84131999-11-21 00:58:14 +0000838 r = RegQueryValueExA(hService, "Type", NULL, &type, (LPBYTE)&val, &size);
839 if(type!=REG_DWORD)
840 {
841 ERR("invalid Type\n");
842 return FALSE;
843 }
844 lpservicestatus->dwServiceType = val;
Michael McCormack75a84131999-11-21 00:58:14 +0000845 /* FIXME: how are these determined or read from the registry? */
Michael McCormack0c0f7d31999-12-04 04:03:45 +0000846 /* SERVICE: unavailable=0, stopped=1, starting=2, running=3? */;
847 lpservicestatus->dwCurrentState = 1;
Michael McCormack75a84131999-11-21 00:58:14 +0000848 lpservicestatus->dwControlsAccepted = 0;
849 lpservicestatus->dwWin32ExitCode = NO_ERROR;
850 lpservicestatus->dwServiceSpecificExitCode = 0;
851 lpservicestatus->dwCheckPoint = 0;
852 lpservicestatus->dwWaitHint = 0;
853
854 return TRUE;
Juergen Schmiedf7b0de31999-01-03 12:48:29 +0000855}
Steve Lustbaderf1e1fd02002-11-25 20:50:53 +0000856
857/******************************************************************************
858 * QueryServiceStatusEx [ADVAPI32.@]
859 *
860 * PARAMS
861 * hService [handle to service]
862 * InfoLevel [information level]
863 * lpBuffer [buffer]
864 * cbBufSize [size of buffer]
865 * pcbBytesNeeded [bytes needed]
866*/
867BOOL WINAPI QueryServiceStatusEx(SC_HANDLE hService, SC_STATUS_TYPE InfoLevel,
868 LPBYTE lpBuffer, DWORD cbBufSize,
869 LPDWORD pcbBytesNeeded)
870{
871 FIXME("stub\n");
872 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
873 return FALSE;
874}
Mike McCormack9b513ad2003-12-02 03:48:53 +0000875
876/******************************************************************************
877 * QueryServiceConfigA [ADVAPI32.@]
878 */
879BOOL WINAPI
880QueryServiceConfigA( SC_HANDLE hService,
881 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
882 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
883{
884 FIXME("%p %p %ld %p\n", hService, lpServiceConfig,
885 cbBufSize, pcbBytesNeeded);
886 return FALSE;
887}
888
889/******************************************************************************
890 * QueryServiceConfigW [ADVAPI32.@]
891 */
892BOOL WINAPI
893QueryServiceConfigW( SC_HANDLE hService,
894 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
895 DWORD cbBufSize, LPDWORD pcbBytesNeeded)
896{
897 const WCHAR szDisplayName[] = {
898 'D','i','s','p','l','a','y','N','a','m','e', 0 };
899 const WCHAR szType[] = {'T','y','p','e',0};
900 const WCHAR szStart[] = {'S','t','a','r','t',0};
901 const WCHAR szError[] = {
902 'E','r','r','o','r','C','o','n','t','r','o','l', 0};
903 const WCHAR szImagePath[] = {'I','m','a','g','e','P','a','t','h',0};
904 const WCHAR szGroup[] = {'G','r','o','u','p',0};
905 const WCHAR szDependencies[] = {
906 'D','e','p','e','n','d','e','n','c','i','e','s',0};
907 LONG r;
908 DWORD type, val, sz, total, n;
909 LPBYTE p;
910
911 TRACE("%p %p %ld %p\n", hService, lpServiceConfig,
912 cbBufSize, pcbBytesNeeded);
913
914 /* calculate the size required first */
915 total = sizeof (QUERY_SERVICE_CONFIGW);
916
917 sz = 0;
918 r = RegQueryValueExW( hService, szImagePath, 0, &type, NULL, &sz );
919 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
920 total += sz;
921
922 sz = 0;
923 r = RegQueryValueExW( hService, szGroup, 0, &type, NULL, &sz );
924 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
925 total += sz;
926
927 sz = 0;
928 r = RegQueryValueExW( hService, szDependencies, 0, &type, NULL, &sz );
929 if( ( r == ERROR_SUCCESS ) && ( type == REG_MULTI_SZ ) )
930 total += sz;
931
932 sz = 0;
933 r = RegQueryValueExW( hService, szStart, 0, &type, NULL, &sz );
934 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
935 total += sz;
936
937 sz = 0;
938 r = RegQueryValueExW( hService, szDisplayName, 0, &type, NULL, &sz );
939 if( ( r == ERROR_SUCCESS ) && ( type == REG_SZ ) )
940 total += sz;
941
942 /* if there's not enough memory, return an error */
943 if( total > *pcbBytesNeeded )
944 {
945 *pcbBytesNeeded = total;
946 SetLastError( ERROR_INSUFFICIENT_BUFFER );
947 return FALSE;
948 }
949
950 *pcbBytesNeeded = total;
951 ZeroMemory( lpServiceConfig, total );
952
953 sz = sizeof val;
954 r = RegQueryValueExW( hService, szType, 0, &type, (LPBYTE)&val, &sz );
955 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
956 lpServiceConfig->dwServiceType = val;
957
958 sz = sizeof val;
959 r = RegQueryValueExW( hService, szStart, 0, &type, (LPBYTE)&val, &sz );
960 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
961 lpServiceConfig->dwStartType = val;
962
963 sz = sizeof val;
964 r = RegQueryValueExW( hService, szError, 0, &type, (LPBYTE)&val, &sz );
965 if( ( r == ERROR_SUCCESS ) || ( type == REG_DWORD ) )
966 lpServiceConfig->dwErrorControl = val;
967
968 /* now do the strings */
969 p = (LPBYTE) &lpServiceConfig[1];
970 n = total - sizeof (QUERY_SERVICE_CONFIGW);
971
972 sz = n;
973 r = RegQueryValueExW( hService, szImagePath, 0, &type, p, &sz );
974 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
975 {
976 lpServiceConfig->lpBinaryPathName = (LPWSTR) p;
977 p += sz;
978 n -= sz;
979 }
980
981 sz = n;
982 r = RegQueryValueExW( hService, szGroup, 0, &type, p, &sz );
983 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
984 {
985 lpServiceConfig->lpLoadOrderGroup = (LPWSTR) p;
986 p += sz;
987 n -= sz;
988 }
989
990 sz = n;
991 r = RegQueryValueExW( hService, szDependencies, 0, &type, p, &sz );
992 if( ( r == ERROR_SUCCESS ) || ( type == REG_SZ ) )
993 {
994 lpServiceConfig->lpDependencies = (LPWSTR) p;
995 p += sz;
996 n -= sz;
997 }
998
999 if( n < 0 )
1000 ERR("Buffer overflow!\n");
1001
1002 TRACE("Image path = %s\n", debugstr_w(lpServiceConfig->lpBinaryPathName) );
1003 TRACE("Group = %s\n", debugstr_w(lpServiceConfig->lpLoadOrderGroup) );
1004
1005 return TRUE;
1006}
1007
1008/******************************************************************************
1009 * ChangeServiceConfigW [ADVAPI32.@]
1010 */
1011BOOL WINAPI ChangeServiceConfigW( SC_HANDLE hService, DWORD dwServiceType,
1012 DWORD dwStartType, DWORD dwErrorControl, LPCWSTR lpBinaryPathName,
1013 LPCWSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCWSTR lpDependencies,
1014 LPCWSTR lpServiceStartName, LPCWSTR lpPassword, LPCWSTR lpDisplayName)
1015{
1016 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1017 hService, dwServiceType, dwStartType, dwErrorControl,
1018 debugstr_w(lpBinaryPathName), debugstr_w(lpLoadOrderGroup),
1019 lpdwTagId, lpDependencies, debugstr_w(lpServiceStartName),
1020 debugstr_w(lpPassword), debugstr_w(lpDisplayName) );
1021 return TRUE;
1022}
1023
1024/******************************************************************************
1025 * ChangeServiceConfigA [ADVAPI32.@]
1026 */
1027BOOL WINAPI ChangeServiceConfigA( SC_HANDLE hService, DWORD dwServiceType,
1028 DWORD dwStartType, DWORD dwErrorControl, LPCSTR lpBinaryPathName,
1029 LPCSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCSTR lpDependencies,
1030 LPCSTR lpServiceStartName, LPCSTR lpPassword, LPCSTR lpDisplayName)
1031{
1032 FIXME("%p %ld %ld %ld %s %s %p %p %s %s %s\n",
1033 hService, dwServiceType, dwStartType, dwErrorControl,
1034 debugstr_a(lpBinaryPathName), debugstr_a(lpLoadOrderGroup),
1035 lpdwTagId, lpDependencies, debugstr_a(lpServiceStartName),
1036 debugstr_a(lpPassword), debugstr_a(lpDisplayName) );
1037 return TRUE;
1038}
Aric Stewart3dc71b62003-12-13 03:25:37 +00001039
1040/******************************************************************************
1041 * ChangeServiceConfig2A [ADVAPI32.@]
1042 */
1043BOOL WINAPI ChangeServiceConfig2A( SC_HANDLE hService, DWORD dwInfoLevel,
1044 LPVOID lpInfo)
1045{
1046 FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo);
1047 return TRUE;
1048}
1049
1050/******************************************************************************
1051 * ChangeServiceConfig2W [ADVAPI32.@]
1052 */
1053BOOL WINAPI ChangeServiceConfig2W( SC_HANDLE hService, DWORD dwInfoLevel,
1054 LPVOID lpInfo)
1055{
1056 if (dwInfoLevel == SERVICE_CONFIG_DESCRIPTION)
1057 {
1058 static const WCHAR szDescription[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1059 LPSERVICE_DESCRIPTIONW sd = (LPSERVICE_DESCRIPTIONW)lpInfo;
1060 if (sd->lpDescription)
1061 {
1062 TRACE("Setting Description to %s\n",debugstr_w(sd->lpDescription));
1063 if (sd->lpDescription[0] == 0)
1064 RegDeleteValueW(hService,szDescription);
1065 else
1066 RegSetValueExW(hService, szDescription, 0, REG_SZ,
1067 (LPVOID)sd->lpDescription,
1068 sizeof(WCHAR)*(strlenW(sd->lpDescription)+1));
1069 }
1070 }
1071 else
1072 FIXME("STUB: %p %ld %p\n",hService, dwInfoLevel, lpInfo);
1073 return TRUE;
1074}