3 * COPYRIGHT: See COPYING in the top level directory
4 * PROJECT: ReactOS system libraries
5 * FILE: lib/advapi32/service/sctrl.c
6 * PURPOSE: Service control manager functions
7 * PROGRAMMER: Emanuele Aliberti
13 /* INCLUDES ******************************************************************/
15 #define NTOS_MODE_USER
25 /* TYPES *********************************************************************/
30 UNICODE_STRING ServiceName;
31 LPSERVICE_MAIN_FUNCTIONW MainFunction;
32 LPHANDLER_FUNCTION HandlerFunction;
33 SERVICE_STATUS ServiceStatus;
34 } ACTIVE_SERVICE, *PACTIVE_SERVICE;
36 /* GLOBALS *******************************************************************/
38 static ULONG ActiveServiceCount;
39 static PACTIVE_SERVICE ActiveServices;
40 /* static PHANDLE ActiveServicesThreadHandles; */ /* uncomment when in use */
42 /* FUNCTIONS *****************************************************************/
45 static PACTIVE_SERVICE
46 ScLookupServiceByServiceName(LPWSTR lpServiceName)
50 for (i = 0; i < ActiveServiceCount; i++)
52 if (_wcsicmp(ActiveServices[i].ServiceName.Buffer, lpServiceName) == 0)
54 return(&ActiveServices[i]);
58 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
64 static PACTIVE_SERVICE
65 ScLookupServiceByThreadId(DWORD ThreadId)
69 for (i = 0; i < ActiveServiceCount; i++)
71 if (ActiveServices[i].ThreadId == ThreadId)
73 return(&ActiveServices[i]);
77 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
84 ScConnectControlPipe(HANDLE *hPipe)
90 WaitNamedPipeW(L"\\\\.\\pipe\\net\\NtControlPipe",
93 *hPipe = CreateFileW(L"\\\\.\\pipe\\net\\NtControlPipe",
94 GENERIC_READ | GENERIC_WRITE,
95 FILE_SHARE_READ | FILE_SHARE_WRITE,
98 FILE_ATTRIBUTE_NORMAL,
100 if (*hPipe == INVALID_HANDLE_VALUE)
101 return(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT);
103 dwState = PIPE_READMODE_MESSAGE;
104 if (!SetNamedPipeHandleState(*hPipe, &dwState, NULL, NULL))
107 *hPipe = INVALID_HANDLE_VALUE;
108 return(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT);
111 dwProcessId = GetCurrentProcessId();
118 return(ERROR_SUCCESS);
123 ScServiceDispatcher(HANDLE hPipe, PVOID p1, PVOID p2)
125 DPRINT1("ScDispatcherLoop() called\n");
130 /* Read command from the control pipe */
132 /* Execute command */
140 ScServiceMainStub(LPVOID Context)
142 LPSERVICE_MAIN_FUNCTIONW lpServiceProc = (LPSERVICE_MAIN_FUNCTIONW)Context;
144 /* FIXME: Send argc and argv (from command line) as arguments */
146 (lpServiceProc)(0, NULL);
148 return ERROR_SUCCESS;
152 /**********************************************************************
153 * RegisterServiceCtrlHandlerA
157 SERVICE_STATUS_HANDLE STDCALL
158 RegisterServiceCtrlHandlerA(LPCSTR lpServiceName,
159 LPHANDLER_FUNCTION lpHandlerProc)
161 ANSI_STRING ServiceNameA;
162 UNICODE_STRING ServiceNameU;
163 SERVICE_STATUS_HANDLE SHandle;
165 RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
166 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
168 SetLastError(ERROR_OUTOFMEMORY);
169 return((SERVICE_STATUS_HANDLE)0);
172 SHandle = RegisterServiceCtrlHandlerW(ServiceNameU.Buffer,
175 RtlFreeUnicodeString(&ServiceNameU);
181 /**********************************************************************
182 * RegisterServiceCtrlHandlerW
186 SERVICE_STATUS_HANDLE STDCALL
187 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName,
188 LPHANDLER_FUNCTION lpHandlerProc)
190 PACTIVE_SERVICE Service;
192 Service = ScLookupServiceByServiceName((LPWSTR)lpServiceName);
195 return((SERVICE_STATUS_HANDLE)NULL);
198 Service->HandlerFunction = lpHandlerProc;
200 return((SERVICE_STATUS_HANDLE)Service->ThreadId);
204 /**********************************************************************
210 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus,
213 BOOL bUpdateImmediately)
215 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
220 /**********************************************************************
221 * SetServiceObjectSecurity
226 SetServiceObjectSecurity(SC_HANDLE hService,
227 SECURITY_INFORMATION dwSecurityInformation,
228 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
230 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
235 /**********************************************************************
241 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus,
242 LPSERVICE_STATUS lpServiceStatus)
244 PACTIVE_SERVICE Service;
246 Service = ScLookupServiceByThreadId((DWORD)hServiceStatus);
249 SetLastError(ERROR_INVALID_HANDLE);
253 RtlCopyMemory(&Service->ServiceStatus,
255 sizeof(SERVICE_STATUS));
261 /**********************************************************************
262 * StartServiceCtrlDispatcherA
267 StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable)
269 // FIXME how to deal with diffs between ANSI/UNICODE
271 LPSERVICE_TABLE_ENTRYW ServiceStartTableW;
272 ANSI_STRING ServiceNameA;
273 UNICODE_STRING ServiceNameW;
279 while (lpServiceStartTable[i].lpServiceProc != NULL)
285 ServiceStartTableW = RtlAllocateHeap(RtlGetProcessHeap(),
287 sizeof(SERVICE_TABLE_ENTRYW) * Count);
288 for (i = 0; i < Count; i++)
292 lpServiceStartTable[i].lpServiceName);
293 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(
298 for (j = 0; j < i; j++)
300 RtlInitUnicodeString(
302 ServiceStartTableW[j].lpServiceName);
303 RtlFreeUnicodeString(&ServiceNameW);
305 RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW);
306 SetLastError(ERROR_OUTOFMEMORY);
309 ServiceStartTableW[i].lpServiceName = ServiceNameW.Buffer;
310 ServiceStartTableW[i].lpServiceProc =
311 lpServiceStartTable[i].lpServiceProc;
314 b = StartServiceCtrlDispatcherW(ServiceStartTableW);
316 for (i = 0; i < Count; i++)
318 RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW[i].lpServiceName);
321 RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW);
331 /**********************************************************************
332 * StartServiceCtrlDispatcherW
337 StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable)
343 DPRINT("StartServiceCtrlDispatcherW() called\n");
346 while (lpServiceStartTable[i].lpServiceProc != NULL)
351 ActiveServiceCount = i;
352 ActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
354 ActiveServiceCount * sizeof(ACTIVE_SERVICE));
355 if (ActiveServices == NULL)
360 /* Copy service names and start procedure */
361 for (i = 0; i < ActiveServiceCount; i++)
363 RtlCreateUnicodeString(&ActiveServices[i].ServiceName,
364 lpServiceStartTable[i].lpServiceName);
365 ActiveServices[i].MainFunction = lpServiceStartTable[i].lpServiceProc;
368 dwError = ScConnectControlPipe(&hPipe);
369 if (dwError == ERROR_SUCCESS)
371 /* FIXME: free the service table */
375 ScServiceDispatcher(hPipe, NULL, NULL);
378 /* FIXME: free the service table */
383 ActiveServicesThreadHandles = RtlAllocateHeap(RtlGetProcessHeap(),
385 (ActiveServiceCount + 1) * sizeof(HANDLE));
386 if (!ActiveServicesThreadHandles)
388 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveServices);
389 ActiveServices = NULL;
393 for (i = 0; i<ActiveServiceCount; i++)
399 lpServiceStartTable[i].lpServiceProc,
402 if (h == INVALID_HANDLE_VALUE)
404 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveServicesThreadHandles);
405 ActiveServicesThreadHandles = NULL;
406 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveServices);
407 ActiveServices = NULL;
410 ActiveServicesThreadHandles[i + 1] = h;
411 ActiveServices[i].ThreadId = Tid;
414 while (ActiveServiceCount > 0)
416 r = WaitForMultipleObjects(
417 ActiveServiceCount + 1,
418 ActiveServicesThreadHandles,
421 if (r == WAIT_OBJECT_0)
423 /* Received message from the scm */
425 else if (r > WAIT_OBJECT_0 && r < (WAIT_OBJECT_0 + ActiveServiceCount))
429 ActiveServiceCount--;
430 ActiveServicesThreadHandles[r - WAIT_OBJECT_0 - 1] =
431 ActiveServicesThreadHandles[ActiveServiceCount + 1];
433 &ActiveServices[r - WAIT_OBJECT_0 - 2],
434 &ActiveServices[ActiveServiceCount],
435 sizeof(ACTIVE_SERVICE));