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 ******************************************************************/
21 /* TYPES *********************************************************************/
23 typedef struct _ACTIVE_SERVICE
26 UNICODE_STRING ServiceName
;
29 LPSERVICE_MAIN_FUNCTIONA lpFuncA
;
30 LPSERVICE_MAIN_FUNCTIONW lpFuncW
;
32 LPHANDLER_FUNCTION HandlerFunction
;
33 LPHANDLER_FUNCTION_EX HandlerFunctionEx
;
34 LPVOID HandlerContext
;
35 SERVICE_STATUS ServiceStatus
;
38 } ACTIVE_SERVICE
, *PACTIVE_SERVICE
;
41 /* GLOBALS *******************************************************************/
43 static DWORD dwActiveServiceCount
= 0;
44 static PACTIVE_SERVICE lpActiveServices
= NULL
;
47 /* FUNCTIONS *****************************************************************/
49 static PACTIVE_SERVICE
50 ScLookupServiceByServiceName(LPWSTR lpServiceName
)
54 for (i
= 0; i
< dwActiveServiceCount
; i
++)
56 if (_wcsicmp(lpActiveServices
[i
].ServiceName
.Buffer
, lpServiceName
) == 0)
58 return &lpActiveServices
[i
];
62 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST
);
68 static PACTIVE_SERVICE
69 ScLookupServiceByThreadId(DWORD ThreadId
)
73 for (i
= 0; i
< dwActiveServiceCount
; i
++)
75 if (lpActiveServices
[i
].ThreadId
== ThreadId
)
77 return &lpActiveServices
[i
];
81 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST
);
88 ScServiceMainStub(LPVOID Context
)
90 PACTIVE_SERVICE lpService
;
94 lpService
= (PACTIVE_SERVICE
)Context
;
96 DPRINT("ScServiceMainStub() called\n");
99 while (lpService
->Arguments
[dwLength
])
101 dwLength
+= wcslen(&lpService
->Arguments
[dwLength
]) + 1;
105 /* Build the argument vector and call the main service routine */
106 if (lpService
->bUnicode
)
111 lpArgVector
= HeapAlloc(GetProcessHeap(),
113 (dwArgCount
+ 1) * sizeof(LPWSTR
));
114 if (lpArgVector
== NULL
)
115 return ERROR_OUTOFMEMORY
;
118 Ptr
= lpService
->Arguments
;
121 lpArgVector
[dwArgCount
] = Ptr
;
124 Ptr
+= (wcslen(Ptr
) + 1);
126 lpArgVector
[dwArgCount
] = NULL
;
128 (lpService
->Main
.lpFuncW
)(dwArgCount
, lpArgVector
);
130 HeapFree(GetProcessHeap(),
141 AnsiLength
= WideCharToMultiByte(CP_ACP
,
143 lpService
->Arguments
,
149 AnsiString
= HeapAlloc(GetProcessHeap(),
152 WideCharToMultiByte(CP_ACP
,
154 lpService
->Arguments
,
161 lpArgVector
= HeapAlloc(GetProcessHeap(),
163 (dwArgCount
+ 1) * sizeof(LPSTR
));
169 lpArgVector
[dwArgCount
] = Ptr
;
172 Ptr
+= (strlen(Ptr
) + 1);
174 lpArgVector
[dwArgCount
] = NULL
;
176 (lpService
->Main
.lpFuncA
)(dwArgCount
, lpArgVector
);
178 HeapFree(GetProcessHeap(),
181 HeapFree(GetProcessHeap(),
186 return ERROR_SUCCESS
;
191 ScConnectControlPipe(HANDLE
*hPipe
)
193 DWORD dwBytesWritten
;
197 if (!WaitNamedPipeW(L
"\\\\.\\pipe\\net\\NtControlPipe", 15000))
199 DPRINT1("WaitNamedPipe() failed (Error %lu)\n", GetLastError());
200 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
203 *hPipe
= CreateFileW(L
"\\\\.\\pipe\\net\\NtControlPipe",
204 GENERIC_READ
| GENERIC_WRITE
,
208 FILE_ATTRIBUTE_NORMAL
,
210 if (*hPipe
== INVALID_HANDLE_VALUE
)
212 DPRINT1("CreateFileW() failed (Error %lu)\n", GetLastError());
213 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
216 dwState
= PIPE_READMODE_MESSAGE
;
217 if (!SetNamedPipeHandleState(*hPipe
, &dwState
, NULL
, NULL
))
220 *hPipe
= INVALID_HANDLE_VALUE
;
221 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
224 dwProcessId
= GetCurrentProcessId();
231 DPRINT("Sent process id %lu\n", dwProcessId
);
233 return ERROR_SUCCESS
;
239 ScStartService(PSCM_START_PACKET StartPacket
)
241 PACTIVE_SERVICE lpService
;
244 DPRINT("Size: %lu\n", StartPacket
->Size
);
245 DPRINT("Service: %S\n", &StartPacket
->Arguments
[0]);
247 lpService
= ScLookupServiceByServiceName(&StartPacket
->Arguments
[0]);
248 if (lpService
== NULL
)
249 return ERROR_SERVICE_DOES_NOT_EXIST
;
251 lpService
->Arguments
= HeapAlloc(GetProcessHeap(),
253 StartPacket
->Size
* sizeof(WCHAR
));
254 if (lpService
->Arguments
== NULL
)
255 return ERROR_OUTOFMEMORY
;
257 memcpy(lpService
->Arguments
,
258 StartPacket
->Arguments
,
259 StartPacket
->Size
* sizeof(WCHAR
));
261 ThreadHandle
= CreateThread(NULL
,
266 &lpService
->ThreadId
);
267 if (ThreadHandle
== NULL
)
268 return ERROR_SERVICE_NO_THREAD
;
270 ResumeThread(ThreadHandle
);
271 CloseHandle(ThreadHandle
);
273 return ERROR_SUCCESS
;
278 ScServiceDispatcher(HANDLE hPipe
,
286 DPRINT("ScDispatcherLoop() called\n");
288 Buffer
= HeapAlloc(GetProcessHeap(),
296 /* Read command from the control pipe */
297 bResult
= ReadFile(hPipe
,
302 if (bResult
== FALSE
)
304 DPRINT1("Pipe read failed (Error: %lu)\n", GetLastError());
308 /* Execute command */
311 case SCM_START_COMMAND
:
312 DPRINT("Start command\n");
313 ScStartService((PSCM_START_PACKET
)Buffer
);
317 DPRINT1("Unknown command %lu", Buffer
[0]);
322 HeapFree(GetProcessHeap(),
330 /**********************************************************************
331 * RegisterServiceCtrlHandlerA
335 SERVICE_STATUS_HANDLE STDCALL
336 RegisterServiceCtrlHandlerA(LPCSTR lpServiceName
,
337 LPHANDLER_FUNCTION lpHandlerProc
)
339 ANSI_STRING ServiceNameA
;
340 UNICODE_STRING ServiceNameU
;
341 SERVICE_STATUS_HANDLE SHandle
;
343 RtlInitAnsiString(&ServiceNameA
, (LPSTR
)lpServiceName
);
344 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU
, &ServiceNameA
, TRUE
)))
346 SetLastError(ERROR_OUTOFMEMORY
);
347 return (SERVICE_STATUS_HANDLE
)0;
350 SHandle
= RegisterServiceCtrlHandlerW(ServiceNameU
.Buffer
,
353 RtlFreeUnicodeString(&ServiceNameU
);
359 /**********************************************************************
360 * RegisterServiceCtrlHandlerW
364 SERVICE_STATUS_HANDLE STDCALL
365 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName
,
366 LPHANDLER_FUNCTION lpHandlerProc
)
368 PACTIVE_SERVICE Service
;
370 Service
= ScLookupServiceByServiceName((LPWSTR
)lpServiceName
);
373 return (SERVICE_STATUS_HANDLE
)NULL
;
376 Service
->HandlerFunction
= lpHandlerProc
;
377 Service
->HandlerFunctionEx
= NULL
;
379 return (SERVICE_STATUS_HANDLE
)Service
->ThreadId
;
383 /**********************************************************************
384 * RegisterServiceCtrlHandlerExA
388 SERVICE_STATUS_HANDLE STDCALL
389 RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName
,
390 LPHANDLER_FUNCTION_EX lpHandlerProc
,
393 ANSI_STRING ServiceNameA
;
394 UNICODE_STRING ServiceNameU
;
395 SERVICE_STATUS_HANDLE SHandle
;
397 RtlInitAnsiString(&ServiceNameA
, (LPSTR
)lpServiceName
);
398 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU
, &ServiceNameA
, TRUE
)))
400 SetLastError(ERROR_OUTOFMEMORY
);
401 return (SERVICE_STATUS_HANDLE
)0;
404 SHandle
= RegisterServiceCtrlHandlerExW(ServiceNameU
.Buffer
,
408 RtlFreeUnicodeString(&ServiceNameU
);
414 /**********************************************************************
415 * RegisterServiceCtrlHandlerExW
419 SERVICE_STATUS_HANDLE STDCALL
420 RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName
,
421 LPHANDLER_FUNCTION_EX lpHandlerProc
,
424 PACTIVE_SERVICE Service
;
426 Service
= ScLookupServiceByServiceName((LPWSTR
)lpServiceName
);
429 return (SERVICE_STATUS_HANDLE
)NULL
;
432 Service
->HandlerFunction
= NULL
;
433 Service
->HandlerFunctionEx
= lpHandlerProc
;
434 Service
->HandlerContext
= lpContext
;
436 return (SERVICE_STATUS_HANDLE
)Service
->ThreadId
;
440 /**********************************************************************
446 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus
,
449 BOOL bUpdateImmediately
)
451 SetLastError(ERROR_CALL_NOT_IMPLEMENTED
);
456 /**********************************************************************
462 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus
,
463 LPSERVICE_STATUS lpServiceStatus
)
465 PACTIVE_SERVICE Service
;
467 Service
= ScLookupServiceByThreadId((DWORD
)hServiceStatus
);
470 SetLastError(ERROR_INVALID_HANDLE
);
474 RtlCopyMemory(&Service
->ServiceStatus
,
476 sizeof(SERVICE_STATUS
));
482 /**********************************************************************
483 * StartServiceCtrlDispatcherA
488 StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable
)
493 PUCHAR lpMessageBuffer
;
495 DPRINT("StartServiceCtrlDispatcherA() called\n");
498 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
503 dwActiveServiceCount
= i
;
504 lpActiveServices
= RtlAllocateHeap(RtlGetProcessHeap(),
506 dwActiveServiceCount
* sizeof(ACTIVE_SERVICE
));
507 if (lpActiveServices
== NULL
)
512 /* Copy service names and start procedure */
513 for (i
= 0; i
< dwActiveServiceCount
; i
++)
515 RtlCreateUnicodeStringFromAsciiz(&lpActiveServices
[i
].ServiceName
,
516 lpServiceStartTable
[i
].lpServiceName
);
517 lpActiveServices
[i
].Main
.lpFuncA
= lpServiceStartTable
[i
].lpServiceProc
;
518 lpActiveServices
[i
].bUnicode
= FALSE
;
521 dwError
= ScConnectControlPipe(&hPipe
);
522 if (dwError
!= ERROR_SUCCESS
)
524 /* Free the service table */
525 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
526 lpActiveServices
= NULL
;
527 dwActiveServiceCount
= 0;
531 lpMessageBuffer
= RtlAllocateHeap(RtlGetProcessHeap(),
534 if (lpMessageBuffer
== NULL
)
536 /* Free the service table */
537 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
538 lpActiveServices
= NULL
;
539 dwActiveServiceCount
= 0;
544 ScServiceDispatcher(hPipe
, lpMessageBuffer
, 256);
547 /* Free the message buffer */
548 RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer
);
550 /* Free the service table */
551 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
552 lpActiveServices
= NULL
;
553 dwActiveServiceCount
= 0;
559 /**********************************************************************
560 * StartServiceCtrlDispatcherW
565 StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable
)
570 PUCHAR lpMessageBuffer
;
572 DPRINT("StartServiceCtrlDispatcherW() called\n");
575 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
580 dwActiveServiceCount
= i
;
581 lpActiveServices
= RtlAllocateHeap(RtlGetProcessHeap(),
583 dwActiveServiceCount
* sizeof(ACTIVE_SERVICE
));
584 if (lpActiveServices
== NULL
)
589 /* Copy service names and start procedure */
590 for (i
= 0; i
< dwActiveServiceCount
; i
++)
592 RtlCreateUnicodeString(&lpActiveServices
[i
].ServiceName
,
593 lpServiceStartTable
[i
].lpServiceName
);
594 lpActiveServices
[i
].Main
.lpFuncW
= lpServiceStartTable
[i
].lpServiceProc
;
595 lpActiveServices
[i
].bUnicode
= TRUE
;
598 dwError
= ScConnectControlPipe(&hPipe
);
599 if (dwError
!= ERROR_SUCCESS
)
601 /* Free the service table */
602 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
603 lpActiveServices
= NULL
;
604 dwActiveServiceCount
= 0;
608 lpMessageBuffer
= RtlAllocateHeap(RtlGetProcessHeap(),
611 if (lpMessageBuffer
== NULL
)
613 /* Free the service table */
614 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
615 lpActiveServices
= NULL
;
616 dwActiveServiceCount
= 0;
621 ScServiceDispatcher(hPipe
, lpMessageBuffer
, 256);
624 /* Free the message buffer */
625 RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer
);
627 /* Free the service table */
628 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
629 lpActiveServices
= NULL
;
630 dwActiveServiceCount
= 0;