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()\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
;
138 static PACTIVE_SERVICE
139 ScLookupServiceByServiceName(LPCWSTR lpServiceName
)
143 TRACE("ScLookupServiceByServiceName(%S)\n",
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");
165 ScServiceMainStubA(LPVOID Context
)
167 PSERVICE_THREAD_PARAMSA ThreadParams
= Context
;
169 TRACE("ScServiceMainStubA(%p)\n", Context
);
171 /* Call the main service routine and free the arguments vector */
172 (ThreadParams
->lpServiceMain
)(ThreadParams
->dwArgCount
,
173 ThreadParams
->lpArgVector
);
175 if (ThreadParams
->lpArgVector
!= NULL
)
177 HeapFree(GetProcessHeap(), 0, ThreadParams
->lpArgVector
);
179 HeapFree(GetProcessHeap(), 0, ThreadParams
);
181 return ERROR_SUCCESS
;
186 ScServiceMainStubW(LPVOID Context
)
188 PSERVICE_THREAD_PARAMSW ThreadParams
= Context
;
190 TRACE("ScServiceMainStubW(%p)\n", Context
);
192 /* Call the main service routine and free the arguments vector */
193 (ThreadParams
->lpServiceMain
)(ThreadParams
->dwArgCount
,
194 ThreadParams
->lpArgVector
);
196 if (ThreadParams
->lpArgVector
!= NULL
)
198 HeapFree(GetProcessHeap(), 0, ThreadParams
->lpArgVector
);
200 HeapFree(GetProcessHeap(), 0, ThreadParams
);
202 return ERROR_SUCCESS
;
207 ScConnectControlPipe(HANDLE
*hPipe
)
209 DWORD dwBytesWritten
;
211 DWORD dwServiceCurrent
= 0;
213 WCHAR NtControlPipeName
[MAX_PATH
+ 1];
214 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
217 TRACE("ScConnectControlPipe(%p)\n",
220 /* Get the service number and create the named pipe */
221 RtlZeroMemory(&QueryTable
,
224 QueryTable
[0].Name
= L
"";
225 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
226 QueryTable
[0].EntryContext
= &dwServiceCurrent
;
228 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
233 if (!NT_SUCCESS(Status
))
235 ERR("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
236 return RtlNtStatusToDosError(Status
);
239 swprintf(NtControlPipeName
, L
"\\\\.\\pipe\\net\\NtControlPipe%u", dwServiceCurrent
);
241 if (!WaitNamedPipeW(NtControlPipeName
, 30000))
243 ERR("WaitNamedPipe(%S) failed (Error %lu)\n", NtControlPipeName
, GetLastError());
244 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
247 *hPipe
= CreateFileW(NtControlPipeName
,
248 GENERIC_READ
| GENERIC_WRITE
,
249 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
252 FILE_ATTRIBUTE_NORMAL
,
254 if (*hPipe
== INVALID_HANDLE_VALUE
)
256 ERR("CreateFileW() failed for pipe %S (Error %lu)\n", NtControlPipeName
, GetLastError());
257 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
260 dwState
= PIPE_READMODE_MESSAGE
;
261 if (!SetNamedPipeHandleState(*hPipe
, &dwState
, NULL
, NULL
))
264 *hPipe
= INVALID_HANDLE_VALUE
;
265 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
268 /* Pass the ProcessId to the SCM */
269 dwProcessId
= GetCurrentProcessId();
276 TRACE("Sent Process ID %lu\n", dwProcessId
);
278 return ERROR_SUCCESS
;
283 * Ansi/Unicode argument layout of the vector passed to a service at startup,
284 * depending on the different versions of Windows considered:
287 * [argv array of pointers][parameter 1][parameter 2]...[service name]
290 * [argv array of pointers][align to 8 bytes]
291 * [parameter 1][parameter 2]...[service name]
294 * [argv array of pointers][service name]
295 * [parameter 1][align to 4 bytes][parameter 2][align to 4 bytes]...
297 * Space for parameters and service name is always enough to store
298 * both the Ansi and the Unicode versions including NULL terminator.
302 ScBuildUnicodeArgsVector(PSCM_CONTROL_PACKET ControlPacket
,
304 LPWSTR
**lpArgVector
)
307 PWSTR pszServiceName
;
313 if (ControlPacket
== NULL
|| lpArgCount
== NULL
|| lpArgVector
== NULL
)
314 return ERROR_INVALID_PARAMETER
;
319 /* Retrieve and count the start command line (NULL-terminated) */
320 pszServiceName
= (PWSTR
)((ULONG_PTR
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
);
321 cbServiceName
= lstrlenW(pszServiceName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
324 * The total size of the argument vector is equal to the entry for
325 * the service name, plus the size of the original argument vector.
327 cbTotal
= sizeof(PWSTR
) + cbServiceName
;
328 if (ControlPacket
->dwArgumentsCount
> 0)
329 cbArguments
= ControlPacket
->dwSize
- ControlPacket
->dwArgumentsOffset
;
332 cbTotal
+= cbArguments
;
334 /* Allocate the new argument vector */
335 lpVector
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbTotal
);
336 if (lpVector
== NULL
)
337 return ERROR_NOT_ENOUGH_MEMORY
;
340 * The first argument is reserved for the service name, which
341 * will be appended to the end of the argument string list.
344 /* Copy the remaining arguments */
345 if (ControlPacket
->dwArgumentsCount
> 0)
348 (PWSTR
)((ULONG_PTR
)ControlPacket
+ ControlPacket
->dwArgumentsOffset
),
351 for (i
= 0; i
< ControlPacket
->dwArgumentsCount
; i
++)
353 lpVector
[i
+ 1] = (PWSTR
)((ULONG_PTR
)&lpVector
[1] + (ULONG_PTR
)lpVector
[i
+ 1]);
354 TRACE("Unicode lpVector[%lu] = '%ls'\n", i
+ 1, lpVector
[i
+ 1]);
358 /* Now copy the service name */
359 lpVector
[0] = (PWSTR
)((ULONG_PTR
)&lpVector
[1] + cbArguments
);
360 memcpy(lpVector
[0], pszServiceName
, cbServiceName
);
361 TRACE("Unicode lpVector[%lu] = '%ls'\n", 0, lpVector
[0]);
363 *lpArgCount
= ControlPacket
->dwArgumentsCount
+ 1;
364 *lpArgVector
= lpVector
;
366 return ERROR_SUCCESS
;
371 ScBuildAnsiArgsVector(PSCM_CONTROL_PACKET ControlPacket
,
380 UNICODE_STRING UnicodeString
;
381 ANSI_STRING AnsiString
;
383 if (ControlPacket
== NULL
|| lpArgCount
== NULL
|| lpArgVector
== NULL
)
384 return ERROR_INVALID_PARAMETER
;
389 /* Build the UNICODE arguments vector */
390 dwError
= ScBuildUnicodeArgsVector(ControlPacket
, &ArgCount
, &lpVectorW
);
391 if (dwError
!= ERROR_SUCCESS
)
394 /* Convert the vector to ANSI in place */
395 lpVectorA
= (PSTR
*)lpVectorW
;
396 for (i
= 0; i
< ArgCount
; i
++)
398 RtlInitUnicodeString(&UnicodeString
, lpVectorW
[i
]);
399 RtlInitEmptyAnsiString(&AnsiString
, lpVectorA
[i
], UnicodeString
.MaximumLength
);
400 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, FALSE
);
401 if (!NT_SUCCESS(Status
))
403 /* Failed to convert to ANSI; free the allocated vector and return */
404 dwError
= RtlNtStatusToDosError(Status
);
405 HeapFree(GetProcessHeap(), 0, lpVectorW
);
409 /* NULL-terminate the string */
410 AnsiString
.Buffer
[AnsiString
.Length
/ sizeof(CHAR
)] = ANSI_NULL
;
412 TRACE("Ansi lpVector[%lu] = '%s'\n", i
, lpVectorA
[i
]);
415 *lpArgCount
= ArgCount
;
416 *lpArgVector
= lpVectorA
;
418 return ERROR_SUCCESS
;
423 ScStartService(PACTIVE_SERVICE lpService
,
424 PSCM_CONTROL_PACKET ControlPacket
)
429 PSERVICE_THREAD_PARAMSA ThreadParamsA
;
430 PSERVICE_THREAD_PARAMSW ThreadParamsW
;
432 TRACE("ScStartService(%p %p)\n",
433 lpService
, ControlPacket
);
435 if (lpService
== NULL
|| ControlPacket
== NULL
)
436 return ERROR_INVALID_PARAMETER
;
438 TRACE("Size: %lu\n", ControlPacket
->dwSize
);
439 TRACE("Service: %S\n", (PWSTR
)((ULONG_PTR
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
));
441 /* Set the service status handle */
442 lpService
->hServiceStatus
= ControlPacket
->hServiceStatus
;
444 /* Build the arguments vector */
445 if (lpService
->bUnicode
!= FALSE
)
447 ThreadParamsW
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ThreadParamsW
));
448 if (ThreadParamsW
== NULL
)
449 return ERROR_NOT_ENOUGH_MEMORY
;
450 dwError
= ScBuildUnicodeArgsVector(ControlPacket
,
451 &ThreadParamsW
->dwArgCount
,
452 &ThreadParamsW
->lpArgVector
);
453 if (dwError
!= ERROR_SUCCESS
)
455 HeapFree(GetProcessHeap(), 0, ThreadParamsW
);
458 ThreadParamsW
->lpServiceMain
= lpService
->ServiceMain
.W
;
459 ThreadHandle
= CreateThread(NULL
,
465 if (ThreadHandle
== NULL
)
467 if (ThreadParamsW
->lpArgVector
!= NULL
)
469 HeapFree(GetProcessHeap(), 0, ThreadParamsW
->lpArgVector
);
471 HeapFree(GetProcessHeap(), 0, ThreadParamsW
);
473 return ERROR_SERVICE_NO_THREAD
;
476 CloseHandle(ThreadHandle
);
480 ThreadParamsA
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ThreadParamsA
));
481 if (ThreadParamsA
== NULL
)
482 return ERROR_NOT_ENOUGH_MEMORY
;
483 dwError
= ScBuildAnsiArgsVector(ControlPacket
,
484 &ThreadParamsA
->dwArgCount
,
485 &ThreadParamsA
->lpArgVector
);
486 if (dwError
!= ERROR_SUCCESS
)
488 HeapFree(GetProcessHeap(), 0, ThreadParamsA
);
491 ThreadParamsA
->lpServiceMain
= lpService
->ServiceMain
.A
;
492 ThreadHandle
= CreateThread(NULL
,
498 if (ThreadHandle
== NULL
)
500 if (ThreadParamsA
->lpArgVector
!= NULL
)
502 HeapFree(GetProcessHeap(), 0, ThreadParamsA
->lpArgVector
);
504 HeapFree(GetProcessHeap(), 0, ThreadParamsA
);
506 return ERROR_SERVICE_NO_THREAD
;
509 CloseHandle(ThreadHandle
);
512 return ERROR_SUCCESS
;
517 ScControlService(PACTIVE_SERVICE lpService
,
518 PSCM_CONTROL_PACKET ControlPacket
)
520 DWORD dwError
= ERROR_SUCCESS
;
522 TRACE("ScControlService(%p %p)\n",
523 lpService
, ControlPacket
);
525 if (lpService
== NULL
|| ControlPacket
== NULL
)
526 return ERROR_INVALID_PARAMETER
;
528 TRACE("Size: %lu\n", ControlPacket
->dwSize
);
529 TRACE("Service: %S\n", (PWSTR
)((ULONG_PTR
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
));
531 if (lpService
->HandlerFunction
)
535 (lpService
->HandlerFunction
)(ControlPacket
->dwControl
);
537 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
539 dwError
= ERROR_EXCEPTION_IN_SERVICE
;
543 else if (lpService
->HandlerFunctionEx
)
547 /* FIXME: Send correct 2nd and 3rd parameters */
548 (lpService
->HandlerFunctionEx
)(ControlPacket
->dwControl
,
550 lpService
->HandlerContext
);
552 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
554 dwError
= ERROR_EXCEPTION_IN_SERVICE
;
560 dwError
= ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
563 TRACE("ScControlService() done (Error %lu)\n", dwError
);
570 ScServiceDispatcher(HANDLE hPipe
,
571 PSCM_CONTROL_PACKET ControlPacket
,
576 BOOL bRunning
= TRUE
;
577 LPWSTR lpServiceName
;
578 PACTIVE_SERVICE lpService
;
579 SCM_REPLY_PACKET ReplyPacket
;
582 TRACE("ScServiceDispatcher(%p %p %lu)\n",
583 hPipe
, ControlPacket
, dwBufferSize
);
585 if (ControlPacket
== NULL
|| dwBufferSize
< sizeof(SCM_CONTROL_PACKET
))
590 /* Read command from the control pipe */
591 bResult
= ReadFile(hPipe
,
596 if (bResult
== FALSE
)
598 ERR("Pipe read failed (Error: %lu)\n", GetLastError());
602 lpServiceName
= (LPWSTR
)((PBYTE
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
);
603 TRACE("Service: %S\n", lpServiceName
);
605 if ((ControlPacket
->dwControl
== SERVICE_CONTROL_STOP
) &&
606 (lpServiceName
[0] == UNICODE_NULL
))
608 TRACE("Stop dispatcher thread\n");
610 dwError
= ERROR_SUCCESS
;
614 if (ControlPacket
->dwControl
== SERVICE_CONTROL_START_OWN
)
615 lpActiveServices
[0].bOwnProcess
= TRUE
;
617 lpService
= ScLookupServiceByServiceName(lpServiceName
);
618 if (lpService
!= NULL
)
620 /* Execute command */
621 switch (ControlPacket
->dwControl
)
623 case SERVICE_CONTROL_START_SHARE
:
624 case SERVICE_CONTROL_START_OWN
:
625 TRACE("Start command - received SERVICE_CONTROL_START\n");
626 dwError
= ScStartService(lpService
, ControlPacket
);
629 case SERVICE_CONTROL_STOP
:
630 TRACE("Stop command - received SERVICE_CONTROL_STOP\n");
631 dwError
= ScControlService(lpService
, ControlPacket
);
635 TRACE("Command %lu received", ControlPacket
->dwControl
);
636 dwError
= ScControlService(lpService
, ControlPacket
);
642 dwError
= ERROR_SERVICE_NOT_IN_EXE
;
646 ReplyPacket
.dwError
= dwError
;
648 /* Send the reply packet */
649 bResult
= WriteFile(hPipe
,
654 if (bResult
== FALSE
)
656 ERR("Pipe write failed (Error: %lu)\n", GetLastError());
665 /**********************************************************************
666 * RegisterServiceCtrlHandlerA
670 SERVICE_STATUS_HANDLE WINAPI
671 RegisterServiceCtrlHandlerA(LPCSTR lpServiceName
,
672 LPHANDLER_FUNCTION lpHandlerProc
)
674 ANSI_STRING ServiceNameA
;
675 UNICODE_STRING ServiceNameU
;
676 SERVICE_STATUS_HANDLE hServiceStatus
;
678 TRACE("RegisterServiceCtrlHandlerA(%s %p)\n",
679 debugstr_a(lpServiceName
), lpHandlerProc
);
681 RtlInitAnsiString(&ServiceNameA
, lpServiceName
);
682 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU
, &ServiceNameA
, TRUE
)))
684 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
688 hServiceStatus
= RegisterServiceCtrlHandlerW(ServiceNameU
.Buffer
,
691 RtlFreeUnicodeString(&ServiceNameU
);
693 return hServiceStatus
;
697 /**********************************************************************
698 * RegisterServiceCtrlHandlerW
702 SERVICE_STATUS_HANDLE WINAPI
703 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName
,
704 LPHANDLER_FUNCTION lpHandlerProc
)
706 PACTIVE_SERVICE Service
;
708 TRACE("RegisterServiceCtrlHandlerW(%s %p)\n",
709 debugstr_w(lpServiceName
), lpHandlerProc
);
711 Service
= ScLookupServiceByServiceName(lpServiceName
);
714 SetLastError(ERROR_SERVICE_NOT_IN_EXE
);
720 SetLastError(ERROR_INVALID_PARAMETER
);
724 Service
->HandlerFunction
= lpHandlerProc
;
725 Service
->HandlerFunctionEx
= NULL
;
727 TRACE("RegisterServiceCtrlHandler returning %p\n", Service
->hServiceStatus
);
729 return Service
->hServiceStatus
;
733 /**********************************************************************
734 * RegisterServiceCtrlHandlerExA
738 SERVICE_STATUS_HANDLE WINAPI
739 RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName
,
740 LPHANDLER_FUNCTION_EX lpHandlerProc
,
743 ANSI_STRING ServiceNameA
;
744 UNICODE_STRING ServiceNameU
;
745 SERVICE_STATUS_HANDLE hServiceStatus
;
747 TRACE("RegisterServiceCtrlHandlerExA(%s %p %p)\n",
748 debugstr_a(lpServiceName
), lpHandlerProc
, lpContext
);
750 RtlInitAnsiString(&ServiceNameA
, lpServiceName
);
751 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU
, &ServiceNameA
, TRUE
)))
753 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
757 hServiceStatus
= RegisterServiceCtrlHandlerExW(ServiceNameU
.Buffer
,
761 RtlFreeUnicodeString(&ServiceNameU
);
763 return hServiceStatus
;
767 /**********************************************************************
768 * RegisterServiceCtrlHandlerExW
772 SERVICE_STATUS_HANDLE WINAPI
773 RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName
,
774 LPHANDLER_FUNCTION_EX lpHandlerProc
,
777 PACTIVE_SERVICE Service
;
779 TRACE("RegisterServiceCtrlHandlerExW(%s %p %p)\n",
780 debugstr_w(lpServiceName
), lpHandlerProc
, lpContext
);
782 Service
= ScLookupServiceByServiceName(lpServiceName
);
785 SetLastError(ERROR_SERVICE_NOT_IN_EXE
);
791 SetLastError(ERROR_INVALID_PARAMETER
);
795 Service
->HandlerFunction
= NULL
;
796 Service
->HandlerFunctionEx
= lpHandlerProc
;
797 Service
->HandlerContext
= lpContext
;
799 TRACE("RegisterServiceCtrlHandlerEx returning %p\n", Service
->hServiceStatus
);
801 return Service
->hServiceStatus
;
805 /**********************************************************************
806 * I_ScIsSecurityProcess
814 I_ScIsSecurityProcess(VOID
)
816 FIXME("I_ScIsSecurityProcess()\n");
820 /**********************************************************************
821 * I_ScPnPGetServiceName
829 I_ScPnPGetServiceName(IN SERVICE_STATUS_HANDLE hServiceStatus
,
830 OUT LPWSTR lpServiceName
,
831 IN DWORD cchServiceName
)
835 TRACE("I_ScPnPGetServiceName(%lu %p %lu)\n",
836 hServiceStatus
, lpServiceName
, cchServiceName
);
838 for (i
= 0; i
< dwActiveServiceCount
; i
++)
840 if (lpActiveServices
[i
].hServiceStatus
== hServiceStatus
)
842 wcscpy(lpServiceName
, lpActiveServices
[i
].ServiceName
.Buffer
);
843 return ERROR_SUCCESS
;
847 return ERROR_SERVICE_NOT_IN_EXE
;
851 /**********************************************************************
852 * I_ScSetServiceBitsA
859 I_ScSetServiceBitsA(SERVICE_STATUS_HANDLE hServiceStatus
,
862 BOOL bUpdateImmediately
,
867 TRACE("I_ScSetServiceBitsA(%lu %lx %u %u %s)\n",
868 hServiceStatus
, dwServiceBits
, bSetBitsOn
, bUpdateImmediately
,
869 debugstr_a(lpString
));
873 bResult
= RI_ScSetServiceBitsA((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
879 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
881 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
890 /**********************************************************************
891 * I_ScSetServiceBitsW
898 I_ScSetServiceBitsW(SERVICE_STATUS_HANDLE hServiceStatus
,
901 BOOL bUpdateImmediately
,
906 TRACE("I_ScSetServiceBitsW(%lu %lx %u %u %s)\n",
907 hServiceStatus
, dwServiceBits
, bSetBitsOn
, bUpdateImmediately
,
908 debugstr_w(lpString
));
912 bResult
= RI_ScSetServiceBitsW((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
918 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
920 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
929 /**********************************************************************
935 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus
,
938 BOOL bUpdateImmediately
)
940 TRACE("SetServiceBits(%lu %lx %u %u)\n",
941 hServiceStatus
, dwServiceBits
, bSetBitsOn
, bUpdateImmediately
);
943 return I_ScSetServiceBitsW(hServiceStatus
,
951 /**********************************************************************
957 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus
,
958 LPSERVICE_STATUS lpServiceStatus
)
962 TRACE("SetServiceStatus(%lu %p)\n",
963 hServiceStatus
, lpServiceStatus
);
967 dwError
= RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
970 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
972 dwError
= ScmRpcStatusToWinError(RpcExceptionCode());
976 if (dwError
!= ERROR_SUCCESS
)
978 ERR("RSetServiceStatus() failed (Error %lu)\n", dwError
);
979 SetLastError(dwError
);
983 TRACE("SetServiceStatus() done\n");
989 /**********************************************************************
990 * StartServiceCtrlDispatcherA
995 StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA
*lpServiceStartTable
)
1000 PSCM_CONTROL_PACKET ControlPacket
;
1004 TRACE("StartServiceCtrlDispatcherA(%p)\n",
1005 lpServiceStartTable
);
1008 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
1013 dwActiveServiceCount
= i
;
1015 /* Allocate the service table */
1016 lpActiveServices
= RtlAllocateHeap(RtlGetProcessHeap(),
1018 dwActiveServiceCount
* sizeof(ACTIVE_SERVICE
));
1019 if (lpActiveServices
== NULL
)
1021 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1025 /* Copy service names and start procedure */
1026 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1028 RtlCreateUnicodeStringFromAsciiz(&lpActiveServices
[i
].ServiceName
,
1029 lpServiceStartTable
[i
].lpServiceName
);
1030 lpActiveServices
[i
].ServiceMain
.A
= lpServiceStartTable
[i
].lpServiceProc
;
1031 lpActiveServices
[i
].hServiceStatus
= NULL
;
1032 lpActiveServices
[i
].bUnicode
= FALSE
;
1033 lpActiveServices
[i
].bOwnProcess
= FALSE
;
1036 /* Connect to the SCM */
1037 dwError
= ScConnectControlPipe(&hPipe
);
1038 if (dwError
!= ERROR_SUCCESS
)
1044 dwBufSize
= sizeof(SCM_CONTROL_PACKET
) +
1045 (MAX_SERVICE_NAME_LENGTH
+ 1) * sizeof(WCHAR
);
1047 ControlPacket
= RtlAllocateHeap(RtlGetProcessHeap(),
1050 if (ControlPacket
== NULL
)
1052 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1057 ScCreateStatusBinding();
1059 /* Call the dispatcher loop */
1060 ScServiceDispatcher(hPipe
, ControlPacket
, dwBufSize
);
1063 ScDestroyStatusBinding();
1065 /* Close the connection */
1068 /* Free the control packet */
1069 RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket
);
1072 /* Free the service table */
1073 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1075 RtlFreeUnicodeString(&lpActiveServices
[i
].ServiceName
);
1077 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
1078 lpActiveServices
= NULL
;
1079 dwActiveServiceCount
= 0;
1082 SetLastError(dwError
);
1088 /**********************************************************************
1089 * StartServiceCtrlDispatcherW
1094 StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW
*lpServiceStartTable
)
1099 PSCM_CONTROL_PACKET ControlPacket
;
1103 TRACE("StartServiceCtrlDispatcherW(%p)\n",
1104 lpServiceStartTable
);
1107 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
1112 dwActiveServiceCount
= i
;
1114 /* Allocate the service table */
1115 lpActiveServices
= RtlAllocateHeap(RtlGetProcessHeap(),
1117 dwActiveServiceCount
* sizeof(ACTIVE_SERVICE
));
1118 if (lpActiveServices
== NULL
)
1120 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1124 /* Copy service names and start procedure */
1125 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1127 RtlCreateUnicodeString(&lpActiveServices
[i
].ServiceName
,
1128 lpServiceStartTable
[i
].lpServiceName
);
1129 lpActiveServices
[i
].ServiceMain
.W
= lpServiceStartTable
[i
].lpServiceProc
;
1130 lpActiveServices
[i
].hServiceStatus
= NULL
;
1131 lpActiveServices
[i
].bUnicode
= TRUE
;
1132 lpActiveServices
[i
].bOwnProcess
= FALSE
;
1135 /* Connect to the SCM */
1136 dwError
= ScConnectControlPipe(&hPipe
);
1137 if (dwError
!= ERROR_SUCCESS
)
1143 dwBufSize
= sizeof(SCM_CONTROL_PACKET
) +
1144 (MAX_SERVICE_NAME_LENGTH
+ 1) * sizeof(WCHAR
);
1146 ControlPacket
= RtlAllocateHeap(RtlGetProcessHeap(),
1149 if (ControlPacket
== NULL
)
1151 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1156 ScCreateStatusBinding();
1158 /* Call the dispatcher loop */
1159 ScServiceDispatcher(hPipe
, ControlPacket
, dwBufSize
);
1161 ScDestroyStatusBinding();
1163 /* Close the connection */
1166 /* Free the control packet */
1167 RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket
);
1170 /* Free the service table */
1171 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1173 RtlFreeUnicodeString(&lpActiveServices
[i
].ServiceName
);
1175 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
1176 lpActiveServices
= NULL
;
1177 dwActiveServiceCount
= 0;
1180 SetLastError(dwError
);