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_FUNCTION 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_FUNCTION lpServiceProc = (LPSERVICE_MAIN_FUNCTION)Context;
144 /* FIXME: Send argc and argv (from command line) as arguments */
146 (lpServiceProc)(0, NULL);
148 return ERROR_SUCCESS;
152 /**********************************************************************
153 * RegisterServiceCtrlHandlerA
155 SERVICE_STATUS_HANDLE STDCALL
156 RegisterServiceCtrlHandlerA(LPCSTR lpServiceName,
157 LPHANDLER_FUNCTION lpHandlerProc)
159 ANSI_STRING ServiceNameA;
160 UNICODE_STRING ServiceNameU;
161 SERVICE_STATUS_HANDLE SHandle;
163 RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
164 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
166 SetLastError(ERROR_OUTOFMEMORY);
167 return((SERVICE_STATUS_HANDLE)0);
170 SHandle = RegisterServiceCtrlHandlerW(ServiceNameU.Buffer,
173 RtlFreeUnicodeString(&ServiceNameU);
179 /**********************************************************************
180 * RegisterServiceCtrlHandlerW
182 SERVICE_STATUS_HANDLE STDCALL
183 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName,
184 LPHANDLER_FUNCTION lpHandlerProc)
186 PACTIVE_SERVICE Service;
188 Service = ScLookupServiceByServiceName((LPWSTR)lpServiceName);
191 return((SERVICE_STATUS_HANDLE)NULL);
194 Service->HandlerFunction = lpHandlerProc;
196 return((SERVICE_STATUS_HANDLE)Service->ThreadId);
200 /**********************************************************************
204 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus,
207 BOOL bUpdateImmediately)
209 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
214 /**********************************************************************
215 * SetServiceObjectSecurity
218 SetServiceObjectSecurity(SC_HANDLE hService,
219 SECURITY_INFORMATION dwSecurityInformation,
220 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
222 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
227 /**********************************************************************
231 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus,
232 LPSERVICE_STATUS lpServiceStatus)
234 PACTIVE_SERVICE Service;
236 Service = ScLookupServiceByThreadId((DWORD)hServiceStatus);
239 SetLastError(ERROR_INVALID_HANDLE);
243 RtlCopyMemory(&Service->ServiceStatus,
245 sizeof(SERVICE_STATUS));
251 /**********************************************************************
252 * StartServiceCtrlDispatcherA
255 StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable)
257 LPSERVICE_TABLE_ENTRYW ServiceStartTableW;
258 ANSI_STRING ServiceNameA;
259 UNICODE_STRING ServiceNameW;
265 while (lpServiceStartTable[i].lpServiceProc != NULL)
271 ServiceStartTableW = RtlAllocateHeap(RtlGetProcessHeap(),
273 sizeof(SERVICE_TABLE_ENTRYW) * Count);
274 for (i = 0; i < Count; i++)
278 lpServiceStartTable[i].lpServiceName);
279 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(
284 for (j = 0; j < i; j++)
286 RtlInitUnicodeString(
288 ServiceStartTableW[j].lpServiceName);
289 RtlFreeUnicodeString(&ServiceNameW);
291 RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW);
292 SetLastError(ERROR_OUTOFMEMORY);
295 ServiceStartTableW[i].lpServiceName = ServiceNameW.Buffer;
296 ServiceStartTableW[i].lpServiceProc =
297 lpServiceStartTable[i].lpServiceProc;
300 b = StartServiceCtrlDispatcherW(ServiceStartTableW);
302 for (i = 0; i < Count; i++)
304 RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW[i].lpServiceName);
307 RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW);
313 /**********************************************************************
314 * StartServiceCtrlDispatcherW
317 StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable)
323 DPRINT1("StartServiceCtrlDispatcherW() called\n");
326 while (lpServiceStartTable[i].lpServiceProc != NULL)
331 ActiveServiceCount = i;
332 ActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
334 ActiveServiceCount * sizeof(ACTIVE_SERVICE));
335 if (ActiveServices == NULL)
340 /* Copy service names and start procedure */
341 for (i = 0; i < ActiveServiceCount; i++)
343 RtlCreateUnicodeString(&ActiveServices[i].ServiceName,
344 lpServiceStartTable[i].lpServiceName);
345 ActiveServices[i].MainFunction = lpServiceStartTable[i].lpServiceProc;
348 dwError = ScConnectControlPipe(&hPipe);
349 if (dwError == ERROR_SUCCESS)
351 /* FIXME: free the service table */
355 ScServiceDispatcher(hPipe, NULL, NULL);
358 /* FIXME: free the service table */
363 ActiveServicesThreadHandles = RtlAllocateHeap(RtlGetProcessHeap(),
365 (ActiveServiceCount + 1) * sizeof(HANDLE));
366 if (!ActiveServicesThreadHandles)
368 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveServices);
369 ActiveServices = NULL;
373 for (i = 0; i<ActiveServiceCount; i++)
379 lpServiceStartTable[i].lpServiceProc,
382 if (h == INVALID_HANDLE_VALUE)
384 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveServicesThreadHandles);
385 ActiveServicesThreadHandles = NULL;
386 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveServices);
387 ActiveServices = NULL;
390 ActiveServicesThreadHandles[i + 1] = h;
391 ActiveServices[i].ThreadId = Tid;
394 while (ActiveServiceCount > 0)
396 r = WaitForMultipleObjects(
397 ActiveServiceCount + 1,
398 ActiveServicesThreadHandles,
401 if (r == WAIT_OBJECT_0)
403 /* Received message from the scm */
405 else if (r > WAIT_OBJECT_0 && r < (WAIT_OBJECT_0 + ActiveServiceCount))
409 ActiveServiceCount--;
410 ActiveServicesThreadHandles[r - WAIT_OBJECT_0 - 1] =
411 ActiveServicesThreadHandles[ActiveServiceCount + 1];
413 &ActiveServices[r - WAIT_OBJECT_0 - 2],
414 &ActiveServices[ActiveServiceCount],
415 sizeof(ACTIVE_SERVICE));