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 ******************************************************************/
20 /* TYPES *********************************************************************/
25 UNICODE_STRING ServiceName
;
26 LPSERVICE_MAIN_FUNCTIONW MainFunction
;
27 LPHANDLER_FUNCTION HandlerFunction
;
28 SERVICE_STATUS ServiceStatus
;
29 } ACTIVE_SERVICE
, *PACTIVE_SERVICE
;
31 /* GLOBALS *******************************************************************/
33 static ULONG ActiveServiceCount
;
34 static PACTIVE_SERVICE ActiveServices
;
35 /* static PHANDLE ActiveServicesThreadHandles; */ /* uncomment when in use */
37 /* FUNCTIONS *****************************************************************/
40 static PACTIVE_SERVICE
41 ScLookupServiceByServiceName(LPWSTR lpServiceName
)
45 for (i
= 0; i
< ActiveServiceCount
; i
++)
47 if (_wcsicmp(ActiveServices
[i
].ServiceName
.Buffer
, lpServiceName
) == 0)
49 return(&ActiveServices
[i
]);
53 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST
);
59 static PACTIVE_SERVICE
60 ScLookupServiceByThreadId(DWORD ThreadId
)
64 for (i
= 0; i
< ActiveServiceCount
; i
++)
66 if (ActiveServices
[i
].ThreadId
== ThreadId
)
68 return(&ActiveServices
[i
]);
72 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST
);
79 ScConnectControlPipe(HANDLE
*hPipe
)
85 WaitNamedPipeW(L
"\\\\.\\pipe\\net\\NtControlPipe",
88 *hPipe
= CreateFileW(L
"\\\\.\\pipe\\net\\NtControlPipe",
89 GENERIC_READ
| GENERIC_WRITE
,
90 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
93 FILE_ATTRIBUTE_NORMAL
,
95 if (*hPipe
== INVALID_HANDLE_VALUE
)
96 return(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
);
98 dwState
= PIPE_READMODE_MESSAGE
;
99 if (!SetNamedPipeHandleState(*hPipe
, &dwState
, NULL
, NULL
))
102 *hPipe
= INVALID_HANDLE_VALUE
;
103 return(ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
);
106 dwProcessId
= GetCurrentProcessId();
113 return(ERROR_SUCCESS
);
118 ScServiceDispatcher(HANDLE hPipe
, PVOID p1
, PVOID p2
)
120 DPRINT1("ScDispatcherLoop() called\n");
125 /* Read command from the control pipe */
127 /* Execute command */
135 ScServiceMainStub(LPVOID Context
)
137 LPSERVICE_MAIN_FUNCTIONW lpServiceProc
= (LPSERVICE_MAIN_FUNCTIONW
)Context
;
139 /* FIXME: Send argc and argv (from command line) as arguments */
141 (lpServiceProc
)(0, NULL
);
143 return ERROR_SUCCESS
;
147 /**********************************************************************
148 * 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
181 SERVICE_STATUS_HANDLE STDCALL
182 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName
,
183 LPHANDLER_FUNCTION lpHandlerProc
)
185 PACTIVE_SERVICE Service
;
187 Service
= ScLookupServiceByServiceName((LPWSTR
)lpServiceName
);
190 return((SERVICE_STATUS_HANDLE
)NULL
);
193 Service
->HandlerFunction
= lpHandlerProc
;
195 return((SERVICE_STATUS_HANDLE
)Service
->ThreadId
);
199 /**********************************************************************
205 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus
,
208 BOOL bUpdateImmediately
)
210 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
215 /**********************************************************************
216 * SetServiceObjectSecurity
221 SetServiceObjectSecurity(SC_HANDLE hService
,
222 SECURITY_INFORMATION dwSecurityInformation
,
223 PSECURITY_DESCRIPTOR lpSecurityDescriptor
)
225 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
230 /**********************************************************************
236 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus
,
237 LPSERVICE_STATUS lpServiceStatus
)
239 PACTIVE_SERVICE Service
;
241 Service
= ScLookupServiceByThreadId((DWORD
)hServiceStatus
);
244 SetLastError(ERROR_INVALID_HANDLE
);
248 RtlCopyMemory(&Service
->ServiceStatus
,
250 sizeof(SERVICE_STATUS
));
256 /**********************************************************************
257 * StartServiceCtrlDispatcherA
262 StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable
)
264 // FIXME how to deal with diffs between ANSI/UNICODE
266 LPSERVICE_TABLE_ENTRYW ServiceStartTableW
;
267 ANSI_STRING ServiceNameA
;
268 UNICODE_STRING ServiceNameW
;
274 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
280 ServiceStartTableW
= RtlAllocateHeap(RtlGetProcessHeap(),
282 sizeof(SERVICE_TABLE_ENTRYW
) * Count
);
283 for (i
= 0; i
< Count
; i
++)
287 lpServiceStartTable
[i
].lpServiceName
);
288 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(
293 for (j
= 0; j
< i
; j
++)
295 RtlInitUnicodeString(
297 ServiceStartTableW
[j
].lpServiceName
);
298 RtlFreeUnicodeString(&ServiceNameW
);
300 RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW
);
301 SetLastError(ERROR_OUTOFMEMORY
);
304 ServiceStartTableW
[i
].lpServiceName
= ServiceNameW
.Buffer
;
305 ServiceStartTableW
[i
].lpServiceProc
=
306 lpServiceStartTable
[i
].lpServiceProc
;
309 b
= StartServiceCtrlDispatcherW(ServiceStartTableW
);
311 for (i
= 0; i
< Count
; i
++)
313 RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW
[i
].lpServiceName
);
316 RtlFreeHeap(RtlGetProcessHeap(), 0, ServiceStartTableW
);
326 /**********************************************************************
327 * StartServiceCtrlDispatcherW
332 StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable
)
338 DPRINT("StartServiceCtrlDispatcherW() called\n");
341 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
346 ActiveServiceCount
= i
;
347 ActiveServices
= RtlAllocateHeap(RtlGetProcessHeap(),
349 ActiveServiceCount
* sizeof(ACTIVE_SERVICE
));
350 if (ActiveServices
== NULL
)
355 /* Copy service names and start procedure */
356 for (i
= 0; i
< ActiveServiceCount
; i
++)
358 RtlCreateUnicodeString(&ActiveServices
[i
].ServiceName
,
359 lpServiceStartTable
[i
].lpServiceName
);
360 ActiveServices
[i
].MainFunction
= lpServiceStartTable
[i
].lpServiceProc
;
363 dwError
= ScConnectControlPipe(&hPipe
);
364 if (dwError
== ERROR_SUCCESS
)
366 /* FIXME: free the service table */
370 ScServiceDispatcher(hPipe
, NULL
, NULL
);
373 /* FIXME: free the service table */
378 ActiveServicesThreadHandles
= RtlAllocateHeap(RtlGetProcessHeap(),
380 (ActiveServiceCount
+ 1) * sizeof(HANDLE
));
381 if (!ActiveServicesThreadHandles
)
383 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveServices
);
384 ActiveServices
= NULL
;
388 for (i
= 0; i
<ActiveServiceCount
; i
++)
394 lpServiceStartTable
[i
].lpServiceProc
,
397 if (h
== INVALID_HANDLE_VALUE
)
399 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveServicesThreadHandles
);
400 ActiveServicesThreadHandles
= NULL
;
401 RtlFreeHeap(RtlGetProcessHeap(), 0, ActiveServices
);
402 ActiveServices
= NULL
;
405 ActiveServicesThreadHandles
[i
+ 1] = h
;
406 ActiveServices
[i
].ThreadId
= Tid
;
409 while (ActiveServiceCount
> 0)
411 r
= WaitForMultipleObjects(
412 ActiveServiceCount
+ 1,
413 ActiveServicesThreadHandles
,
416 if (r
== WAIT_OBJECT_0
)
418 /* Received message from the scm */
420 else if (r
> WAIT_OBJECT_0
&& r
< (WAIT_OBJECT_0
+ ActiveServiceCount
))
424 ActiveServiceCount
--;
425 ActiveServicesThreadHandles
[r
- WAIT_OBJECT_0
- 1] =
426 ActiveServicesThreadHandles
[ActiveServiceCount
+ 1];
428 &ActiveServices
[r
- WAIT_OBJECT_0
- 2],
429 &ActiveServices
[ActiveServiceCount
],
430 sizeof(ACTIVE_SERVICE
));