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
;
26 } SERVICE_THREAD_PARAMSA
, *PSERVICE_THREAD_PARAMSA
;
29 typedef struct _SERVICE_THREAD_PARAMSW
31 LPSERVICE_MAIN_FUNCTIONW lpServiceMain
;
35 } SERVICE_THREAD_PARAMSW
, *PSERVICE_THREAD_PARAMSW
;
38 typedef struct _ACTIVE_SERVICE
40 SERVICE_STATUS_HANDLE hServiceStatus
;
41 UNICODE_STRING ServiceName
;
44 LPSERVICE_MAIN_FUNCTIONA A
;
45 LPSERVICE_MAIN_FUNCTIONW W
;
47 LPHANDLER_FUNCTION HandlerFunction
;
48 LPHANDLER_FUNCTION_EX HandlerFunctionEx
;
49 LPVOID HandlerContext
;
53 } ACTIVE_SERVICE
, *PACTIVE_SERVICE
;
56 /* GLOBALS *******************************************************************/
58 static DWORD dwActiveServiceCount
= 0;
59 static PACTIVE_SERVICE lpActiveServices
= NULL
;
60 static handle_t hStatusBinding
= NULL
;
63 /* FUNCTIONS *****************************************************************/
66 RPC_SERVICE_STATUS_HANDLE_bind(RPC_SERVICE_STATUS_HANDLE hServiceStatus
)
68 return hStatusBinding
;
73 RPC_SERVICE_STATUS_HANDLE_unbind(RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
80 ScCreateStatusBinding(VOID
)
82 LPWSTR pszStringBinding
;
85 TRACE("ScCreateStatusBinding()\n");
87 status
= RpcStringBindingComposeW(NULL
,
93 if (status
!= RPC_S_OK
)
95 ERR("RpcStringBindingCompose returned 0x%x\n", status
);
99 /* Set the binding handle that will be used to bind to the server. */
100 status
= RpcBindingFromStringBindingW(pszStringBinding
,
102 if (status
!= RPC_S_OK
)
104 ERR("RpcBindingFromStringBinding returned 0x%x\n", status
);
107 status
= RpcStringFreeW(&pszStringBinding
);
108 if (status
!= RPC_S_OK
)
110 ERR("RpcStringFree returned 0x%x\n", status
);
118 ScDestroyStatusBinding(VOID
)
122 TRACE("ScDestroyStatusBinding()\n");
124 if (hStatusBinding
== NULL
)
127 status
= RpcBindingFree(&hStatusBinding
);
128 if (status
!= RPC_S_OK
)
130 ERR("RpcBindingFree returned 0x%x\n", status
);
134 hStatusBinding
= NULL
;
141 static PACTIVE_SERVICE
142 ScLookupServiceByServiceName(LPCWSTR lpServiceName
)
146 TRACE("ScLookupServiceByServiceName(%S)\n",
149 if (lpActiveServices
[0].bOwnProcess
)
150 return &lpActiveServices
[0];
152 for (i
= 0; i
< dwActiveServiceCount
; i
++)
154 TRACE("Checking %S\n", lpActiveServices
[i
].ServiceName
.Buffer
);
155 if (_wcsicmp(lpActiveServices
[i
].ServiceName
.Buffer
, lpServiceName
) == 0)
158 return &lpActiveServices
[i
];
162 TRACE("No service found!\n");
168 ScServiceMainStubA(LPVOID Context
)
171 PSERVICE_THREAD_PARAMSA ThreadParams
= Context
;
173 TRACE("ScServiceMainStubA(%p)\n", Context
);
175 /* Set service tag */
176 Teb
= NtCurrentTeb();
177 Teb
->SubProcessTag
= UlongToPtr(ThreadParams
->dwServiceTag
);
179 /* Call the main service routine and free the arguments vector */
180 (ThreadParams
->lpServiceMain
)(ThreadParams
->dwArgCount
,
181 ThreadParams
->lpArgVector
);
183 /* Reset service tag */
184 Teb
->SubProcessTag
= 0;
186 if (ThreadParams
->lpArgVector
!= NULL
)
188 HeapFree(GetProcessHeap(), 0, ThreadParams
->lpArgVector
);
190 HeapFree(GetProcessHeap(), 0, ThreadParams
);
192 return ERROR_SUCCESS
;
197 ScServiceMainStubW(LPVOID Context
)
200 PSERVICE_THREAD_PARAMSW ThreadParams
= Context
;
202 TRACE("ScServiceMainStubW(%p)\n", Context
);
204 /* Set service tag */
205 Teb
= NtCurrentTeb();
206 Teb
->SubProcessTag
= UlongToPtr(ThreadParams
->dwServiceTag
);
208 /* Call the main service routine and free the arguments vector */
209 (ThreadParams
->lpServiceMain
)(ThreadParams
->dwArgCount
,
210 ThreadParams
->lpArgVector
);
212 /* Reset service tag */
213 Teb
->SubProcessTag
= 0;
215 if (ThreadParams
->lpArgVector
!= NULL
)
217 HeapFree(GetProcessHeap(), 0, ThreadParams
->lpArgVector
);
219 HeapFree(GetProcessHeap(), 0, ThreadParams
);
221 return ERROR_SUCCESS
;
226 ScConnectControlPipe(HANDLE
*hPipe
)
228 DWORD dwBytesWritten
;
230 DWORD dwServiceCurrent
= 0;
232 WCHAR NtControlPipeName
[MAX_PATH
+ 1];
233 RTL_QUERY_REGISTRY_TABLE QueryTable
[2];
236 TRACE("ScConnectControlPipe(%p)\n",
239 /* Get the service number and create the named pipe */
240 RtlZeroMemory(&QueryTable
,
243 QueryTable
[0].Name
= L
"";
244 QueryTable
[0].Flags
= RTL_QUERY_REGISTRY_DIRECT
| RTL_QUERY_REGISTRY_REQUIRED
;
245 QueryTable
[0].EntryContext
= &dwServiceCurrent
;
247 Status
= RtlQueryRegistryValues(RTL_REGISTRY_CONTROL
,
252 if (!NT_SUCCESS(Status
))
254 ERR("RtlQueryRegistryValues() failed (Status %lx)\n", Status
);
255 return RtlNtStatusToDosError(Status
);
258 swprintf(NtControlPipeName
, L
"\\\\.\\pipe\\net\\NtControlPipe%u", dwServiceCurrent
);
260 if (!WaitNamedPipeW(NtControlPipeName
, 30000))
262 ERR("WaitNamedPipe(%S) failed (Error %lu)\n", NtControlPipeName
, GetLastError());
263 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
266 *hPipe
= CreateFileW(NtControlPipeName
,
267 GENERIC_READ
| GENERIC_WRITE
,
268 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
271 FILE_ATTRIBUTE_NORMAL
,
273 if (*hPipe
== INVALID_HANDLE_VALUE
)
275 ERR("CreateFileW() failed for pipe %S (Error %lu)\n", NtControlPipeName
, GetLastError());
276 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
279 dwState
= PIPE_READMODE_MESSAGE
;
280 if (!SetNamedPipeHandleState(*hPipe
, &dwState
, NULL
, NULL
))
283 *hPipe
= INVALID_HANDLE_VALUE
;
284 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT
;
287 /* Pass the ProcessId to the SCM */
288 dwProcessId
= GetCurrentProcessId();
295 TRACE("Sent Process ID %lu\n", dwProcessId
);
297 return ERROR_SUCCESS
;
302 * Ansi/Unicode argument layout of the vector passed to a service at startup,
303 * depending on the different versions of Windows considered:
306 * [argv array of pointers][parameter 1][parameter 2]...[service name]
309 * [argv array of pointers][align to 8 bytes]
310 * [parameter 1][parameter 2]...[service name]
313 * [argv array of pointers][service name]
314 * [parameter 1][align to 4 bytes][parameter 2][align to 4 bytes]...
316 * Space for parameters and service name is always enough to store
317 * both the Ansi and the Unicode versions including NULL terminator.
321 ScBuildUnicodeArgsVector(PSCM_CONTROL_PACKET ControlPacket
,
323 LPWSTR
**lpArgVector
)
326 PWSTR pszServiceName
;
332 if (ControlPacket
== NULL
|| lpArgCount
== NULL
|| lpArgVector
== NULL
)
333 return ERROR_INVALID_PARAMETER
;
338 /* Retrieve and count the start command line (NULL-terminated) */
339 pszServiceName
= (PWSTR
)((ULONG_PTR
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
);
340 cbServiceName
= lstrlenW(pszServiceName
) * sizeof(WCHAR
) + sizeof(UNICODE_NULL
);
343 * The total size of the argument vector is equal to the entry for
344 * the service name, plus the size of the original argument vector.
346 cbTotal
= sizeof(PWSTR
) + cbServiceName
;
347 if (ControlPacket
->dwArgumentsCount
> 0)
348 cbArguments
= ControlPacket
->dwSize
- ControlPacket
->dwArgumentsOffset
;
351 cbTotal
+= cbArguments
;
353 /* Allocate the new argument vector */
354 lpVector
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbTotal
);
355 if (lpVector
== NULL
)
356 return ERROR_NOT_ENOUGH_MEMORY
;
359 * The first argument is reserved for the service name, which
360 * will be appended to the end of the argument string list.
363 /* Copy the remaining arguments */
364 if (ControlPacket
->dwArgumentsCount
> 0)
367 (PWSTR
)((ULONG_PTR
)ControlPacket
+ ControlPacket
->dwArgumentsOffset
),
370 for (i
= 0; i
< ControlPacket
->dwArgumentsCount
; i
++)
372 lpVector
[i
+ 1] = (PWSTR
)((ULONG_PTR
)&lpVector
[1] + (ULONG_PTR
)lpVector
[i
+ 1]);
373 TRACE("Unicode lpVector[%lu] = '%ls'\n", i
+ 1, lpVector
[i
+ 1]);
377 /* Now copy the service name */
378 lpVector
[0] = (PWSTR
)((ULONG_PTR
)&lpVector
[1] + cbArguments
);
379 memcpy(lpVector
[0], pszServiceName
, cbServiceName
);
380 TRACE("Unicode lpVector[%lu] = '%ls'\n", 0, lpVector
[0]);
382 *lpArgCount
= ControlPacket
->dwArgumentsCount
+ 1;
383 *lpArgVector
= lpVector
;
385 return ERROR_SUCCESS
;
390 ScBuildAnsiArgsVector(PSCM_CONTROL_PACKET ControlPacket
,
399 UNICODE_STRING UnicodeString
;
400 ANSI_STRING AnsiString
;
402 if (ControlPacket
== NULL
|| lpArgCount
== NULL
|| lpArgVector
== NULL
)
403 return ERROR_INVALID_PARAMETER
;
408 /* Build the UNICODE arguments vector */
409 dwError
= ScBuildUnicodeArgsVector(ControlPacket
, &ArgCount
, &lpVectorW
);
410 if (dwError
!= ERROR_SUCCESS
)
413 /* Convert the vector to ANSI in place */
414 lpVectorA
= (PSTR
*)lpVectorW
;
415 for (i
= 0; i
< ArgCount
; i
++)
417 RtlInitUnicodeString(&UnicodeString
, lpVectorW
[i
]);
418 RtlInitEmptyAnsiString(&AnsiString
, lpVectorA
[i
], UnicodeString
.MaximumLength
);
419 Status
= RtlUnicodeStringToAnsiString(&AnsiString
, &UnicodeString
, FALSE
);
420 if (!NT_SUCCESS(Status
))
422 /* Failed to convert to ANSI; free the allocated vector and return */
423 dwError
= RtlNtStatusToDosError(Status
);
424 HeapFree(GetProcessHeap(), 0, lpVectorW
);
428 /* NULL-terminate the string */
429 AnsiString
.Buffer
[AnsiString
.Length
/ sizeof(CHAR
)] = ANSI_NULL
;
431 TRACE("Ansi lpVector[%lu] = '%s'\n", i
, lpVectorA
[i
]);
434 *lpArgCount
= ArgCount
;
435 *lpArgVector
= lpVectorA
;
437 return ERROR_SUCCESS
;
442 ScStartService(PACTIVE_SERVICE lpService
,
443 PSCM_CONTROL_PACKET ControlPacket
)
448 PSERVICE_THREAD_PARAMSA ThreadParamsA
;
449 PSERVICE_THREAD_PARAMSW ThreadParamsW
;
451 TRACE("ScStartService(%p %p)\n",
452 lpService
, ControlPacket
);
454 if (lpService
== NULL
|| ControlPacket
== NULL
)
455 return ERROR_INVALID_PARAMETER
;
457 TRACE("Size: %lu\n", ControlPacket
->dwSize
);
458 TRACE("Service: %S\n", (PWSTR
)((ULONG_PTR
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
));
460 /* Set the service status handle */
461 lpService
->hServiceStatus
= ControlPacket
->hServiceStatus
;
462 /* Set the service tag */
463 lpService
->dwServiceTag
= ControlPacket
->dwServiceTag
;
465 /* Build the arguments vector */
466 if (lpService
->bUnicode
!= FALSE
)
468 ThreadParamsW
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ThreadParamsW
));
469 if (ThreadParamsW
== NULL
)
470 return ERROR_NOT_ENOUGH_MEMORY
;
471 dwError
= ScBuildUnicodeArgsVector(ControlPacket
,
472 &ThreadParamsW
->dwArgCount
,
473 &ThreadParamsW
->lpArgVector
);
474 if (dwError
!= ERROR_SUCCESS
)
476 HeapFree(GetProcessHeap(), 0, ThreadParamsW
);
479 ThreadParamsW
->lpServiceMain
= lpService
->ServiceMain
.W
;
480 ThreadParamsW
->dwServiceTag
= ControlPacket
->dwServiceTag
;
481 ThreadHandle
= CreateThread(NULL
,
487 if (ThreadHandle
== NULL
)
489 if (ThreadParamsW
->lpArgVector
!= NULL
)
491 HeapFree(GetProcessHeap(), 0, ThreadParamsW
->lpArgVector
);
493 HeapFree(GetProcessHeap(), 0, ThreadParamsW
);
495 return ERROR_SERVICE_NO_THREAD
;
498 CloseHandle(ThreadHandle
);
502 ThreadParamsA
= HeapAlloc(GetProcessHeap(), 0, sizeof(*ThreadParamsA
));
503 if (ThreadParamsA
== NULL
)
504 return ERROR_NOT_ENOUGH_MEMORY
;
505 dwError
= ScBuildAnsiArgsVector(ControlPacket
,
506 &ThreadParamsA
->dwArgCount
,
507 &ThreadParamsA
->lpArgVector
);
508 if (dwError
!= ERROR_SUCCESS
)
510 HeapFree(GetProcessHeap(), 0, ThreadParamsA
);
513 ThreadParamsA
->lpServiceMain
= lpService
->ServiceMain
.A
;
514 ThreadParamsA
->dwServiceTag
= ControlPacket
->dwServiceTag
;
515 ThreadHandle
= CreateThread(NULL
,
521 if (ThreadHandle
== NULL
)
523 if (ThreadParamsA
->lpArgVector
!= NULL
)
525 HeapFree(GetProcessHeap(), 0, ThreadParamsA
->lpArgVector
);
527 HeapFree(GetProcessHeap(), 0, ThreadParamsA
);
529 return ERROR_SERVICE_NO_THREAD
;
532 CloseHandle(ThreadHandle
);
535 return ERROR_SUCCESS
;
540 ScControlService(PACTIVE_SERVICE lpService
,
541 PSCM_CONTROL_PACKET ControlPacket
)
543 DWORD dwError
= ERROR_SUCCESS
;
545 TRACE("ScControlService(%p %p)\n",
546 lpService
, ControlPacket
);
548 if (lpService
== NULL
|| ControlPacket
== NULL
)
549 return ERROR_INVALID_PARAMETER
;
551 TRACE("Size: %lu\n", ControlPacket
->dwSize
);
552 TRACE("Service: %S\n", (PWSTR
)((ULONG_PTR
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
));
554 /* Set service tag */
555 NtCurrentTeb()->SubProcessTag
= UlongToPtr(lpService
->dwServiceTag
);
557 if (lpService
->HandlerFunction
)
561 (lpService
->HandlerFunction
)(ControlPacket
->dwControl
);
563 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
565 dwError
= ERROR_EXCEPTION_IN_SERVICE
;
569 else if (lpService
->HandlerFunctionEx
)
573 /* FIXME: Send correct 2nd and 3rd parameters */
574 (lpService
->HandlerFunctionEx
)(ControlPacket
->dwControl
,
576 lpService
->HandlerContext
);
578 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
580 dwError
= ERROR_EXCEPTION_IN_SERVICE
;
586 dwError
= ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
589 /* Reset service tag */
590 NtCurrentTeb()->SubProcessTag
= 0;
592 TRACE("ScControlService() done (Error %lu)\n", dwError
);
599 ScServiceDispatcher(HANDLE hPipe
,
600 PSCM_CONTROL_PACKET ControlPacket
,
605 BOOL bRunning
= TRUE
;
606 LPWSTR lpServiceName
;
607 PACTIVE_SERVICE lpService
;
608 SCM_REPLY_PACKET ReplyPacket
;
611 TRACE("ScServiceDispatcher(%p %p %lu)\n",
612 hPipe
, ControlPacket
, dwBufferSize
);
614 if (ControlPacket
== NULL
|| dwBufferSize
< sizeof(SCM_CONTROL_PACKET
))
619 /* Read command from the control pipe */
620 bResult
= ReadFile(hPipe
,
625 if (bResult
== FALSE
)
627 ERR("Pipe read failed (Error: %lu)\n", GetLastError());
631 lpServiceName
= (LPWSTR
)((PBYTE
)ControlPacket
+ ControlPacket
->dwServiceNameOffset
);
632 TRACE("Service: %S\n", lpServiceName
);
634 if ((ControlPacket
->dwControl
== SERVICE_CONTROL_STOP
) &&
635 (lpServiceName
[0] == UNICODE_NULL
))
637 TRACE("Stop dispatcher thread\n");
639 dwError
= ERROR_SUCCESS
;
643 if (ControlPacket
->dwControl
== SERVICE_CONTROL_START_OWN
)
644 lpActiveServices
[0].bOwnProcess
= TRUE
;
646 lpService
= ScLookupServiceByServiceName(lpServiceName
);
647 if (lpService
!= NULL
)
649 /* Execute command */
650 switch (ControlPacket
->dwControl
)
652 case SERVICE_CONTROL_START_SHARE
:
653 case SERVICE_CONTROL_START_OWN
:
654 TRACE("Start command - received SERVICE_CONTROL_START\n");
655 dwError
= ScStartService(lpService
, ControlPacket
);
658 case SERVICE_CONTROL_STOP
:
659 TRACE("Stop command - received SERVICE_CONTROL_STOP\n");
660 dwError
= ScControlService(lpService
, ControlPacket
);
664 TRACE("Command %lu received", ControlPacket
->dwControl
);
665 dwError
= ScControlService(lpService
, ControlPacket
);
671 dwError
= ERROR_SERVICE_NOT_IN_EXE
;
675 ReplyPacket
.dwError
= dwError
;
677 /* Send the reply packet */
678 bResult
= WriteFile(hPipe
,
683 if (bResult
== FALSE
)
685 ERR("Pipe write failed (Error: %lu)\n", GetLastError());
694 /**********************************************************************
695 * RegisterServiceCtrlHandlerA
699 SERVICE_STATUS_HANDLE WINAPI
700 RegisterServiceCtrlHandlerA(LPCSTR lpServiceName
,
701 LPHANDLER_FUNCTION lpHandlerProc
)
703 ANSI_STRING ServiceNameA
;
704 UNICODE_STRING ServiceNameU
;
705 SERVICE_STATUS_HANDLE hServiceStatus
;
707 TRACE("RegisterServiceCtrlHandlerA(%s %p)\n",
708 debugstr_a(lpServiceName
), lpHandlerProc
);
710 RtlInitAnsiString(&ServiceNameA
, lpServiceName
);
711 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU
, &ServiceNameA
, TRUE
)))
713 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
717 hServiceStatus
= RegisterServiceCtrlHandlerW(ServiceNameU
.Buffer
,
720 RtlFreeUnicodeString(&ServiceNameU
);
722 return hServiceStatus
;
726 /**********************************************************************
727 * RegisterServiceCtrlHandlerW
731 SERVICE_STATUS_HANDLE WINAPI
732 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName
,
733 LPHANDLER_FUNCTION lpHandlerProc
)
735 PACTIVE_SERVICE Service
;
737 TRACE("RegisterServiceCtrlHandlerW(%s %p)\n",
738 debugstr_w(lpServiceName
), lpHandlerProc
);
740 Service
= ScLookupServiceByServiceName(lpServiceName
);
743 SetLastError(ERROR_SERVICE_NOT_IN_EXE
);
749 SetLastError(ERROR_INVALID_PARAMETER
);
753 Service
->HandlerFunction
= lpHandlerProc
;
754 Service
->HandlerFunctionEx
= NULL
;
756 TRACE("RegisterServiceCtrlHandler returning %p\n", Service
->hServiceStatus
);
758 return Service
->hServiceStatus
;
762 /**********************************************************************
763 * RegisterServiceCtrlHandlerExA
767 SERVICE_STATUS_HANDLE WINAPI
768 RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName
,
769 LPHANDLER_FUNCTION_EX lpHandlerProc
,
772 ANSI_STRING ServiceNameA
;
773 UNICODE_STRING ServiceNameU
;
774 SERVICE_STATUS_HANDLE hServiceStatus
;
776 TRACE("RegisterServiceCtrlHandlerExA(%s %p %p)\n",
777 debugstr_a(lpServiceName
), lpHandlerProc
, lpContext
);
779 RtlInitAnsiString(&ServiceNameA
, lpServiceName
);
780 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU
, &ServiceNameA
, TRUE
)))
782 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
786 hServiceStatus
= RegisterServiceCtrlHandlerExW(ServiceNameU
.Buffer
,
790 RtlFreeUnicodeString(&ServiceNameU
);
792 return hServiceStatus
;
796 /**********************************************************************
797 * RegisterServiceCtrlHandlerExW
801 SERVICE_STATUS_HANDLE WINAPI
802 RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName
,
803 LPHANDLER_FUNCTION_EX lpHandlerProc
,
806 PACTIVE_SERVICE Service
;
808 TRACE("RegisterServiceCtrlHandlerExW(%s %p %p)\n",
809 debugstr_w(lpServiceName
), lpHandlerProc
, lpContext
);
811 Service
= ScLookupServiceByServiceName(lpServiceName
);
814 SetLastError(ERROR_SERVICE_NOT_IN_EXE
);
820 SetLastError(ERROR_INVALID_PARAMETER
);
824 Service
->HandlerFunction
= NULL
;
825 Service
->HandlerFunctionEx
= lpHandlerProc
;
826 Service
->HandlerContext
= lpContext
;
828 TRACE("RegisterServiceCtrlHandlerEx returning %p\n", Service
->hServiceStatus
);
830 return Service
->hServiceStatus
;
834 /**********************************************************************
835 * I_ScIsSecurityProcess
843 I_ScIsSecurityProcess(VOID
)
845 FIXME("I_ScIsSecurityProcess()\n");
849 /**********************************************************************
850 * I_ScPnPGetServiceName
858 I_ScPnPGetServiceName(IN SERVICE_STATUS_HANDLE hServiceStatus
,
859 OUT LPWSTR lpServiceName
,
860 IN DWORD cchServiceName
)
864 TRACE("I_ScPnPGetServiceName(%lu %p %lu)\n",
865 hServiceStatus
, lpServiceName
, cchServiceName
);
867 for (i
= 0; i
< dwActiveServiceCount
; i
++)
869 if (lpActiveServices
[i
].hServiceStatus
== hServiceStatus
)
871 wcscpy(lpServiceName
, lpActiveServices
[i
].ServiceName
.Buffer
);
872 return ERROR_SUCCESS
;
876 return ERROR_SERVICE_NOT_IN_EXE
;
880 /**********************************************************************
881 * I_ScSetServiceBitsA
888 I_ScSetServiceBitsA(SERVICE_STATUS_HANDLE hServiceStatus
,
891 BOOL bUpdateImmediately
,
896 TRACE("I_ScSetServiceBitsA(%lu %lx %u %u %s)\n",
897 hServiceStatus
, dwServiceBits
, bSetBitsOn
, bUpdateImmediately
,
898 debugstr_a(lpString
));
902 bResult
= RI_ScSetServiceBitsA((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
908 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
910 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
919 /**********************************************************************
920 * I_ScSetServiceBitsW
927 I_ScSetServiceBitsW(SERVICE_STATUS_HANDLE hServiceStatus
,
930 BOOL bUpdateImmediately
,
935 TRACE("I_ScSetServiceBitsW(%lu %lx %u %u %s)\n",
936 hServiceStatus
, dwServiceBits
, bSetBitsOn
, bUpdateImmediately
,
937 debugstr_w(lpString
));
941 bResult
= RI_ScSetServiceBitsW((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
947 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
949 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
958 /**********************************************************************
964 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus
,
967 BOOL bUpdateImmediately
)
969 TRACE("SetServiceBits(%lu %lx %u %u)\n",
970 hServiceStatus
, dwServiceBits
, bSetBitsOn
, bUpdateImmediately
);
972 return I_ScSetServiceBitsW(hServiceStatus
,
980 /**********************************************************************
986 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus
,
987 LPSERVICE_STATUS lpServiceStatus
)
991 TRACE("SetServiceStatus(%lu %p)\n",
992 hServiceStatus
, lpServiceStatus
);
996 dwError
= RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE
)hServiceStatus
,
999 RpcExcept(EXCEPTION_EXECUTE_HANDLER
)
1001 dwError
= ScmRpcStatusToWinError(RpcExceptionCode());
1005 if (dwError
!= ERROR_SUCCESS
)
1007 ERR("RSetServiceStatus() failed (Error %lu)\n", dwError
);
1008 SetLastError(dwError
);
1012 TRACE("SetServiceStatus() done\n");
1018 /**********************************************************************
1019 * StartServiceCtrlDispatcherA
1024 StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA
*lpServiceStartTable
)
1029 PSCM_CONTROL_PACKET ControlPacket
;
1033 TRACE("StartServiceCtrlDispatcherA(%p)\n",
1034 lpServiceStartTable
);
1037 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
1042 dwActiveServiceCount
= i
;
1044 /* Allocate the service table */
1045 lpActiveServices
= RtlAllocateHeap(RtlGetProcessHeap(),
1047 dwActiveServiceCount
* sizeof(ACTIVE_SERVICE
));
1048 if (lpActiveServices
== NULL
)
1050 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1054 /* Copy service names and start procedure */
1055 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1057 RtlCreateUnicodeStringFromAsciiz(&lpActiveServices
[i
].ServiceName
,
1058 lpServiceStartTable
[i
].lpServiceName
);
1059 lpActiveServices
[i
].ServiceMain
.A
= lpServiceStartTable
[i
].lpServiceProc
;
1060 lpActiveServices
[i
].hServiceStatus
= NULL
;
1061 lpActiveServices
[i
].bUnicode
= FALSE
;
1062 lpActiveServices
[i
].bOwnProcess
= FALSE
;
1065 /* Connect to the SCM */
1066 dwError
= ScConnectControlPipe(&hPipe
);
1067 if (dwError
!= ERROR_SUCCESS
)
1073 dwBufSize
= sizeof(SCM_CONTROL_PACKET
) +
1074 (MAX_SERVICE_NAME_LENGTH
+ 1) * sizeof(WCHAR
);
1076 ControlPacket
= RtlAllocateHeap(RtlGetProcessHeap(),
1079 if (ControlPacket
== NULL
)
1081 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1086 ScCreateStatusBinding();
1088 /* Call the dispatcher loop */
1089 ScServiceDispatcher(hPipe
, ControlPacket
, dwBufSize
);
1092 ScDestroyStatusBinding();
1094 /* Close the connection */
1097 /* Free the control packet */
1098 RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket
);
1101 /* Free the service table */
1102 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1104 RtlFreeUnicodeString(&lpActiveServices
[i
].ServiceName
);
1106 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
1107 lpActiveServices
= NULL
;
1108 dwActiveServiceCount
= 0;
1111 SetLastError(dwError
);
1117 /**********************************************************************
1118 * StartServiceCtrlDispatcherW
1123 StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW
*lpServiceStartTable
)
1128 PSCM_CONTROL_PACKET ControlPacket
;
1132 TRACE("StartServiceCtrlDispatcherW(%p)\n",
1133 lpServiceStartTable
);
1136 while (lpServiceStartTable
[i
].lpServiceProc
!= NULL
)
1141 dwActiveServiceCount
= i
;
1143 /* Allocate the service table */
1144 lpActiveServices
= RtlAllocateHeap(RtlGetProcessHeap(),
1146 dwActiveServiceCount
* sizeof(ACTIVE_SERVICE
));
1147 if (lpActiveServices
== NULL
)
1149 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
1153 /* Copy service names and start procedure */
1154 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1156 RtlCreateUnicodeString(&lpActiveServices
[i
].ServiceName
,
1157 lpServiceStartTable
[i
].lpServiceName
);
1158 lpActiveServices
[i
].ServiceMain
.W
= lpServiceStartTable
[i
].lpServiceProc
;
1159 lpActiveServices
[i
].hServiceStatus
= NULL
;
1160 lpActiveServices
[i
].bUnicode
= TRUE
;
1161 lpActiveServices
[i
].bOwnProcess
= FALSE
;
1164 /* Connect to the SCM */
1165 dwError
= ScConnectControlPipe(&hPipe
);
1166 if (dwError
!= ERROR_SUCCESS
)
1172 dwBufSize
= sizeof(SCM_CONTROL_PACKET
) +
1173 (MAX_SERVICE_NAME_LENGTH
+ 1) * sizeof(WCHAR
);
1175 ControlPacket
= RtlAllocateHeap(RtlGetProcessHeap(),
1178 if (ControlPacket
== NULL
)
1180 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1185 ScCreateStatusBinding();
1187 /* Call the dispatcher loop */
1188 ScServiceDispatcher(hPipe
, ControlPacket
, dwBufSize
);
1190 ScDestroyStatusBinding();
1192 /* Close the connection */
1195 /* Free the control packet */
1196 RtlFreeHeap(RtlGetProcessHeap(), 0, ControlPacket
);
1199 /* Free the service table */
1200 for (i
= 0; i
< dwActiveServiceCount
; i
++)
1202 RtlFreeUnicodeString(&lpActiveServices
[i
].ServiceName
);
1204 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices
);
1205 lpActiveServices
= NULL
;
1206 dwActiveServiceCount
= 0;
1209 SetLastError(dwError
);