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_service
);
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()\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()\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
;
139 ScLookupServiceByServiceName(IN LPCWSTR lpServiceName
,
140 OUT PACTIVE_SERVICE
* pService
)
144 TRACE("ScLookupServiceByServiceName(%S)\n",
147 if (lpActiveServices
[0].bOwnProcess
)
149 *pService
= &lpActiveServices
[0];
150 return ERROR_SUCCESS
;
153 for (i
= 0; i
< dwActiveServiceCount
; i
++)
155 TRACE("Checking %S\n", lpActiveServices
[i
].ServiceName
.Buffer
);
156 if (_wcsicmp(lpActiveServices
[i
].ServiceName
.Buffer
, lpServiceName
) == 0)
159 *pService
= &lpActiveServices
[i
];
160 return ERROR_SUCCESS
;
164 TRACE("No service found!\n");
166 return ERROR_SERVICE_NOT_IN_EXE
;
171 ScServiceMainStubA(LPVOID Context
)
173 PSERVICE_THREAD_PARAMSA ThreadParams
= Context
;
175 TRACE("ScServiceMainStubA(%p)\n", Context
);
177 /* Call the main service routine and free the arguments vector */
178 (ThreadParams
->lpServiceMain
)(ThreadParams
->dwArgCount
,
179 ThreadParams
->lpArgVector
);
181 if (ThreadParams
->lpArgVector
!= NULL
)
183 HeapFree(GetProcessHeap(), 0, ThreadParams
->lpArgVector
);
185 HeapFree(GetProcessHeap(), 0, ThreadParams
);
187 return ERROR_SUCCESS
;
192 ScServiceMainStubW(LPVOID Context
)
194 PSERVICE_THREAD_PARAMSW ThreadParams
= Context
;
196 TRACE("ScServiceMainStubW(%p)\n", Context
);
198 /* Call the main service routine and free the arguments vector */
199 (ThreadParams
->lpServiceMain
)(ThreadParams
->dwArgCount
,
200 ThreadParams
->lpArgVector
);
202 if (ThreadParams
->lpArgVector
!= NULL
)
204 HeapFree(GetProcessHeap(), 0, ThreadParams
->lpArgVector
);
206 HeapFree(GetProcessHeap(), 0, ThreadParams
);
208 return ERROR_SUCCESS
;
213 ScConnectControlPipe(HANDLE
*hPipe
)
215 DWORD dwBytesWritten
;
217 DWORD dwServiceCurrent
= 0;
219 WCHAR NtControlPipeName
[MAX_PATH
+ 1];
220 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
223 TRACE("ScConnectControlPipe(%p)\n",
226 /* Get the service number and create the named pipe */
227 RtlZeroMemory(&QueryTable
,
230 QueryTable
[0].Name
= L
"";
231 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
232 QueryTable
[0].EntryContext
= &dwServiceCurrent
;
234 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
239 if (!NT_SUCCESS(Status
))
241 ERR("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
242 return RtlNtStatusToDosError(Status
);
245 swprintf(NtControlPipeName
, L
"\\\\.\\pipe\\net\\NtControlPipe%u", dwServiceCurrent
);
247 if (!WaitNamedPipeW(NtControlPipeName
, 30000))
249 ERR("WaitNamedPipe(%S) failed (Error %lu)\n", NtControlPipeName
, GetLastError());
250 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
253 *hPipe
= CreateFileW(NtControlPipeName
,
254 GENERIC_READ
| GENERIC_WRITE
,
255 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
258 FILE_ATTRIBUTE_NORMAL
,
260 if (*hPipe
== INVALID_HANDLE_VALUE
)
262 ERR("CreateFileW() failed for pipe %S (Error %lu)\n", NtControlPipeName
, GetLastError());
263 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
266 dwState
= PIPE_READMODE_MESSAGE
;
267 if (!SetNamedPipeHandleState(*hPipe
, &dwState
, NULL
, NULL
))
270 *hPipe
= INVALID_HANDLE_VALUE
;
271 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
274 /* Pass the ProcessId to the SCM */
275 dwProcessId
= GetCurrentProcessId();
282 TRACE("Sent Process ID %lu\n", dwProcessId
);
284 return ERROR_SUCCESS
;
289 * Ansi/Unicode argument layout of the vector passed to a service at startup,
290 * depending on the different versions of Windows considered:
293 * [argv array of pointers][parameter 1][parameter 2]...[service name]
296 * [argv array of pointers][align to 8 bytes]
297 * [parameter 1][parameter 2]...[service name]
300 * [argv array of pointers][service name]
301 * [parameter 1][align to 4 bytes][parameter 2][align to 4 bytes]...
303 * Space for parameters and service name is always enough to store
304 * both the Ansi and the Unicode versions including NULL terminator.
308 ScBuildUnicodeArgsVector(PSCM_CONTROL_PACKET ControlPacket
,
310 LPWSTR
**lpArgVector
)
313 PWSTR pszServiceName
;
319 if (ControlPacket
== NULL
|| lpArgCount
== NULL
|| lpArgVector
== NULL
)
320 return ERROR_INVALID_PARAMETER
;
325 /* Retrieve and count the start command line (NULL-terminated) */
326 pszServiceName
= (PWSTR
)((ULONG_PTR
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
);
327 cbServiceName
= lstrlenW(pszServiceName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
330 * The total size of the argument vector is equal to the entry for
331 * the service name, plus the size of the original argument vector.
333 cbTotal
= sizeof(PWSTR
) + cbServiceName
;
334 if (ControlPacket
->dwArgumentsCount
> 0)
335 cbArguments
= ControlPacket
->dwSize
- ControlPacket
->dwArgumentsOffset
;
338 cbTotal
+= cbArguments
;
340 /* Allocate the new argument vector */
341 lpVector
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbTotal
);
342 if (lpVector
== NULL
)
343 return ERROR_NOT_ENOUGH_MEMORY
;
346 * The first argument is reserved for the service name, which
347 * will be appended to the end of the argument string list.
350 /* Copy the remaining arguments */
351 if (ControlPacket
->dwArgumentsCount
> 0)
354 (PWSTR
)((ULONG_PTR
)ControlPacket
+ ControlPacket
->dwArgumentsOffset
),
357 for (i
= 0; i
< ControlPacket
->dwArgumentsCount
; i
++)
359 lpVector
[i
+ 1] = (PWSTR
)((ULONG_PTR
)&lpVector
[1] + (ULONG_PTR
)lpVector
[i
+ 1]);
360 TRACE("Unicode lpVector[%lu] = '%ls'\n", i
+ 1, lpVector
[i
+ 1]);
364 /* Now copy the service name */
365 lpVector
[0] = (PWSTR
)((ULONG_PTR
)&lpVector
[1] + cbArguments
);
366 memcpy(lpVector
[0], pszServiceName
, cbServiceName
);
367 TRACE("Unicode lpVector[%lu] = '%ls'\n", 0, lpVector
[0]);
369 *lpArgCount
= ControlPacket
->dwArgumentsCount
+ 1;
370 *lpArgVector
= lpVector
;
372 return ERROR_SUCCESS
;
377 ScBuildAnsiArgsVector(PSCM_CONTROL_PACKET ControlPacket
,
386 UNICODE_STRING UnicodeString
;
387 ANSI_STRING AnsiString
;
389 if (ControlPacket
== NULL
|| lpArgCount
== NULL
|| lpArgVector
== NULL
)
390 return ERROR_INVALID_PARAMETER
;
395 /* Build the UNICODE arguments vector */
396 dwError
= ScBuildUnicodeArgsVector(ControlPacket
, &ArgCount
, &lpVectorW
);
397 if (dwError
!= ERROR_SUCCESS
)
400 /* Convert the vector to ANSI in place */
401 lpVectorA
= (PSTR
*)lpVectorW
;
402 for (i
= 0; i
< ArgCount
; i
++)
404 RtlInitUnicodeString(&UnicodeString
, lpVectorW
[i
]);
405 RtlInitEmptyAnsiString(&AnsiString
, lpVectorA
[i
], UnicodeString
.MaximumLength
);
406 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, FALSE
);
407 if (!NT_SUCCESS(Status
))
409 /* Failed to convert to ANSI; free the allocated vector and return */
410 dwError
= RtlNtStatusToDosError(Status
);
411 HeapFree(GetProcessHeap(), 0, lpVectorW
);
415 /* NULL-terminate the string */
416 AnsiString
.Buffer
[AnsiString
.Length
/ sizeof(CHAR
)] = ANSI_NULL
;
418 TRACE("Ansi lpVector[%lu] = '%s'\n", i
, lpVectorA
[i
]);
421 *lpArgCount
= ArgCount
;
422 *lpArgVector
= lpVectorA
;
424 return ERROR_SUCCESS
;
429 ScStartService(PACTIVE_SERVICE lpService
,
430 PSCM_CONTROL_PACKET ControlPacket
)
435 PSERVICE_THREAD_PARAMSA ThreadParamsA
;
436 PSERVICE_THREAD_PARAMSW ThreadParamsW
;
438 TRACE("ScStartService(%p %p)\n",
439 lpService
, ControlPacket
);
441 if (lpService
== NULL
|| ControlPacket
== NULL
)
442 return ERROR_INVALID_PARAMETER
;
444 TRACE("Size: %lu\n", ControlPacket
->dwSize
);
445 TRACE("Service: %S\n", (PWSTR
)((ULONG_PTR
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
));
447 /* Set the service status handle */
448 lpService
->hServiceStatus
= ControlPacket
->hServiceStatus
;
450 /* Build the arguments vector */
451 if (lpService
->bUnicode
!= FALSE
)
453 ThreadParamsW
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ThreadParamsW
));
454 if (ThreadParamsW
== NULL
)
455 return ERROR_NOT_ENOUGH_MEMORY
;
456 dwError
= ScBuildUnicodeArgsVector(ControlPacket
,
457 &ThreadParamsW
->dwArgCount
,
458 &ThreadParamsW
->lpArgVector
);
459 if (dwError
!= ERROR_SUCCESS
)
461 HeapFree(GetProcessHeap(), 0, ThreadParamsW
);
464 ThreadParamsW
->lpServiceMain
= lpService
->ServiceMain
.W
;
465 ThreadHandle
= CreateThread(NULL
,
471 if (ThreadHandle
== NULL
)
473 if (ThreadParamsW
->lpArgVector
!= NULL
)
475 HeapFree(GetProcessHeap(), 0, ThreadParamsW
->lpArgVector
);
477 HeapFree(GetProcessHeap(), 0, ThreadParamsW
);
479 return ERROR_SERVICE_NO_THREAD
;
482 CloseHandle(ThreadHandle
);
486 ThreadParamsA
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ThreadParamsA
));
487 if (ThreadParamsA
== NULL
)
488 return ERROR_NOT_ENOUGH_MEMORY
;
489 dwError
= ScBuildAnsiArgsVector(ControlPacket
,
490 &ThreadParamsA
->dwArgCount
,
491 &ThreadParamsA
->lpArgVector
);
492 if (dwError
!= ERROR_SUCCESS
)
494 HeapFree(GetProcessHeap(), 0, ThreadParamsA
);
497 ThreadParamsA
->lpServiceMain
= lpService
->ServiceMain
.A
;
498 ThreadHandle
= CreateThread(NULL
,
504 if (ThreadHandle
== NULL
)
506 if (ThreadParamsA
->lpArgVector
!= NULL
)
508 HeapFree(GetProcessHeap(), 0, ThreadParamsA
->lpArgVector
);
510 HeapFree(GetProcessHeap(), 0, ThreadParamsA
);
512 return ERROR_SERVICE_NO_THREAD
;
515 CloseHandle(ThreadHandle
);
518 return ERROR_SUCCESS
;
523 ScControlService(PACTIVE_SERVICE lpService
,
524 PSCM_CONTROL_PACKET ControlPacket
)
528 TRACE("ScControlService(%p %p)\n",
529 lpService
, ControlPacket
);
531 if (lpService
== NULL
|| ControlPacket
== NULL
)
532 return ERROR_INVALID_PARAMETER
;
534 TRACE("Size: %lu\n", ControlPacket
->dwSize
);
535 TRACE("Service: %S\n", (PWSTR
)((ULONG_PTR
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
));
537 if (lpService
->HandlerFunction
)
539 (lpService
->HandlerFunction
)(ControlPacket
->dwControl
);
540 dwError
= ERROR_SUCCESS
;
542 else if (lpService
->HandlerFunctionEx
)
544 /* FIXME: Send correct 2nd and 3rd parameters */
545 dwError
= (lpService
->HandlerFunctionEx
)(ControlPacket
->dwControl
,
547 lpService
->HandlerContext
);
550 TRACE("ScControlService() done (Error %lu)\n", dwError
);
557 ScServiceDispatcher(HANDLE hPipe
,
558 PSCM_CONTROL_PACKET ControlPacket
,
563 BOOL bRunning
= TRUE
;
564 LPWSTR lpServiceName
;
565 PACTIVE_SERVICE lpService
;
566 SCM_REPLY_PACKET ReplyPacket
;
569 TRACE("ScServiceDispatcher(%p %p %lu)\n",
570 hPipe
, ControlPacket
, dwBufferSize
);
572 if (ControlPacket
== NULL
|| dwBufferSize
< sizeof(SCM_CONTROL_PACKET
))
577 /* Read command from the control pipe */
578 bResult
= ReadFile(hPipe
,
583 if (bResult
== FALSE
)
585 ERR("Pipe read failed (Error: %lu)\n", GetLastError());
589 lpServiceName
= (LPWSTR
)((PBYTE
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
);
590 TRACE("Service: %S\n", lpServiceName
);
592 if (lpServiceName
[0] == UNICODE_NULL
)
594 ERR("Stop dispatcher thread\n");
596 dwError
= ERROR_SUCCESS
;
600 if (ControlPacket
->dwControl
== SERVICE_CONTROL_START_OWN
)
601 lpActiveServices
[0].bOwnProcess
= TRUE
;
603 dwError
= ScLookupServiceByServiceName(lpServiceName
, &lpService
);
604 if ((dwError
== ERROR_SUCCESS
) && (lpService
!= NULL
))
606 /* Execute command */
607 switch (ControlPacket
->dwControl
)
609 case SERVICE_CONTROL_START_SHARE
:
610 case SERVICE_CONTROL_START_OWN
:
611 TRACE("Start command - received SERVICE_CONTROL_START\n");
612 dwError
= ScStartService(lpService
, ControlPacket
);
615 case SERVICE_CONTROL_STOP
:
616 TRACE("Stop command - received SERVICE_CONTROL_STOP\n");
617 dwError
= ScControlService(lpService
, ControlPacket
);
621 TRACE("Command %lu received", ControlPacket
->dwControl
);
622 dwError
= ScControlService(lpService
, ControlPacket
);
628 ReplyPacket
.dwError
= dwError
;
630 /* Send the reply packet */
631 bResult
= WriteFile(hPipe
,
636 if (bResult
== FALSE
)
638 ERR("Pipe write failed (Error: %lu)\n", GetLastError());
647 /**********************************************************************
648 * RegisterServiceCtrlHandlerA
652 SERVICE_STATUS_HANDLE WINAPI
653 RegisterServiceCtrlHandlerA(LPCSTR lpServiceName
,
654 LPHANDLER_FUNCTION lpHandlerProc
)
656 ANSI_STRING ServiceNameA
;
657 UNICODE_STRING ServiceNameU
;
658 SERVICE_STATUS_HANDLE hServiceStatus
;
660 TRACE("RegisterServiceCtrlHandlerA(%s %p %p)\n",
661 debugstr_a(lpServiceName
), lpHandlerProc
);
663 RtlInitAnsiString(&ServiceNameA
, lpServiceName
);
664 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU
, &ServiceNameA
, TRUE
)))
666 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
670 hServiceStatus
= RegisterServiceCtrlHandlerW(ServiceNameU
.Buffer
,
673 RtlFreeUnicodeString(&ServiceNameU
);
675 return hServiceStatus
;
679 /**********************************************************************
680 * RegisterServiceCtrlHandlerW
684 SERVICE_STATUS_HANDLE WINAPI
685 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName
,
686 LPHANDLER_FUNCTION lpHandlerProc
)
689 PACTIVE_SERVICE Service
;
691 TRACE("RegisterServiceCtrlHandlerW(%s %p %p)\n",
692 debugstr_w(lpServiceName
), lpHandlerProc
);
694 dwError
= ScLookupServiceByServiceName(lpServiceName
, &Service
);
695 if ((dwError
!= ERROR_SUCCESS
) || (Service
== NULL
))
697 SetLastError(dwError
);
703 SetLastError(ERROR_INVALID_PARAMETER
);
707 Service
->HandlerFunction
= lpHandlerProc
;
708 Service
->HandlerFunctionEx
= NULL
;
710 TRACE("RegisterServiceCtrlHandler returning %p\n", Service
->hServiceStatus
);
712 return Service
->hServiceStatus
;
716 /**********************************************************************
717 * RegisterServiceCtrlHandlerExA
721 SERVICE_STATUS_HANDLE WINAPI
722 RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName
,
723 LPHANDLER_FUNCTION_EX lpHandlerProc
,
726 ANSI_STRING ServiceNameA
;
727 UNICODE_STRING ServiceNameU
;
728 SERVICE_STATUS_HANDLE hServiceStatus
;
730 TRACE("RegisterServiceCtrlHandlerExA(%s %p %p)\n",
731 debugstr_a(lpServiceName
), lpHandlerProc
, lpContext
);
733 RtlInitAnsiString(&ServiceNameA
, lpServiceName
);
734 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU
, &ServiceNameA
, TRUE
)))
736 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
740 hServiceStatus
= RegisterServiceCtrlHandlerExW(ServiceNameU
.Buffer
,
744 RtlFreeUnicodeString(&ServiceNameU
);
746 return hServiceStatus
;
750 /**********************************************************************
751 * RegisterServiceCtrlHandlerExW
755 SERVICE_STATUS_HANDLE WINAPI
756 RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName
,
757 LPHANDLER_FUNCTION_EX lpHandlerProc
,
761 PACTIVE_SERVICE Service
;
763 TRACE("RegisterServiceCtrlHandlerExW(%s %p %p)\n",
764 debugstr_w(lpServiceName
), lpHandlerProc
, lpContext
);
766 dwError
= ScLookupServiceByServiceName(lpServiceName
, &Service
);
767 if ((dwError
!= ERROR_SUCCESS
) || (Service
== NULL
))
769 SetLastError(dwError
);
775 SetLastError(ERROR_INVALID_PARAMETER
);
779 Service
->HandlerFunction
= NULL
;
780 Service
->HandlerFunctionEx
= lpHandlerProc
;
781 Service
->HandlerContext
= lpContext
;
783 TRACE("RegisterServiceCtrlHandlerEx returning 0x%p\n", Service
->hServiceStatus
);
785 return Service
->hServiceStatus
;
789 /**********************************************************************
790 * I_ScIsSecurityProcess
798 I_ScIsSecurityProcess(VOID
)
800 FIXME("I_ScIsSecurityProcess()\n");
804 /**********************************************************************
805 * I_ScPnPGetServiceName
813 I_ScPnPGetServiceName(IN SERVICE_STATUS_HANDLE hServiceStatus
,
814 OUT LPWSTR lpServiceName
,
815 IN DWORD cchServiceName
)
819 TRACE("I_ScPnPGetServiceName(%lu %p %lu)\n",
820 hServiceStatus
, lpServiceName
, cchServiceName
);
822 for (i
= 0; i
< dwActiveServiceCount
; i
++)
824 if (lpActiveServices
[i
].hServiceStatus
== hServiceStatus
)
826 wcscpy(lpServiceName
, lpActiveServices
[i
].ServiceName
.Buffer
);
827 return ERROR_SUCCESS
;
831 return ERROR_SERVICE_NOT_IN_EXE
;
835 /**********************************************************************
836 * I_ScSetServiceBitsA
843 I_ScSetServiceBitsA(SERVICE_STATUS_HANDLE hServiceStatus
,
846 BOOL bUpdateImmediately
,
851 TRACE("I_ScSetServiceBitsA(%lu %lx %u %u %s)\n",
852 hServiceStatus
, dwServiceBits
, bSetBitsOn
, bUpdateImmediately
,
853 debugstr_a(lpString
));
857 bResult
= RI_ScSetServiceBitsA((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
863 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
865 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
874 /**********************************************************************
875 * I_ScSetServiceBitsW
882 I_ScSetServiceBitsW(SERVICE_STATUS_HANDLE hServiceStatus
,
885 BOOL bUpdateImmediately
,
890 TRACE("I_ScSetServiceBitsW(%lu %lx %u %u %s)\n",
891 hServiceStatus
, dwServiceBits
, bSetBitsOn
, bUpdateImmediately
,
892 debugstr_w(lpString
));
896 bResult
= RI_ScSetServiceBitsW((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
902 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
904 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
913 /**********************************************************************
919 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus
,
922 BOOL bUpdateImmediately
)
924 TRACE("SetServiceBits(%lu %lx %u %u)\n",
925 hServiceStatus
, dwServiceBits
, bSetBitsOn
, bUpdateImmediately
);
927 return I_ScSetServiceBitsW(hServiceStatus
,
935 /**********************************************************************
941 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus
,
942 LPSERVICE_STATUS lpServiceStatus
)
946 TRACE("SetServiceStatus(%lu %p)\n",
947 hServiceStatus
, lpServiceStatus
);
951 dwError
= RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
954 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
956 dwError
= ScmRpcStatusToWinError(RpcExceptionCode());
960 if (dwError
!= ERROR_SUCCESS
)
962 ERR("RSetServiceStatus() failed (Error %lu)\n", dwError
);
963 SetLastError(dwError
);
967 TRACE("SetServiceStatus() done\n");
973 /**********************************************************************
974 * StartServiceCtrlDispatcherA
979 StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA
*lpServiceStartTable
)
984 PSCM_CONTROL_PACKET ControlPacket
;
988 TRACE("StartServiceCtrlDispatcherA(%p)\n",
989 lpServiceStartTable
);
992 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
997 dwActiveServiceCount
= i
;
999 /* Initialize the service table */
1000 lpActiveServices
= RtlAllocateHeap(RtlGetProcessHeap(),
1002 dwActiveServiceCount
* sizeof(ACTIVE_SERVICE
));
1003 if (lpActiveServices
== NULL
)
1005 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1009 /* Copy service names and start procedure */
1010 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1012 RtlCreateUnicodeStringFromAsciiz(&lpActiveServices
[i
].ServiceName
,
1013 lpServiceStartTable
[i
].lpServiceName
);
1014 lpActiveServices
[i
].ServiceMain
.A
= lpServiceStartTable
[i
].lpServiceProc
;
1015 lpActiveServices
[i
].hServiceStatus
= NULL
;
1016 lpActiveServices
[i
].bUnicode
= FALSE
;
1017 lpActiveServices
[i
].bOwnProcess
= FALSE
;
1020 /* Initialize the connection to the SCM */
1022 dwError
= ScConnectControlPipe(&hPipe
);
1023 if (dwError
!= ERROR_SUCCESS
)
1029 dwBufSize
= sizeof(SCM_CONTROL_PACKET
) +
1030 (MAX_SERVICE_NAME_LENGTH
+ 1) * sizeof(WCHAR
);
1032 ControlPacket
= RtlAllocateHeap(RtlGetProcessHeap(),
1035 if (ControlPacket
== NULL
)
1037 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1042 ScCreateStatusBinding();
1044 /* Start the dispatcher loop */
1045 ScServiceDispatcher(hPipe
, ControlPacket
, dwBufSize
);
1047 /* Close the connection */
1048 ScDestroyStatusBinding();
1051 /* Free the control packet */
1052 RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket
);
1055 /* Free the service table */
1056 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1058 RtlFreeUnicodeString(&lpActiveServices
[i
].ServiceName
);
1060 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
1061 lpActiveServices
= NULL
;
1062 dwActiveServiceCount
= 0;
1064 if (!bRet
) SetLastError(dwError
);
1070 /**********************************************************************
1071 * StartServiceCtrlDispatcherW
1076 StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW
*lpServiceStartTable
)
1081 PSCM_CONTROL_PACKET ControlPacket
;
1085 TRACE("StartServiceCtrlDispatcherW(%p)\n",
1086 lpServiceStartTable
);
1089 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
1094 dwActiveServiceCount
= i
;
1096 /* Initialize the service table */
1097 lpActiveServices
= RtlAllocateHeap(RtlGetProcessHeap(),
1099 dwActiveServiceCount
* sizeof(ACTIVE_SERVICE
));
1100 if (lpActiveServices
== NULL
)
1102 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1106 /* Copy service names and start procedure */
1107 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1109 RtlCreateUnicodeString(&lpActiveServices
[i
].ServiceName
,
1110 lpServiceStartTable
[i
].lpServiceName
);
1111 lpActiveServices
[i
].ServiceMain
.W
= lpServiceStartTable
[i
].lpServiceProc
;
1112 lpActiveServices
[i
].hServiceStatus
= NULL
;
1113 lpActiveServices
[i
].bUnicode
= TRUE
;
1114 lpActiveServices
[i
].bOwnProcess
= FALSE
;
1117 /* Initialize the connection to the SCM */
1119 dwError
= ScConnectControlPipe(&hPipe
);
1120 if (dwError
!= ERROR_SUCCESS
)
1126 dwBufSize
= sizeof(SCM_CONTROL_PACKET
) +
1127 (MAX_SERVICE_NAME_LENGTH
+ 1) * sizeof(WCHAR
);
1129 ControlPacket
= RtlAllocateHeap(RtlGetProcessHeap(),
1132 if (ControlPacket
== NULL
)
1134 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1139 ScCreateStatusBinding();
1141 /* Start the dispatcher loop */
1142 ScServiceDispatcher(hPipe
, ControlPacket
, dwBufSize
);
1144 /* Close the connection */
1145 ScDestroyStatusBinding();
1148 /* Free the control packet */
1149 RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket
);
1152 /* Free the service table */
1153 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1155 RtlFreeUnicodeString(&lpActiveServices
[i
].ServiceName
);
1157 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
1158 lpActiveServices
= NULL
;
1159 dwActiveServiceCount
= 0;
1161 if (!bRet
) SetLastError(dwError
);