2 * PROJECT: ReactOS advapi32
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: dll/win32/advapi32/service/sctrl.c
5 * PURPOSE: Service control manager functions
6 * COPYRIGHT: Copyright 1999 Emanuele Aliberti
7 * Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
8 * Gregor Brunmar <gregor.brunmar@home.se>
13 /* INCLUDES ******************************************************************/
16 WINE_DEFAULT_DEBUG_CHANNEL(advapi
);
19 /* TYPES *********************************************************************/
21 typedef struct _SERVICE_THREAD_PARAMSA
23 LPSERVICE_MAIN_FUNCTIONA lpServiceMain
;
26 } SERVICE_THREAD_PARAMSA
, *PSERVICE_THREAD_PARAMSA
;
29 typedef struct _SERVICE_THREAD_PARAMSW
31 LPSERVICE_MAIN_FUNCTIONW lpServiceMain
;
34 } SERVICE_THREAD_PARAMSW
, *PSERVICE_THREAD_PARAMSW
;
37 typedef struct _ACTIVE_SERVICE
39 SERVICE_STATUS_HANDLE hServiceStatus
;
40 UNICODE_STRING ServiceName
;
43 SERVICE_THREAD_PARAMSA A
;
44 SERVICE_THREAD_PARAMSW W
;
46 LPHANDLER_FUNCTION HandlerFunction
;
47 LPHANDLER_FUNCTION_EX HandlerFunctionEx
;
48 LPVOID HandlerContext
;
51 } ACTIVE_SERVICE
, *PACTIVE_SERVICE
;
54 /* GLOBALS *******************************************************************/
56 static DWORD dwActiveServiceCount
= 0;
57 static PACTIVE_SERVICE lpActiveServices
= NULL
;
58 static handle_t hStatusBinding
= NULL
;
61 /* FUNCTIONS *****************************************************************/
64 RPC_SERVICE_STATUS_HANDLE_bind(RPC_SERVICE_STATUS_HANDLE hServiceStatus
)
66 return hStatusBinding
;
71 RPC_SERVICE_STATUS_HANDLE_unbind(RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
78 ScCreateStatusBinding(VOID
)
80 LPWSTR pszStringBinding
;
83 TRACE("ScCreateStatusBinding() called\n");
85 status
= RpcStringBindingComposeW(NULL
,
91 if (status
!= RPC_S_OK
)
93 ERR("RpcStringBindingCompose returned 0x%x\n", status
);
97 /* Set the binding handle that will be used to bind to the server. */
98 status
= RpcBindingFromStringBindingW(pszStringBinding
,
100 if (status
!= RPC_S_OK
)
102 ERR("RpcBindingFromStringBinding returned 0x%x\n", status
);
105 status
= RpcStringFreeW(&pszStringBinding
);
106 if (status
!= RPC_S_OK
)
108 ERR("RpcStringFree returned 0x%x\n", status
);
116 ScDestroyStatusBinding(VOID
)
120 TRACE("ScDestroyStatusBinding() called\n");
122 if (hStatusBinding
== NULL
)
125 status
= RpcBindingFree(&hStatusBinding
);
126 if (status
!= RPC_S_OK
)
128 ERR("RpcBindingFree returned 0x%x\n", status
);
132 hStatusBinding
= NULL
;
139 static PACTIVE_SERVICE
140 ScLookupServiceByServiceName(LPCWSTR lpServiceName
)
144 TRACE("ScLookupServiceByServiceName(%S) called\n", lpServiceName
);
146 if (lpActiveServices
[0].bOwnProcess
)
147 return &lpActiveServices
[0];
149 for (i
= 0; i
< dwActiveServiceCount
; i
++)
151 TRACE("Checking %S\n", lpActiveServices
[i
].ServiceName
.Buffer
);
152 if (_wcsicmp(lpActiveServices
[i
].ServiceName
.Buffer
, lpServiceName
) == 0)
155 return &lpActiveServices
[i
];
159 TRACE("No service found!\n");
161 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST
);
168 ScServiceMainStub(LPVOID Context
)
170 PACTIVE_SERVICE lpService
= (PACTIVE_SERVICE
)Context
;
172 TRACE("ScServiceMainStub() called\n");
174 /* Call the main service routine and free the arguments vector */
175 if (lpService
->bUnicode
)
177 (lpService
->ThreadParams
.W
.lpServiceMain
)(lpService
->ThreadParams
.W
.dwArgCount
,
178 lpService
->ThreadParams
.W
.lpArgVector
);
180 if (lpService
->ThreadParams
.W
.lpArgVector
!= NULL
)
182 HeapFree(GetProcessHeap(),
184 lpService
->ThreadParams
.W
.lpArgVector
);
186 lpService
->ThreadParams
.W
.lpArgVector
= NULL
;
187 lpService
->ThreadParams
.W
.dwArgCount
= 0;
192 (lpService
->ThreadParams
.A
.lpServiceMain
)(lpService
->ThreadParams
.A
.dwArgCount
,
193 lpService
->ThreadParams
.A
.lpArgVector
);
195 if (lpService
->ThreadParams
.A
.lpArgVector
!= NULL
)
197 HeapFree(GetProcessHeap(),
199 lpService
->ThreadParams
.A
.lpArgVector
);
201 lpService
->ThreadParams
.A
.lpArgVector
= NULL
;
202 lpService
->ThreadParams
.A
.dwArgCount
= 0;
206 return ERROR_SUCCESS
;
211 ScConnectControlPipe(HANDLE
*hPipe
)
213 DWORD dwBytesWritten
;
215 DWORD dwServiceCurrent
= 0;
217 WCHAR NtControlPipeName
[MAX_PATH
+ 1];
218 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
221 /* Get the service number and create the named pipe */
222 RtlZeroMemory(&QueryTable
,
225 QueryTable
[0].Name
= L
"";
226 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
227 QueryTable
[0].EntryContext
= &dwServiceCurrent
;
229 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
235 if (!NT_SUCCESS(Status
))
237 ERR("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
238 return RtlNtStatusToDosError(Status
);
241 swprintf(NtControlPipeName
, L
"\\\\.\\pipe\\net\\NtControlPipe%u", dwServiceCurrent
);
243 if (!WaitNamedPipeW(NtControlPipeName
, 15000))
245 ERR("WaitNamedPipe(%S) failed (Error %lu)\n", NtControlPipeName
, GetLastError());
246 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
249 *hPipe
= CreateFileW(NtControlPipeName
,
250 GENERIC_READ
| GENERIC_WRITE
,
251 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
254 FILE_ATTRIBUTE_NORMAL
,
256 if (*hPipe
== INVALID_HANDLE_VALUE
)
258 ERR("CreateFileW() failed for pipe %S (Error %lu)\n", NtControlPipeName
, GetLastError());
259 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
262 dwState
= PIPE_READMODE_MESSAGE
;
263 if (!SetNamedPipeHandleState(*hPipe
, &dwState
, NULL
, NULL
))
266 *hPipe
= INVALID_HANDLE_VALUE
;
267 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
270 /* Pass the ProcessId to the SCM */
271 dwProcessId
= GetCurrentProcessId();
278 TRACE("Sent Process ID %lu\n", dwProcessId
);
280 return ERROR_SUCCESS
;
285 ScBuildUnicodeArgsVector(PSCM_CONTROL_PACKET ControlPacket
,
287 LPWSTR
**lpArgVector
)
291 LPWSTR pszServiceName
;
296 if (ControlPacket
== NULL
|| lpArgCount
== NULL
|| lpArgVector
== NULL
)
297 return ERROR_INVALID_PARAMETER
;
302 pszServiceName
= (PWSTR
)((PBYTE
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
);
303 cbServiceName
= lstrlenW(pszServiceName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
305 cbTotal
= cbServiceName
+ sizeof(LPWSTR
);
306 if (ControlPacket
->dwArgumentsCount
> 0)
307 cbTotal
+= ControlPacket
->dwSize
- ControlPacket
->dwArgumentsOffset
;
309 lpVector
= HeapAlloc(GetProcessHeap(),
312 if (lpVector
== NULL
)
313 return ERROR_OUTOFMEMORY
;
316 *lpArg
= (LPWSTR
)(lpArg
+ 1);
319 memcpy(lpArg
, pszServiceName
, cbServiceName
);
320 lpArg
= (LPWSTR
*)((ULONG_PTR
)lpArg
+ cbServiceName
);
322 if (ControlPacket
->dwArgumentsCount
> 0)
325 ((PBYTE
)ControlPacket
+ ControlPacket
->dwArgumentsOffset
),
326 ControlPacket
->dwSize
- ControlPacket
->dwArgumentsOffset
);
328 for (i
= 0; i
< ControlPacket
->dwArgumentsCount
; i
++)
330 *lpArg
= (LPWSTR
)((ULONG_PTR
)lpArg
+ (ULONG_PTR
)*lpArg
);
335 *lpArgCount
= ControlPacket
->dwArgumentsCount
+ 1;
336 *lpArgVector
= lpVector
;
338 return ERROR_SUCCESS
;
343 ScBuildAnsiArgsVector(PSCM_CONTROL_PACKET ControlPacket
,
349 LPWSTR lpUnicodeString
;
350 LPWSTR pszServiceName
;
355 DWORD dwAnsiSize
= 0;
356 DWORD dwAnsiNameSize
= 0;
359 if (ControlPacket
== NULL
|| lpArgCount
== NULL
|| lpArgVector
== NULL
)
360 return ERROR_INVALID_PARAMETER
;
365 pszServiceName
= (PWSTR
)((PBYTE
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
);
366 cbServiceName
= lstrlenW(pszServiceName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
368 dwAnsiNameSize
= WideCharToMultiByte(CP_ACP
,
377 dwVectorSize
= ControlPacket
->dwArgumentsCount
* sizeof(LPWSTR
);
378 if (ControlPacket
->dwArgumentsCount
> 0)
380 lpUnicodeString
= (LPWSTR
)((PBYTE
)ControlPacket
+
381 ControlPacket
->dwArgumentsOffset
+
383 dwUnicodeSize
= (ControlPacket
->dwSize
-
384 ControlPacket
->dwArgumentsOffset
-
385 dwVectorSize
) / sizeof(WCHAR
);
387 dwAnsiSize
= WideCharToMultiByte(CP_ACP
,
397 dwVectorSize
+= sizeof(LPWSTR
);
399 lpVector
= HeapAlloc(GetProcessHeap(),
401 dwVectorSize
+ dwAnsiNameSize
+ dwAnsiSize
);
402 if (lpVector
== NULL
)
403 return ERROR_OUTOFMEMORY
;
405 lpPtr
= (LPSTR
*)lpVector
;
406 lpAnsiString
= (LPSTR
)((ULONG_PTR
)lpVector
+ dwVectorSize
);
408 WideCharToMultiByte(CP_ACP
,
417 if (ControlPacket
->dwArgumentsCount
> 0)
419 lpAnsiString
= (LPSTR
)((ULONG_PTR
)lpAnsiString
+ dwAnsiNameSize
);
421 WideCharToMultiByte(CP_ACP
,
431 lpAnsiString
= (LPSTR
)((ULONG_PTR
)lpVector
+ dwVectorSize
);
432 for (i
= 0; i
< ControlPacket
->dwArgumentsCount
+ 1; i
++)
434 *lpPtr
= lpAnsiString
;
437 lpAnsiString
+= (strlen(lpAnsiString
) + 1);
440 *lpArgCount
= ControlPacket
->dwArgumentsCount
+ 1;
441 *lpArgVector
= lpVector
;
443 return ERROR_SUCCESS
;
448 ScStartService(PACTIVE_SERVICE lpService
,
449 PSCM_CONTROL_PACKET ControlPacket
)
455 if (lpService
== NULL
|| ControlPacket
== NULL
)
456 return ERROR_INVALID_PARAMETER
;
458 TRACE("ScStartService() called\n");
459 TRACE("Size: %lu\n", ControlPacket
->dwSize
);
460 TRACE("Service: %S\n", (PWSTR
)((PBYTE
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
));
462 /* Set the service status handle */
463 lpService
->hServiceStatus
= ControlPacket
->hServiceStatus
;
465 /* Build the arguments vector */
466 if (lpService
->bUnicode
== TRUE
)
468 dwError
= ScBuildUnicodeArgsVector(ControlPacket
,
469 &lpService
->ThreadParams
.W
.dwArgCount
,
470 &lpService
->ThreadParams
.W
.lpArgVector
);
474 dwError
= ScBuildAnsiArgsVector(ControlPacket
,
475 &lpService
->ThreadParams
.A
.dwArgCount
,
476 &lpService
->ThreadParams
.A
.lpArgVector
);
479 if (dwError
!= ERROR_SUCCESS
)
482 /* Invoke the services entry point and implement the command loop */
483 ThreadHandle
= CreateThread(NULL
,
489 if (ThreadHandle
== NULL
)
491 /* Free the arguments vector */
492 if (lpService
->bUnicode
)
494 if (lpService
->ThreadParams
.W
.lpArgVector
!= NULL
)
496 HeapFree(GetProcessHeap(),
498 lpService
->ThreadParams
.W
.lpArgVector
);
499 lpService
->ThreadParams
.W
.lpArgVector
= NULL
;
500 lpService
->ThreadParams
.W
.dwArgCount
= 0;
505 if (lpService
->ThreadParams
.A
.lpArgVector
!= NULL
)
507 HeapFree(GetProcessHeap(),
509 lpService
->ThreadParams
.A
.lpArgVector
);
510 lpService
->ThreadParams
.A
.lpArgVector
= NULL
;
511 lpService
->ThreadParams
.A
.dwArgCount
= 0;
515 return ERROR_SERVICE_NO_THREAD
;
518 ResumeThread(ThreadHandle
);
519 CloseHandle(ThreadHandle
);
521 return ERROR_SUCCESS
;
526 ScControlService(PACTIVE_SERVICE lpService
,
527 PSCM_CONTROL_PACKET ControlPacket
)
529 if (lpService
== NULL
|| ControlPacket
== NULL
)
530 return ERROR_INVALID_PARAMETER
;
532 TRACE("ScControlService() called\n");
533 TRACE("Size: %lu\n", ControlPacket
->dwSize
);
534 TRACE("Service: %S\n", (PWSTR
)((PBYTE
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
));
536 if (lpService
->HandlerFunction
)
538 (lpService
->HandlerFunction
)(ControlPacket
->dwControl
);
540 else if (lpService
->HandlerFunctionEx
)
542 /* FIXME: send correct params */
543 (lpService
->HandlerFunctionEx
)(ControlPacket
->dwControl
, 0, NULL
, NULL
);
546 TRACE("ScControlService() done\n");
548 return ERROR_SUCCESS
;
553 ScServiceDispatcher(HANDLE hPipe
,
554 PSCM_CONTROL_PACKET ControlPacket
,
559 DWORD dwRunningServices
= 0;
560 LPWSTR lpServiceName
;
561 PACTIVE_SERVICE lpService
;
562 SCM_REPLY_PACKET ReplyPacket
;
565 TRACE("ScDispatcherLoop() called\n");
567 if (ControlPacket
== NULL
|| dwBufferSize
< sizeof(SCM_CONTROL_PACKET
))
572 /* Read command from the control pipe */
573 bResult
= ReadFile(hPipe
,
578 if (bResult
== FALSE
)
580 ERR("Pipe read failed (Error: %lu)\n", GetLastError());
584 lpServiceName
= (LPWSTR
)((PBYTE
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
);
585 TRACE("Service: %S\n", lpServiceName
);
587 if (ControlPacket
->dwControl
== SERVICE_CONTROL_START_OWN
)
588 lpActiveServices
[0].bOwnProcess
= TRUE
;
590 lpService
= ScLookupServiceByServiceName(lpServiceName
);
591 if (lpService
!= NULL
)
593 /* Execute command */
594 switch (ControlPacket
->dwControl
)
596 case SERVICE_CONTROL_START_SHARE
:
597 case SERVICE_CONTROL_START_OWN
:
598 TRACE("Start command - received SERVICE_CONTROL_START\n");
599 dwError
= ScStartService(lpService
, ControlPacket
);
600 if (dwError
== ERROR_SUCCESS
)
604 case SERVICE_CONTROL_STOP
:
605 TRACE("Stop command - received SERVICE_CONTROL_STOP\n");
606 dwError
= ScControlService(lpService
, ControlPacket
);
607 if (dwError
== ERROR_SUCCESS
)
612 TRACE("Command %lu received", ControlPacket
->dwControl
);
613 dwError
= ScControlService(lpService
, ControlPacket
);
619 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
622 ReplyPacket
.dwError
= dwError
;
624 /* Send the reply packet */
625 bResult
= WriteFile(hPipe
,
630 if (bResult
== FALSE
)
632 ERR("Pipe write failed (Error: %lu)\n", GetLastError());
636 if (dwRunningServices
== 0)
644 /**********************************************************************
645 * RegisterServiceCtrlHandlerA
649 SERVICE_STATUS_HANDLE WINAPI
650 RegisterServiceCtrlHandlerA(LPCSTR lpServiceName
,
651 LPHANDLER_FUNCTION lpHandlerProc
)
653 ANSI_STRING ServiceNameA
;
654 UNICODE_STRING ServiceNameU
;
655 SERVICE_STATUS_HANDLE SHandle
;
657 RtlInitAnsiString(&ServiceNameA
, (LPSTR
)lpServiceName
);
658 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU
, &ServiceNameA
, TRUE
)))
660 SetLastError(ERROR_OUTOFMEMORY
);
661 return (SERVICE_STATUS_HANDLE
)0;
664 SHandle
= RegisterServiceCtrlHandlerW(ServiceNameU
.Buffer
,
667 RtlFreeUnicodeString(&ServiceNameU
);
673 /**********************************************************************
674 * RegisterServiceCtrlHandlerW
678 SERVICE_STATUS_HANDLE WINAPI
679 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName
,
680 LPHANDLER_FUNCTION lpHandlerProc
)
682 PACTIVE_SERVICE Service
;
684 Service
= ScLookupServiceByServiceName((LPWSTR
)lpServiceName
);
687 return (SERVICE_STATUS_HANDLE
)NULL
;
690 Service
->HandlerFunction
= lpHandlerProc
;
691 Service
->HandlerFunctionEx
= NULL
;
693 TRACE("RegisterServiceCtrlHandler returning %lu\n", Service
->hServiceStatus
);
695 return Service
->hServiceStatus
;
699 /**********************************************************************
700 * RegisterServiceCtrlHandlerExA
704 SERVICE_STATUS_HANDLE WINAPI
705 RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName
,
706 LPHANDLER_FUNCTION_EX lpHandlerProc
,
709 ANSI_STRING ServiceNameA
;
710 UNICODE_STRING ServiceNameU
;
711 SERVICE_STATUS_HANDLE SHandle
;
713 RtlInitAnsiString(&ServiceNameA
, (LPSTR
)lpServiceName
);
714 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU
, &ServiceNameA
, TRUE
)))
716 SetLastError(ERROR_OUTOFMEMORY
);
717 return (SERVICE_STATUS_HANDLE
)0;
720 SHandle
= RegisterServiceCtrlHandlerExW(ServiceNameU
.Buffer
,
724 RtlFreeUnicodeString(&ServiceNameU
);
730 /**********************************************************************
731 * RegisterServiceCtrlHandlerExW
735 SERVICE_STATUS_HANDLE WINAPI
736 RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName
,
737 LPHANDLER_FUNCTION_EX lpHandlerProc
,
740 PACTIVE_SERVICE Service
;
742 Service
= ScLookupServiceByServiceName(lpServiceName
);
745 return (SERVICE_STATUS_HANDLE
)NULL
;
748 Service
->HandlerFunction
= NULL
;
749 Service
->HandlerFunctionEx
= lpHandlerProc
;
750 Service
->HandlerContext
= lpContext
;
752 TRACE("RegisterServiceCtrlHandlerEx returning %lu\n", Service
->hServiceStatus
);
754 return Service
->hServiceStatus
;
758 /**********************************************************************
759 * I_ScSetServiceBitsA
766 I_ScSetServiceBitsA(SERVICE_STATUS_HANDLE hServiceStatus
,
769 BOOL bUpdateImmediately
,
776 /* Call to services.exe using RPC */
777 bResult
= RI_ScSetServiceBitsA((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
783 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
785 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
794 /**********************************************************************
795 * I_ScSetServiceBitsW
802 I_ScSetServiceBitsW(SERVICE_STATUS_HANDLE hServiceStatus
,
805 BOOL bUpdateImmediately
,
812 /* Call to services.exe using RPC */
813 bResult
= RI_ScSetServiceBitsW((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
819 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
821 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
830 /**********************************************************************
836 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus
,
839 BOOL bUpdateImmediately
)
841 return I_ScSetServiceBitsW(hServiceStatus
,
849 /**********************************************************************
855 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus
,
856 LPSERVICE_STATUS lpServiceStatus
)
860 TRACE("SetServiceStatus() called\n");
861 TRACE("hServiceStatus %lu\n", hServiceStatus
);
865 /* Call to services.exe using RPC */
866 dwError
= RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
869 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
871 dwError
= ScmRpcStatusToWinError(RpcExceptionCode());
875 if (dwError
!= ERROR_SUCCESS
)
877 ERR("ScmrSetServiceStatus() failed (Error %lu)\n", dwError
);
878 SetLastError(dwError
);
882 TRACE("SetServiceStatus() done (ret %lu)\n", dwError
);
888 /**********************************************************************
889 * StartServiceCtrlDispatcherA
894 StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA
*lpServiceStartTable
)
899 PSCM_CONTROL_PACKET ControlPacket
;
903 TRACE("StartServiceCtrlDispatcherA() called\n");
906 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
911 dwActiveServiceCount
= i
;
912 lpActiveServices
= RtlAllocateHeap(RtlGetProcessHeap(),
914 dwActiveServiceCount
* sizeof(ACTIVE_SERVICE
));
915 if (lpActiveServices
== NULL
)
920 /* Copy service names and start procedure */
921 for (i
= 0; i
< dwActiveServiceCount
; i
++)
923 RtlCreateUnicodeStringFromAsciiz(&lpActiveServices
[i
].ServiceName
,
924 lpServiceStartTable
[i
].lpServiceName
);
925 lpActiveServices
[i
].ThreadParams
.A
.lpServiceMain
= lpServiceStartTable
[i
].lpServiceProc
;
926 lpActiveServices
[i
].hServiceStatus
= 0;
927 lpActiveServices
[i
].bUnicode
= FALSE
;
928 lpActiveServices
[i
].bOwnProcess
= FALSE
;
931 dwError
= ScConnectControlPipe(&hPipe
);
932 if (dwError
!= ERROR_SUCCESS
)
938 dwBufSize
= sizeof(SCM_CONTROL_PACKET
) +
939 (MAX_SERVICE_NAME_LENGTH
+ 1) * sizeof(WCHAR
);
941 ControlPacket
= RtlAllocateHeap(RtlGetProcessHeap(),
944 if (ControlPacket
== NULL
)
950 ScCreateStatusBinding();
952 ScServiceDispatcher(hPipe
, ControlPacket
, dwBufSize
);
954 ScDestroyStatusBinding();
958 /* Free the control packet */
959 RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket
);
962 /* Free the service table */
963 for (i
= 0; i
< dwActiveServiceCount
; i
++)
965 RtlFreeUnicodeString(&lpActiveServices
[i
].ServiceName
);
967 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
968 lpActiveServices
= NULL
;
969 dwActiveServiceCount
= 0;
975 /**********************************************************************
976 * StartServiceCtrlDispatcherW
981 StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW
*lpServiceStartTable
)
986 PSCM_CONTROL_PACKET ControlPacket
;
990 TRACE("StartServiceCtrlDispatcherW() called\n");
993 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
998 dwActiveServiceCount
= i
;
999 lpActiveServices
= RtlAllocateHeap(RtlGetProcessHeap(),
1001 dwActiveServiceCount
* sizeof(ACTIVE_SERVICE
));
1002 if (lpActiveServices
== NULL
)
1007 /* Copy service names and start procedure */
1008 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1010 RtlCreateUnicodeString(&lpActiveServices
[i
].ServiceName
,
1011 lpServiceStartTable
[i
].lpServiceName
);
1012 lpActiveServices
[i
].ThreadParams
.W
.lpServiceMain
= lpServiceStartTable
[i
].lpServiceProc
;
1013 lpActiveServices
[i
].hServiceStatus
= 0;
1014 lpActiveServices
[i
].bUnicode
= TRUE
;
1015 lpActiveServices
[i
].bOwnProcess
= FALSE
;
1018 dwError
= ScConnectControlPipe(&hPipe
);
1019 if (dwError
!= ERROR_SUCCESS
)
1025 dwBufSize
= sizeof(SCM_CONTROL_PACKET
) +
1026 (MAX_SERVICE_NAME_LENGTH
+ 1) * sizeof(WCHAR
);
1028 ControlPacket
= RtlAllocateHeap(RtlGetProcessHeap(),
1031 if (ControlPacket
== NULL
)
1037 ScCreateStatusBinding();
1039 ScServiceDispatcher(hPipe
, ControlPacket
, dwBufSize
);
1041 ScDestroyStatusBinding();
1045 /* Free the control packet */
1046 RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket
);
1049 /* Free the service table */
1050 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1052 RtlFreeUnicodeString(&lpActiveServices
[i
].ServiceName
);
1054 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
1055 lpActiveServices
= NULL
;
1056 dwActiveServiceCount
= 0;