1 /* $Id: sctrl.c,v 1.6 2002/09/07 15:12:23 chorns Exp $
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 ******************************************************************/
22 /* TYPES *********************************************************************/
27 UNICODE_STRING ServiceName
;
28 LPSERVICE_MAIN_FUNCTION MainFunction
;
29 LPHANDLER_FUNCTION HandlerFunction
;
30 SERVICE_STATUS ServiceStatus
;
31 } ACTIVE_SERVICE
, *PACTIVE_SERVICE
;
33 /* GLOBALS *******************************************************************/
35 static ULONG ActiveServiceCount
;
36 static PACTIVE_SERVICE ActiveServices
;
37 static PHANDLE ActiveServicesThreadHandles
;
39 /* FUNCTIONS *****************************************************************/
42 static PACTIVE_SERVICE
43 ScLookupServiceByServiceName(LPWSTR lpServiceName
)
47 for (i
= 0; i
< ActiveServiceCount
; i
++)
49 if (_wcsicmp(ActiveServices
[i
].ServiceName
.Buffer
, lpServiceName
) == 0)
51 return(&ActiveServices
[i
]);
55 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST
);
61 static PACTIVE_SERVICE
62 ScLookupServiceByThreadId(DWORD ThreadId
)
66 for (i
= 0; i
< ActiveServiceCount
; i
++)
68 if (ActiveServices
[i
].ThreadId
== ThreadId
)
70 return(&ActiveServices
[i
]);
74 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST
);
81 ScConnectControlPipe(HANDLE
*hPipe
)
87 WaitNamedPipeW(L
"\\\\.\\pipe\\net\\NtControlPipe",
90 *hPipe
= CreateFileW(L
"\\\\.\\pipe\\net\\NtControlPipe",
91 GENERIC_READ
| GENERIC_WRITE
,
92 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
95 FILE_ATTRIBUTE_NORMAL
,
97 if (*hPipe
== INVALID_HANDLE_VALUE
)
98 return(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
);
100 dwState
= PIPE_READMODE_MESSAGE
;
101 if (!SetNamedPipeHandleState(*hPipe
, &dwState
, NULL
, NULL
))
104 *hPipe
= INVALID_HANDLE_VALUE
;
105 return(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
);
108 dwProcessId
= GetCurrentProcessId();
115 return(ERROR_SUCCESS
);
120 ScServiceDispatcher(HANDLE hPipe
, PVOID p1
, PVOID p2
)
122 DPRINT1("ScDispatcherLoop() called\n");
127 /* Read command from the control pipe */
129 /* Execute command */
137 ScServiceMainStub(LPVOID Context
)
139 LPSERVICE_MAIN_FUNCTION lpServiceProc
= (LPSERVICE_MAIN_FUNCTION
)Context
;
141 /* FIXME: Send argc and argv (from command line) as arguments */
143 (lpServiceProc
)(0, NULL
);
145 return ERROR_SUCCESS
;
149 /**********************************************************************
150 * RegisterServiceCtrlHandlerA
152 SERVICE_STATUS_HANDLE STDCALL
153 RegisterServiceCtrlHandlerA(LPCSTR lpServiceName
,
154 LPHANDLER_FUNCTION lpHandlerProc
)
156 ANSI_STRING ServiceNameA
;
157 UNICODE_STRING ServiceNameU
;
158 SERVICE_STATUS_HANDLE SHandle
;
160 RtlInitAnsiString(&ServiceNameA
, (LPSTR
)lpServiceName
);
161 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU
, &ServiceNameA
, TRUE
)))
163 SetLastError(ERROR_OUTOFMEMORY
);
164 return((SERVICE_STATUS_HANDLE
)0);
167 SHandle
= RegisterServiceCtrlHandlerW(ServiceNameU
.Buffer
,
170 RtlFreeUnicodeString(&ServiceNameU
);
176 /**********************************************************************
177 * RegisterServiceCtrlHandlerW
179 SERVICE_STATUS_HANDLE STDCALL
180 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName
,
181 LPHANDLER_FUNCTION lpHandlerProc
)
183 PACTIVE_SERVICE Service
;
185 Service
= ScLookupServiceByServiceName((LPWSTR
)lpServiceName
);
188 return((SERVICE_STATUS_HANDLE
)NULL
);
191 Service
->HandlerFunction
= lpHandlerProc
;
193 return((SERVICE_STATUS_HANDLE
)Service
->ThreadId
);
197 /**********************************************************************
201 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus
,
204 BOOL bUpdateImmediately
)
206 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
211 /**********************************************************************
212 * SetServiceObjectSecurity
215 SetServiceObjectSecurity(SC_HANDLE hService
,
216 SECURITY_INFORMATION dwSecurityInformation
,
217 PSECURITY_DESCRIPTOR lpSecurityDescriptor
)
219 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
224 /**********************************************************************
228 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus
,
229 LPSERVICE_STATUS lpServiceStatus
)
231 PACTIVE_SERVICE Service
;
233 Service
= ScLookupServiceByThreadId((DWORD
)hServiceStatus
);
236 SetLastError(ERROR_INVALID_HANDLE
);
240 RtlCopyMemory(&Service
->ServiceStatus
,
242 sizeof(SERVICE_STATUS
));
248 /**********************************************************************
249 * StartServiceCtrlDispatcherA
252 StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable
)
254 LPSERVICE_TABLE_ENTRYW ServiceStartTableW
;
255 ANSI_STRING ServiceNameA
;
256 UNICODE_STRING ServiceNameW
;
262 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
268 ServiceStartTableW
= RtlAllocateHeap(RtlGetProcessHeap(),
270 sizeof(SERVICE_TABLE_ENTRYW
) * Count
);
271 for (i
= 0; i
< Count
; i
++)
275 lpServiceStartTable
[i
].lpServiceName
);
276 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(
281 for (j
= 0; j
< i
; j
++)
283 RtlInitUnicodeString(
285 ServiceStartTableW
[j
].lpServiceName
);
286 RtlFreeUnicodeString(&ServiceNameW
);
288 RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW
);
289 SetLastError(ERROR_OUTOFMEMORY
);
292 ServiceStartTableW
[i
].lpServiceName
= ServiceNameW
.Buffer
;
293 ServiceStartTableW
[i
].lpServiceProc
=
294 lpServiceStartTable
[i
].lpServiceProc
;
297 b
= StartServiceCtrlDispatcherW(ServiceStartTableW
);
299 for (i
= 0; i
< Count
; i
++)
301 RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW
[i
].lpServiceName
);
304 RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW
);
310 /**********************************************************************
311 * StartServiceCtrlDispatcherW
314 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
));