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>
12 /* INCLUDES ******************************************************************/
15 WINE_DEFAULT_DEBUG_CHANNEL(advapi
);
18 /* TYPES *********************************************************************/
20 typedef struct _SERVICE_THREAD_PARAMSA
22 LPSERVICE_MAIN_FUNCTIONA lpServiceMain
;
25 } SERVICE_THREAD_PARAMSA
, *PSERVICE_THREAD_PARAMSA
;
28 typedef struct _SERVICE_THREAD_PARAMSW
30 LPSERVICE_MAIN_FUNCTIONW lpServiceMain
;
33 } SERVICE_THREAD_PARAMSW
, *PSERVICE_THREAD_PARAMSW
;
36 typedef struct _ACTIVE_SERVICE
38 SERVICE_STATUS_HANDLE hServiceStatus
;
39 UNICODE_STRING ServiceName
;
42 LPSERVICE_MAIN_FUNCTIONA A
;
43 LPSERVICE_MAIN_FUNCTIONW W
;
45 LPHANDLER_FUNCTION HandlerFunction
;
46 LPHANDLER_FUNCTION_EX HandlerFunctionEx
;
47 LPVOID HandlerContext
;
50 } ACTIVE_SERVICE
, *PACTIVE_SERVICE
;
53 /* GLOBALS *******************************************************************/
55 static DWORD dwActiveServiceCount
= 0;
56 static PACTIVE_SERVICE lpActiveServices
= NULL
;
57 static handle_t hStatusBinding
= NULL
;
60 /* FUNCTIONS *****************************************************************/
63 RPC_SERVICE_STATUS_HANDLE_bind(RPC_SERVICE_STATUS_HANDLE hServiceStatus
)
65 return hStatusBinding
;
70 RPC_SERVICE_STATUS_HANDLE_unbind(RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
77 ScCreateStatusBinding(VOID
)
79 LPWSTR pszStringBinding
;
82 TRACE("ScCreateStatusBinding() called\n");
84 status
= RpcStringBindingComposeW(NULL
,
90 if (status
!= RPC_S_OK
)
92 ERR("RpcStringBindingCompose returned 0x%x\n", status
);
96 /* Set the binding handle that will be used to bind to the server. */
97 status
= RpcBindingFromStringBindingW(pszStringBinding
,
99 if (status
!= RPC_S_OK
)
101 ERR("RpcBindingFromStringBinding returned 0x%x\n", status
);
104 status
= RpcStringFreeW(&pszStringBinding
);
105 if (status
!= RPC_S_OK
)
107 ERR("RpcStringFree returned 0x%x\n", status
);
115 ScDestroyStatusBinding(VOID
)
119 TRACE("ScDestroyStatusBinding() called\n");
121 if (hStatusBinding
== NULL
)
124 status
= RpcBindingFree(&hStatusBinding
);
125 if (status
!= RPC_S_OK
)
127 ERR("RpcBindingFree returned 0x%x\n", status
);
131 hStatusBinding
= NULL
;
138 static PACTIVE_SERVICE
139 ScLookupServiceByServiceName(LPCWSTR lpServiceName
)
143 TRACE("ScLookupServiceByServiceName(%S) called\n", lpServiceName
);
145 if (lpActiveServices
[0].bOwnProcess
)
146 return &lpActiveServices
[0];
148 for (i
= 0; i
< dwActiveServiceCount
; i
++)
150 TRACE("Checking %S\n", lpActiveServices
[i
].ServiceName
.Buffer
);
151 if (_wcsicmp(lpActiveServices
[i
].ServiceName
.Buffer
, lpServiceName
) == 0)
154 return &lpActiveServices
[i
];
158 TRACE("No service found!\n");
160 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST
);
167 ScServiceMainStubA(LPVOID Context
)
169 PSERVICE_THREAD_PARAMSA ThreadParams
= Context
;
171 TRACE("ScServiceMainStubA() called\n");
173 /* Call the main service routine and free the arguments vector */
174 (ThreadParams
->lpServiceMain
)(ThreadParams
->dwArgCount
,
175 ThreadParams
->lpArgVector
);
177 if (ThreadParams
->lpArgVector
!= NULL
)
179 HeapFree(GetProcessHeap(), 0, ThreadParams
->lpArgVector
);
181 HeapFree(GetProcessHeap(), 0, ThreadParams
);
183 return ERROR_SUCCESS
;
187 ScServiceMainStubW(LPVOID Context
)
189 PSERVICE_THREAD_PARAMSW ThreadParams
= Context
;
191 TRACE("ScServiceMainStubW() called\n");
193 /* Call the main service routine and free the arguments vector */
194 (ThreadParams
->lpServiceMain
)(ThreadParams
->dwArgCount
,
195 ThreadParams
->lpArgVector
);
197 if (ThreadParams
->lpArgVector
!= NULL
)
199 HeapFree(GetProcessHeap(), 0, ThreadParams
->lpArgVector
);
201 HeapFree(GetProcessHeap(), 0, ThreadParams
);
203 return ERROR_SUCCESS
;
208 ScConnectControlPipe(HANDLE
*hPipe
)
210 DWORD dwBytesWritten
;
212 DWORD dwServiceCurrent
= 0;
214 WCHAR NtControlPipeName
[MAX_PATH
+ 1];
215 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
218 /* Get the service number and create the named pipe */
219 RtlZeroMemory(&QueryTable
,
222 QueryTable
[0].Name
= L
"";
223 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
224 QueryTable
[0].EntryContext
= &dwServiceCurrent
;
226 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
232 if (!NT_SUCCESS(Status
))
234 ERR("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
235 return RtlNtStatusToDosError(Status
);
238 swprintf(NtControlPipeName
, L
"\\\\.\\pipe\\net\\NtControlPipe%u", dwServiceCurrent
);
240 if (!WaitNamedPipeW(NtControlPipeName
, 30000))
242 ERR("WaitNamedPipe(%S) failed (Error %lu)\n", NtControlPipeName
, GetLastError());
243 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
246 *hPipe
= CreateFileW(NtControlPipeName
,
247 GENERIC_READ
| GENERIC_WRITE
,
248 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
251 FILE_ATTRIBUTE_NORMAL
,
253 if (*hPipe
== INVALID_HANDLE_VALUE
)
255 ERR("CreateFileW() failed for pipe %S (Error %lu)\n", NtControlPipeName
, GetLastError());
256 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
259 dwState
= PIPE_READMODE_MESSAGE
;
260 if (!SetNamedPipeHandleState(*hPipe
, &dwState
, NULL
, NULL
))
263 *hPipe
= INVALID_HANDLE_VALUE
;
264 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
267 /* Pass the ProcessId to the SCM */
268 dwProcessId
= GetCurrentProcessId();
275 TRACE("Sent Process ID %lu\n", dwProcessId
);
277 return ERROR_SUCCESS
;
282 ScBuildUnicodeArgsVector(PSCM_CONTROL_PACKET ControlPacket
,
284 LPWSTR
**lpArgVector
)
288 LPWSTR pszServiceName
;
293 if (ControlPacket
== NULL
|| lpArgCount
== NULL
|| lpArgVector
== NULL
)
294 return ERROR_INVALID_PARAMETER
;
299 pszServiceName
= (PWSTR
)((PBYTE
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
);
300 cbServiceName
= lstrlenW(pszServiceName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
302 cbTotal
= cbServiceName
+ sizeof(LPWSTR
);
303 if (ControlPacket
->dwArgumentsCount
> 0)
304 cbTotal
+= ControlPacket
->dwSize
- ControlPacket
->dwArgumentsOffset
;
306 lpVector
= HeapAlloc(GetProcessHeap(),
309 if (lpVector
== NULL
)
310 return ERROR_OUTOFMEMORY
;
313 *lpArg
= (LPWSTR
)(lpArg
+ 1);
316 memcpy(lpArg
, pszServiceName
, cbServiceName
);
317 lpArg
= (LPWSTR
*)((ULONG_PTR
)lpArg
+ cbServiceName
);
319 if (ControlPacket
->dwArgumentsCount
> 0)
322 ((PBYTE
)ControlPacket
+ ControlPacket
->dwArgumentsOffset
),
323 ControlPacket
->dwSize
- ControlPacket
->dwArgumentsOffset
);
325 for (i
= 0; i
< ControlPacket
->dwArgumentsCount
; i
++)
327 *lpArg
= (LPWSTR
)((ULONG_PTR
)lpArg
+ (ULONG_PTR
)*lpArg
);
332 *lpArgCount
= ControlPacket
->dwArgumentsCount
+ 1;
333 *lpArgVector
= lpVector
;
335 return ERROR_SUCCESS
;
340 ScBuildAnsiArgsVector(PSCM_CONTROL_PACKET ControlPacket
,
346 LPWSTR lpUnicodeString
;
347 LPWSTR pszServiceName
;
352 DWORD dwAnsiSize
= 0;
353 DWORD dwAnsiNameSize
= 0;
356 if (ControlPacket
== NULL
|| lpArgCount
== NULL
|| lpArgVector
== NULL
)
357 return ERROR_INVALID_PARAMETER
;
362 pszServiceName
= (PWSTR
)((PBYTE
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
);
363 cbServiceName
= lstrlenW(pszServiceName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
365 dwAnsiNameSize
= WideCharToMultiByte(CP_ACP
,
374 dwVectorSize
= ControlPacket
->dwArgumentsCount
* sizeof(LPWSTR
);
375 if (ControlPacket
->dwArgumentsCount
> 0)
377 lpUnicodeString
= (LPWSTR
)((PBYTE
)ControlPacket
+
378 ControlPacket
->dwArgumentsOffset
+
380 dwUnicodeSize
= (ControlPacket
->dwSize
-
381 ControlPacket
->dwArgumentsOffset
-
382 dwVectorSize
) / sizeof(WCHAR
);
384 dwAnsiSize
= WideCharToMultiByte(CP_ACP
,
394 dwVectorSize
+= sizeof(LPWSTR
);
396 lpVector
= HeapAlloc(GetProcessHeap(),
398 dwVectorSize
+ dwAnsiNameSize
+ dwAnsiSize
);
399 if (lpVector
== NULL
)
400 return ERROR_OUTOFMEMORY
;
402 lpPtr
= (LPSTR
*)lpVector
;
403 lpAnsiString
= (LPSTR
)((ULONG_PTR
)lpVector
+ dwVectorSize
);
405 WideCharToMultiByte(CP_ACP
,
414 if (ControlPacket
->dwArgumentsCount
> 0)
416 lpAnsiString
= (LPSTR
)((ULONG_PTR
)lpAnsiString
+ dwAnsiNameSize
);
418 WideCharToMultiByte(CP_ACP
,
428 lpAnsiString
= (LPSTR
)((ULONG_PTR
)lpVector
+ dwVectorSize
);
429 for (i
= 0; i
< ControlPacket
->dwArgumentsCount
+ 1; i
++)
431 *lpPtr
= lpAnsiString
;
434 lpAnsiString
+= (strlen(lpAnsiString
) + 1);
437 *lpArgCount
= ControlPacket
->dwArgumentsCount
+ 1;
438 *lpArgVector
= lpVector
;
440 return ERROR_SUCCESS
;
445 ScStartService(PACTIVE_SERVICE lpService
,
446 PSCM_CONTROL_PACKET ControlPacket
)
451 PSERVICE_THREAD_PARAMSA ThreadParamsA
;
452 PSERVICE_THREAD_PARAMSW ThreadParamsW
;
454 if (lpService
== NULL
|| ControlPacket
== NULL
)
455 return ERROR_INVALID_PARAMETER
;
457 TRACE("ScStartService() called\n");
458 TRACE("Size: %lu\n", ControlPacket
->dwSize
);
459 TRACE("Service: %S\n", (PWSTR
)((PBYTE
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
));
461 /* Set the service status handle */
462 lpService
->hServiceStatus
= ControlPacket
->hServiceStatus
;
464 /* Build the arguments vector */
465 if (lpService
->bUnicode
== TRUE
)
467 ThreadParamsW
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ThreadParamsW
));
468 if (ThreadParamsW
== NULL
)
469 return ERROR_NOT_ENOUGH_MEMORY
;
470 dwError
= ScBuildUnicodeArgsVector(ControlPacket
,
471 &ThreadParamsW
->dwArgCount
,
472 &ThreadParamsW
->lpArgVector
);
473 if (dwError
!= ERROR_SUCCESS
)
475 HeapFree(GetProcessHeap(), 0, ThreadParamsW
);
478 ThreadParamsW
->lpServiceMain
= lpService
->ServiceMain
.W
;
479 ThreadHandle
= CreateThread(NULL
,
485 if (ThreadHandle
== NULL
)
487 if (ThreadParamsW
->lpArgVector
!= NULL
)
489 HeapFree(GetProcessHeap(),
491 ThreadParamsW
->lpArgVector
);
493 HeapFree(GetProcessHeap(), 0, ThreadParamsW
);
498 ThreadParamsA
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ThreadParamsA
));
499 if (ThreadParamsA
== NULL
)
500 return ERROR_NOT_ENOUGH_MEMORY
;
501 dwError
= ScBuildAnsiArgsVector(ControlPacket
,
502 &ThreadParamsA
->dwArgCount
,
503 &ThreadParamsA
->lpArgVector
);
504 if (dwError
!= ERROR_SUCCESS
)
506 HeapFree(GetProcessHeap(), 0, ThreadParamsA
);
509 ThreadParamsA
->lpServiceMain
= lpService
->ServiceMain
.A
;
510 ThreadHandle
= CreateThread(NULL
,
516 if (ThreadHandle
== NULL
)
518 if (ThreadParamsA
->lpArgVector
!= NULL
)
520 HeapFree(GetProcessHeap(),
522 ThreadParamsA
->lpArgVector
);
524 HeapFree(GetProcessHeap(), 0, ThreadParamsA
);
528 ResumeThread(ThreadHandle
);
529 CloseHandle(ThreadHandle
);
531 return ERROR_SUCCESS
;
536 ScControlService(PACTIVE_SERVICE lpService
,
537 PSCM_CONTROL_PACKET ControlPacket
)
539 if (lpService
== NULL
|| ControlPacket
== NULL
)
540 return ERROR_INVALID_PARAMETER
;
542 TRACE("ScControlService() called\n");
543 TRACE("Size: %lu\n", ControlPacket
->dwSize
);
544 TRACE("Service: %S\n", (PWSTR
)((PBYTE
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
));
546 if (lpService
->HandlerFunction
)
548 (lpService
->HandlerFunction
)(ControlPacket
->dwControl
);
550 else if (lpService
->HandlerFunctionEx
)
552 /* FIXME: send correct params */
553 (lpService
->HandlerFunctionEx
)(ControlPacket
->dwControl
, 0, NULL
, NULL
);
556 TRACE("ScControlService() done\n");
558 return ERROR_SUCCESS
;
563 ScServiceDispatcher(HANDLE hPipe
,
564 PSCM_CONTROL_PACKET ControlPacket
,
569 DWORD dwRunningServices
= 0;
570 LPWSTR lpServiceName
;
571 PACTIVE_SERVICE lpService
;
572 SCM_REPLY_PACKET ReplyPacket
;
575 TRACE("ScDispatcherLoop() called\n");
577 if (ControlPacket
== NULL
|| dwBufferSize
< sizeof(SCM_CONTROL_PACKET
))
582 /* Read command from the control pipe */
583 bResult
= ReadFile(hPipe
,
588 if (bResult
== FALSE
)
590 ERR("Pipe read failed (Error: %lu)\n", GetLastError());
594 lpServiceName
= (LPWSTR
)((PBYTE
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
);
595 TRACE("Service: %S\n", lpServiceName
);
597 if (ControlPacket
->dwControl
== SERVICE_CONTROL_START_OWN
)
598 lpActiveServices
[0].bOwnProcess
= TRUE
;
600 lpService
= ScLookupServiceByServiceName(lpServiceName
);
601 if (lpService
!= NULL
)
603 /* Execute command */
604 switch (ControlPacket
->dwControl
)
606 case SERVICE_CONTROL_START_SHARE
:
607 case SERVICE_CONTROL_START_OWN
:
608 TRACE("Start command - received SERVICE_CONTROL_START\n");
609 dwError
= ScStartService(lpService
, ControlPacket
);
610 if (dwError
== ERROR_SUCCESS
)
614 case SERVICE_CONTROL_STOP
:
615 TRACE("Stop command - received SERVICE_CONTROL_STOP\n");
616 dwError
= ScControlService(lpService
, ControlPacket
);
617 if (dwError
== ERROR_SUCCESS
)
622 TRACE("Command %lu received", ControlPacket
->dwControl
);
623 dwError
= ScControlService(lpService
, ControlPacket
);
629 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
632 ReplyPacket
.dwError
= dwError
;
634 /* Send the reply packet */
635 bResult
= WriteFile(hPipe
,
640 if (bResult
== FALSE
)
642 ERR("Pipe write failed (Error: %lu)\n", GetLastError());
646 if (dwRunningServices
== 0)
654 /**********************************************************************
655 * RegisterServiceCtrlHandlerA
659 SERVICE_STATUS_HANDLE WINAPI
660 RegisterServiceCtrlHandlerA(LPCSTR lpServiceName
,
661 LPHANDLER_FUNCTION lpHandlerProc
)
663 ANSI_STRING ServiceNameA
;
664 UNICODE_STRING ServiceNameU
;
665 SERVICE_STATUS_HANDLE SHandle
;
667 RtlInitAnsiString(&ServiceNameA
, (LPSTR
)lpServiceName
);
668 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU
, &ServiceNameA
, TRUE
)))
670 SetLastError(ERROR_OUTOFMEMORY
);
671 return (SERVICE_STATUS_HANDLE
)0;
674 SHandle
= RegisterServiceCtrlHandlerW(ServiceNameU
.Buffer
,
677 RtlFreeUnicodeString(&ServiceNameU
);
683 /**********************************************************************
684 * RegisterServiceCtrlHandlerW
688 SERVICE_STATUS_HANDLE WINAPI
689 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName
,
690 LPHANDLER_FUNCTION lpHandlerProc
)
692 PACTIVE_SERVICE Service
;
694 Service
= ScLookupServiceByServiceName((LPWSTR
)lpServiceName
);
697 return (SERVICE_STATUS_HANDLE
)NULL
;
700 Service
->HandlerFunction
= lpHandlerProc
;
701 Service
->HandlerFunctionEx
= NULL
;
703 TRACE("RegisterServiceCtrlHandler returning %lu\n", Service
->hServiceStatus
);
705 return Service
->hServiceStatus
;
709 /**********************************************************************
710 * RegisterServiceCtrlHandlerExA
714 SERVICE_STATUS_HANDLE WINAPI
715 RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName
,
716 LPHANDLER_FUNCTION_EX lpHandlerProc
,
719 ANSI_STRING ServiceNameA
;
720 UNICODE_STRING ServiceNameU
;
721 SERVICE_STATUS_HANDLE SHandle
;
723 RtlInitAnsiString(&ServiceNameA
, (LPSTR
)lpServiceName
);
724 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU
, &ServiceNameA
, TRUE
)))
726 SetLastError(ERROR_OUTOFMEMORY
);
727 return (SERVICE_STATUS_HANDLE
)0;
730 SHandle
= RegisterServiceCtrlHandlerExW(ServiceNameU
.Buffer
,
734 RtlFreeUnicodeString(&ServiceNameU
);
740 /**********************************************************************
741 * RegisterServiceCtrlHandlerExW
745 SERVICE_STATUS_HANDLE WINAPI
746 RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName
,
747 LPHANDLER_FUNCTION_EX lpHandlerProc
,
750 PACTIVE_SERVICE Service
;
752 Service
= ScLookupServiceByServiceName(lpServiceName
);
755 return (SERVICE_STATUS_HANDLE
)NULL
;
758 Service
->HandlerFunction
= NULL
;
759 Service
->HandlerFunctionEx
= lpHandlerProc
;
760 Service
->HandlerContext
= lpContext
;
762 TRACE("RegisterServiceCtrlHandlerEx returning %lu\n", Service
->hServiceStatus
);
764 return Service
->hServiceStatus
;
768 /**********************************************************************
769 * I_ScSetServiceBitsA
776 I_ScSetServiceBitsA(SERVICE_STATUS_HANDLE hServiceStatus
,
779 BOOL bUpdateImmediately
,
786 /* Call to services.exe using RPC */
787 bResult
= RI_ScSetServiceBitsA((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
793 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
795 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
804 /**********************************************************************
805 * I_ScSetServiceBitsW
812 I_ScSetServiceBitsW(SERVICE_STATUS_HANDLE hServiceStatus
,
815 BOOL bUpdateImmediately
,
822 /* Call to services.exe using RPC */
823 bResult
= RI_ScSetServiceBitsW((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
829 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
831 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
840 /**********************************************************************
846 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus
,
849 BOOL bUpdateImmediately
)
851 return I_ScSetServiceBitsW(hServiceStatus
,
859 /**********************************************************************
865 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus
,
866 LPSERVICE_STATUS lpServiceStatus
)
870 TRACE("SetServiceStatus() called\n");
871 TRACE("hServiceStatus %lu\n", hServiceStatus
);
875 /* Call to services.exe using RPC */
876 dwError
= RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
879 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
881 dwError
= ScmRpcStatusToWinError(RpcExceptionCode());
885 if (dwError
!= ERROR_SUCCESS
)
887 ERR("ScmrSetServiceStatus() failed (Error %lu)\n", dwError
);
888 SetLastError(dwError
);
892 TRACE("SetServiceStatus() done (ret %lu)\n", dwError
);
898 /**********************************************************************
899 * StartServiceCtrlDispatcherA
904 StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA
*lpServiceStartTable
)
909 PSCM_CONTROL_PACKET ControlPacket
;
913 TRACE("StartServiceCtrlDispatcherA() called\n");
916 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
921 dwActiveServiceCount
= i
;
922 lpActiveServices
= RtlAllocateHeap(RtlGetProcessHeap(),
924 dwActiveServiceCount
* sizeof(ACTIVE_SERVICE
));
925 if (lpActiveServices
== NULL
)
930 /* Copy service names and start procedure */
931 for (i
= 0; i
< dwActiveServiceCount
; i
++)
933 RtlCreateUnicodeStringFromAsciiz(&lpActiveServices
[i
].ServiceName
,
934 lpServiceStartTable
[i
].lpServiceName
);
935 lpActiveServices
[i
].ServiceMain
.A
= lpServiceStartTable
[i
].lpServiceProc
;
936 lpActiveServices
[i
].hServiceStatus
= 0;
937 lpActiveServices
[i
].bUnicode
= FALSE
;
938 lpActiveServices
[i
].bOwnProcess
= FALSE
;
941 dwError
= ScConnectControlPipe(&hPipe
);
942 if (dwError
!= ERROR_SUCCESS
)
948 dwBufSize
= sizeof(SCM_CONTROL_PACKET
) +
949 (MAX_SERVICE_NAME_LENGTH
+ 1) * sizeof(WCHAR
);
951 ControlPacket
= RtlAllocateHeap(RtlGetProcessHeap(),
954 if (ControlPacket
== NULL
)
960 ScCreateStatusBinding();
962 ScServiceDispatcher(hPipe
, ControlPacket
, dwBufSize
);
964 ScDestroyStatusBinding();
968 /* Free the control packet */
969 RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket
);
972 /* Free the service table */
973 for (i
= 0; i
< dwActiveServiceCount
; i
++)
975 RtlFreeUnicodeString(&lpActiveServices
[i
].ServiceName
);
977 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
978 lpActiveServices
= NULL
;
979 dwActiveServiceCount
= 0;
985 /**********************************************************************
986 * StartServiceCtrlDispatcherW
991 StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW
*lpServiceStartTable
)
996 PSCM_CONTROL_PACKET ControlPacket
;
1000 TRACE("StartServiceCtrlDispatcherW() called\n");
1003 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
1008 dwActiveServiceCount
= i
;
1009 lpActiveServices
= RtlAllocateHeap(RtlGetProcessHeap(),
1011 dwActiveServiceCount
* sizeof(ACTIVE_SERVICE
));
1012 if (lpActiveServices
== NULL
)
1017 /* Copy service names and start procedure */
1018 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1020 RtlCreateUnicodeString(&lpActiveServices
[i
].ServiceName
,
1021 lpServiceStartTable
[i
].lpServiceName
);
1022 lpActiveServices
[i
].ServiceMain
.W
= lpServiceStartTable
[i
].lpServiceProc
;
1023 lpActiveServices
[i
].hServiceStatus
= 0;
1024 lpActiveServices
[i
].bUnicode
= TRUE
;
1025 lpActiveServices
[i
].bOwnProcess
= FALSE
;
1028 dwError
= ScConnectControlPipe(&hPipe
);
1029 if (dwError
!= ERROR_SUCCESS
)
1035 dwBufSize
= sizeof(SCM_CONTROL_PACKET
) +
1036 (MAX_SERVICE_NAME_LENGTH
+ 1) * sizeof(WCHAR
);
1038 ControlPacket
= RtlAllocateHeap(RtlGetProcessHeap(),
1041 if (ControlPacket
== NULL
)
1047 ScCreateStatusBinding();
1049 ScServiceDispatcher(hPipe
, ControlPacket
, dwBufSize
);
1051 ScDestroyStatusBinding();
1055 /* Free the control packet */
1056 RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket
);
1059 /* Free the service table */
1060 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1062 RtlFreeUnicodeString(&lpActiveServices
[i
].ServiceName
);
1064 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
1065 lpActiveServices
= NULL
;
1066 dwActiveServiceCount
= 0;