c77f133ee4953435cea73647788298d36561b803
[reactos.git] / reactos / dll / win32 / advapi32 / service / sctrl.c
1 /*
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>
9 *
10 */
11
12
13 /* INCLUDES ******************************************************************/
14
15 #include <advapi32.h>
16 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
17
18
19 /* TYPES *********************************************************************/
20
21 typedef struct _ACTIVE_SERVICE
22 {
23 SERVICE_STATUS_HANDLE hServiceStatus;
24 UNICODE_STRING ServiceName;
25 union
26 {
27 LPSERVICE_MAIN_FUNCTIONA lpFuncA;
28 LPSERVICE_MAIN_FUNCTIONW lpFuncW;
29 } Main;
30 LPHANDLER_FUNCTION HandlerFunction;
31 LPHANDLER_FUNCTION_EX HandlerFunctionEx;
32 LPVOID HandlerContext;
33 BOOL bUnicode;
34 LPWSTR Arguments;
35 } ACTIVE_SERVICE, *PACTIVE_SERVICE;
36
37
38 /* GLOBALS *******************************************************************/
39
40 static DWORD dwActiveServiceCount = 0;
41 static PACTIVE_SERVICE lpActiveServices = NULL;
42 static handle_t hStatusBinding = NULL;
43
44
45 /* FUNCTIONS *****************************************************************/
46
47 handle_t __RPC_USER
48 RPC_SERVICE_STATUS_HANDLE_bind(RPC_SERVICE_STATUS_HANDLE hServiceStatus)
49 {
50 return hStatusBinding;
51 }
52
53
54 void __RPC_USER
55 RPC_SERVICE_STATUS_HANDLE_unbind(RPC_SERVICE_STATUS_HANDLE hServiceStatus,
56 handle_t hBinding)
57 {
58 }
59
60
61 static RPC_STATUS
62 ScCreateStatusBinding(VOID)
63 {
64 LPWSTR pszStringBinding;
65 RPC_STATUS status;
66
67 TRACE("ScCreateStatusBinding() called\n");
68
69 status = RpcStringBindingComposeW(NULL,
70 L"ncacn_np",
71 NULL,
72 L"\\pipe\\ntsvcs",
73 NULL,
74 &pszStringBinding);
75 if (status != RPC_S_OK)
76 {
77 ERR("RpcStringBindingCompose returned 0x%x\n", status);
78 return status;
79 }
80
81 /* Set the binding handle that will be used to bind to the server. */
82 status = RpcBindingFromStringBindingW(pszStringBinding,
83 &hStatusBinding);
84 if (status != RPC_S_OK)
85 {
86 ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
87 }
88
89 status = RpcStringFreeW(&pszStringBinding);
90 if (status != RPC_S_OK)
91 {
92 ERR("RpcStringFree returned 0x%x\n", status);
93 }
94
95 return status;
96 }
97
98
99 static RPC_STATUS
100 ScDestroyStatusBinding(VOID)
101 {
102 RPC_STATUS status;
103
104 TRACE("ScDestroyStatusBinding() called\n");
105
106 if (hStatusBinding == NULL)
107 return RPC_S_OK;
108
109 status = RpcBindingFree(&hStatusBinding);
110 if (status != RPC_S_OK)
111 {
112 ERR("RpcBindingFree returned 0x%x\n", status);
113 }
114 else
115 {
116 hStatusBinding = NULL;
117 }
118
119 return status;
120 }
121
122
123 static PACTIVE_SERVICE
124 ScLookupServiceByServiceName(LPCWSTR lpServiceName)
125 {
126 DWORD i;
127
128 TRACE("ScLookupServiceByServiceName(%S) called\n", lpServiceName);
129
130 for (i = 0; i < dwActiveServiceCount; i++)
131 {
132 TRACE("Checking %S\n", lpActiveServices[i].ServiceName.Buffer);
133 if (_wcsicmp(lpActiveServices[i].ServiceName.Buffer, lpServiceName) == 0)
134 {
135 TRACE("Found!\n");
136 return &lpActiveServices[i];
137 }
138 }
139
140 TRACE("No service found!\n");
141
142 SetLastError(ERROR_SERVICE_DOES_NOT_EXIST);
143
144 return NULL;
145 }
146
147
148 static DWORD WINAPI
149 ScServiceMainStub(LPVOID Context)
150 {
151 PACTIVE_SERVICE lpService;
152 DWORD dwArgCount = 0;
153 DWORD dwLength = 0;
154 DWORD dwLen;
155 LPWSTR lpPtr;
156
157 lpService = (PACTIVE_SERVICE)Context;
158
159 TRACE("ScServiceMainStub() called\n");
160
161 /* Count arguments */
162 lpPtr = lpService->Arguments;
163 while (*lpPtr)
164 {
165 TRACE("arg: %S\n", lpPtr);
166 dwLen = wcslen(lpPtr) + 1;
167 dwArgCount++;
168 dwLength += dwLen;
169 lpPtr += dwLen;
170 }
171 TRACE("dwArgCount: %ld\ndwLength: %ld\n", dwArgCount, dwLength);
172
173 /* Build the argument vector and call the main service routine */
174 if (lpService->bUnicode)
175 {
176 LPWSTR *lpArgVector;
177 LPWSTR Ptr;
178
179 lpArgVector = HeapAlloc(GetProcessHeap(),
180 HEAP_ZERO_MEMORY,
181 (dwArgCount + 1) * sizeof(LPWSTR));
182 if (lpArgVector == NULL)
183 return ERROR_OUTOFMEMORY;
184
185 dwArgCount = 0;
186 Ptr = lpService->Arguments;
187 while (*Ptr)
188 {
189 lpArgVector[dwArgCount] = Ptr;
190
191 dwArgCount++;
192 Ptr += (wcslen(Ptr) + 1);
193 }
194 lpArgVector[dwArgCount] = NULL;
195
196 (lpService->Main.lpFuncW)(dwArgCount, lpArgVector);
197
198 HeapFree(GetProcessHeap(),
199 0,
200 lpArgVector);
201 }
202 else
203 {
204 LPSTR *lpArgVector;
205 LPSTR Ptr;
206 LPSTR AnsiString;
207 DWORD AnsiLength;
208
209 AnsiLength = WideCharToMultiByte(CP_ACP,
210 0,
211 lpService->Arguments,
212 dwLength,
213 NULL,
214 0,
215 NULL,
216 NULL);
217 if (AnsiLength == 0)
218 return ERROR_INVALID_PARAMETER; /* ? */
219
220 AnsiString = HeapAlloc(GetProcessHeap(),
221 0,
222 AnsiLength + 1);
223 if (AnsiString == NULL)
224 return ERROR_OUTOFMEMORY;
225
226 WideCharToMultiByte(CP_ACP,
227 0,
228 lpService->Arguments,
229 dwLength,
230 AnsiString,
231 AnsiLength,
232 NULL,
233 NULL);
234
235 AnsiString[AnsiLength] = ANSI_NULL;
236
237 lpArgVector = HeapAlloc(GetProcessHeap(),
238 0,
239 (dwArgCount + 1) * sizeof(LPSTR));
240 if (lpArgVector == NULL)
241 {
242 HeapFree(GetProcessHeap(),
243 0,
244 AnsiString);
245 return ERROR_OUTOFMEMORY;
246 }
247
248 dwArgCount = 0;
249 Ptr = AnsiString;
250 while (*Ptr)
251 {
252 lpArgVector[dwArgCount] = Ptr;
253
254 dwArgCount++;
255 Ptr += (strlen(Ptr) + 1);
256 }
257 lpArgVector[dwArgCount] = NULL;
258
259 (lpService->Main.lpFuncA)(dwArgCount, lpArgVector);
260
261 HeapFree(GetProcessHeap(),
262 0,
263 lpArgVector);
264 HeapFree(GetProcessHeap(),
265 0,
266 AnsiString);
267 }
268
269 return ERROR_SUCCESS;
270 }
271
272
273 static DWORD
274 ScConnectControlPipe(HANDLE *hPipe)
275 {
276 DWORD dwBytesWritten;
277 DWORD dwState;
278 DWORD dwServiceCurrent = 0;
279 NTSTATUS Status;
280 WCHAR NtControlPipeName[MAX_PATH + 1];
281 RTL_QUERY_REGISTRY_TABLE QueryTable[2];
282 DWORD dwProcessId;
283
284 /* Get the service number and create the named pipe */
285 RtlZeroMemory(&QueryTable,
286 sizeof(QueryTable));
287
288 QueryTable[0].Name = L"";
289 QueryTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
290 QueryTable[0].EntryContext = &dwServiceCurrent;
291
292 Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL,
293 L"ServiceCurrent",
294 QueryTable,
295 NULL,
296 NULL);
297
298 if (!NT_SUCCESS(Status))
299 {
300 ERR("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
301 return RtlNtStatusToDosError(Status);
302 }
303
304 swprintf(NtControlPipeName, L"\\\\.\\pipe\\net\\NtControlPipe%u", dwServiceCurrent);
305
306 if (!WaitNamedPipeW(NtControlPipeName, 15000))
307 {
308 ERR("WaitNamedPipe(%S) failed (Error %lu)\n", NtControlPipeName, GetLastError());
309 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
310 }
311
312 *hPipe = CreateFileW(NtControlPipeName,
313 GENERIC_READ | GENERIC_WRITE,
314 0,
315 NULL,
316 OPEN_EXISTING,
317 FILE_ATTRIBUTE_NORMAL,
318 NULL);
319 if (*hPipe == INVALID_HANDLE_VALUE)
320 {
321 ERR("CreateFileW() failed for pipe %S (Error %lu)\n", NtControlPipeName, GetLastError());
322 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
323 }
324
325 dwState = PIPE_READMODE_MESSAGE;
326 if (!SetNamedPipeHandleState(*hPipe, &dwState, NULL, NULL))
327 {
328 CloseHandle(*hPipe);
329 *hPipe = INVALID_HANDLE_VALUE;
330 return ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
331 }
332
333 /* Pass the ProcessId to the SCM */
334 dwProcessId = GetCurrentProcessId();
335 WriteFile(*hPipe,
336 &dwProcessId,
337 sizeof(DWORD),
338 &dwBytesWritten,
339 NULL);
340
341 TRACE("Sent Process ID %lu\n", dwProcessId);
342
343 return ERROR_SUCCESS;
344 }
345
346
347 static DWORD
348 ScStartService(PACTIVE_SERVICE lpService,
349 PSCM_CONTROL_PACKET ControlPacket)
350 {
351 HANDLE ThreadHandle;
352 DWORD ThreadId;
353 PWSTR pServiceName;
354 PWSTR Ptr;
355 DWORD dwArgumentsSize;
356
357 TRACE("ScStartService() called\n");
358 TRACE("Size: %lu\n", ControlPacket->dwSize);
359 TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
360
361 /* Set the service status handle */
362 lpService->hServiceStatus = ControlPacket->hServiceStatus;
363
364 pServiceName = (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
365
366 /* Get the service name size */
367 dwArgumentsSize = (wcslen(pServiceName) + 1) * sizeof(WCHAR);
368
369 /* Get the size of the service start arguments */
370 if (ControlPacket->dwArgumentsCount > 0 &&
371 ControlPacket->dwArgumentsOffset != 0)
372 {
373 /* FIXME */
374 #if 0
375 dwArgumentSize += (wcslen(...) + 1) * sizeof(WCHAR);
376 #endif
377 }
378
379 lpService->Arguments = HeapAlloc(GetProcessHeap(),
380 HEAP_ZERO_MEMORY,
381 dwArgumentsSize + sizeof(WCHAR));
382 if (lpService->Arguments == NULL)
383 return ERROR_OUTOFMEMORY;
384
385 Ptr = lpService->Arguments;
386
387 /* Add the service name as first argument */
388 wcscpy(Ptr, pServiceName);
389 Ptr += (wcslen(pServiceName) + 1);
390
391 /* Add service start arguments */
392 if (ControlPacket->dwArgumentsCount > 0 &&
393 ControlPacket->dwArgumentsOffset != 0)
394 {
395 /* FIXME */
396 }
397
398 *Ptr = 0;
399
400 /* invoke the services entry point and implement the command loop */
401 ThreadHandle = CreateThread(NULL,
402 0,
403 ScServiceMainStub,
404 lpService,
405 CREATE_SUSPENDED,
406 &ThreadId);
407 if (ThreadHandle == NULL)
408 return ERROR_SERVICE_NO_THREAD;
409
410 ResumeThread(ThreadHandle);
411 CloseHandle(ThreadHandle);
412
413 return ERROR_SUCCESS;
414 }
415
416
417 static DWORD
418 ScControlService(PACTIVE_SERVICE lpService,
419 PSCM_CONTROL_PACKET ControlPacket)
420 {
421 TRACE("ScControlService() called\n");
422 TRACE("Size: %lu\n", ControlPacket->dwSize);
423 TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
424
425 if (lpService->HandlerFunction)
426 {
427 (lpService->HandlerFunction)(ControlPacket->dwControl);
428 }
429 else if (lpService->HandlerFunctionEx)
430 {
431 /* FIXME: send correct params */
432 (lpService->HandlerFunctionEx)(ControlPacket->dwControl, 0, NULL, NULL);
433 }
434
435 if (ControlPacket->dwControl == SERVICE_CONTROL_STOP)
436 {
437 HeapFree(GetProcessHeap(),
438 0,
439 lpService->Arguments);
440 }
441
442 TRACE("ScControlService() done\n");
443
444 return ERROR_SUCCESS;
445 }
446
447
448 static BOOL
449 ScServiceDispatcher(HANDLE hPipe,
450 PUCHAR lpBuffer,
451 DWORD dwBufferSize)
452 {
453 PSCM_CONTROL_PACKET ControlPacket;
454 DWORD Count;
455 BOOL bResult;
456 DWORD dwRunningServices = 0;
457 LPWSTR lpServiceName;
458 PACTIVE_SERVICE lpService;
459 SCM_REPLY_PACKET ReplyPacket;
460 DWORD dwError;
461
462 TRACE("ScDispatcherLoop() called\n");
463
464 ControlPacket = HeapAlloc(GetProcessHeap(),
465 HEAP_ZERO_MEMORY,
466 1024);
467 if (ControlPacket == NULL)
468 return FALSE;
469
470 while (TRUE)
471 {
472 /* Read command from the control pipe */
473 bResult = ReadFile(hPipe,
474 ControlPacket,
475 1024,
476 &Count,
477 NULL);
478 if (bResult == FALSE)
479 {
480 ERR("Pipe read failed (Error: %lu)\n", GetLastError());
481 return FALSE;
482 }
483
484 lpServiceName = (LPWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
485 TRACE("Service: %S\n", lpServiceName);
486
487 lpService = ScLookupServiceByServiceName(lpServiceName);
488 if (lpService != NULL)
489 {
490 /* Execute command */
491 switch (ControlPacket->dwControl)
492 {
493 case SERVICE_CONTROL_START:
494 TRACE("Start command - recieved SERVICE_CONTROL_START\n");
495 dwError = ScStartService(lpService, ControlPacket);
496 if (dwError == ERROR_SUCCESS)
497 dwRunningServices++;
498 break;
499
500 case SERVICE_CONTROL_STOP:
501 TRACE("Stop command - recieved SERVICE_CONTROL_STOP\n");
502 dwError = ScControlService(lpService, ControlPacket);
503 if (dwError == ERROR_SUCCESS)
504 dwRunningServices--;
505 break;
506
507 default:
508 TRACE("Command %lu received", ControlPacket->dwControl);
509 dwError = ScControlService(lpService, ControlPacket);
510 break;
511 }
512 }
513 else
514 {
515 dwError = ERROR_SERVICE_DOES_NOT_EXIST;
516 }
517
518 ReplyPacket.dwError = dwError;
519
520 /* Send the reply packet */
521 bResult = WriteFile(hPipe,
522 &ReplyPacket,
523 sizeof(ReplyPacket),
524 &Count,
525 NULL);
526 if (bResult == FALSE)
527 {
528 ERR("Pipe write failed (Error: %lu)\n", GetLastError());
529 return FALSE;
530 }
531
532 if (dwRunningServices == 0)
533 break;
534 }
535
536 HeapFree(GetProcessHeap(),
537 0,
538 ControlPacket);
539
540 return TRUE;
541 }
542
543
544 /**********************************************************************
545 * RegisterServiceCtrlHandlerA
546 *
547 * @implemented
548 */
549 SERVICE_STATUS_HANDLE WINAPI
550 RegisterServiceCtrlHandlerA(LPCSTR lpServiceName,
551 LPHANDLER_FUNCTION lpHandlerProc)
552 {
553 ANSI_STRING ServiceNameA;
554 UNICODE_STRING ServiceNameU;
555 SERVICE_STATUS_HANDLE SHandle;
556
557 RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
558 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
559 {
560 SetLastError(ERROR_OUTOFMEMORY);
561 return (SERVICE_STATUS_HANDLE)0;
562 }
563
564 SHandle = RegisterServiceCtrlHandlerW(ServiceNameU.Buffer,
565 lpHandlerProc);
566
567 RtlFreeUnicodeString(&ServiceNameU);
568
569 return SHandle;
570 }
571
572
573 /**********************************************************************
574 * RegisterServiceCtrlHandlerW
575 *
576 * @implemented
577 */
578 SERVICE_STATUS_HANDLE WINAPI
579 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName,
580 LPHANDLER_FUNCTION lpHandlerProc)
581 {
582 PACTIVE_SERVICE Service;
583
584 Service = ScLookupServiceByServiceName((LPWSTR)lpServiceName);
585 if (Service == NULL)
586 {
587 return (SERVICE_STATUS_HANDLE)NULL;
588 }
589
590 Service->HandlerFunction = lpHandlerProc;
591 Service->HandlerFunctionEx = NULL;
592
593 TRACE("RegisterServiceCtrlHandler returning %lu\n", Service->hServiceStatus);
594
595 return Service->hServiceStatus;
596 }
597
598
599 /**********************************************************************
600 * RegisterServiceCtrlHandlerExA
601 *
602 * @implemented
603 */
604 SERVICE_STATUS_HANDLE WINAPI
605 RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName,
606 LPHANDLER_FUNCTION_EX lpHandlerProc,
607 LPVOID lpContext)
608 {
609 ANSI_STRING ServiceNameA;
610 UNICODE_STRING ServiceNameU;
611 SERVICE_STATUS_HANDLE SHandle;
612
613 RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
614 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
615 {
616 SetLastError(ERROR_OUTOFMEMORY);
617 return (SERVICE_STATUS_HANDLE)0;
618 }
619
620 SHandle = RegisterServiceCtrlHandlerExW(ServiceNameU.Buffer,
621 lpHandlerProc,
622 lpContext);
623
624 RtlFreeUnicodeString(&ServiceNameU);
625
626 return SHandle;
627 }
628
629
630 /**********************************************************************
631 * RegisterServiceCtrlHandlerExW
632 *
633 * @implemented
634 */
635 SERVICE_STATUS_HANDLE WINAPI
636 RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName,
637 LPHANDLER_FUNCTION_EX lpHandlerProc,
638 LPVOID lpContext)
639 {
640 PACTIVE_SERVICE Service;
641
642 Service = ScLookupServiceByServiceName(lpServiceName);
643 if (Service == NULL)
644 {
645 return (SERVICE_STATUS_HANDLE)NULL;
646 }
647
648 Service->HandlerFunction = NULL;
649 Service->HandlerFunctionEx = lpHandlerProc;
650 Service->HandlerContext = lpContext;
651
652 TRACE("RegisterServiceCtrlHandlerEx returning %lu\n", Service->hServiceStatus);
653
654 return Service->hServiceStatus;
655 }
656
657
658 /**********************************************************************
659 * I_ScSetServiceBitsA
660 *
661 * Undocumented
662 *
663 * @implemented
664 */
665 BOOL WINAPI
666 I_ScSetServiceBitsA(SERVICE_STATUS_HANDLE hServiceStatus,
667 DWORD dwServiceBits,
668 BOOL bSetBitsOn,
669 BOOL bUpdateImmediately,
670 LPSTR lpString)
671 {
672 BOOL bResult;
673
674 RpcTryExcept
675 {
676 /* Call to services.exe using RPC */
677 bResult = RI_ScSetServiceBitsA((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
678 dwServiceBits,
679 bSetBitsOn,
680 bUpdateImmediately,
681 lpString);
682 }
683 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
684 {
685 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
686 bResult = FALSE;
687 }
688 RpcEndExcept;
689
690 return bResult;
691 }
692
693
694 /**********************************************************************
695 * I_ScSetServiceBitsW
696 *
697 * Undocumented
698 *
699 * @implemented
700 */
701 BOOL WINAPI
702 I_ScSetServiceBitsW(SERVICE_STATUS_HANDLE hServiceStatus,
703 DWORD dwServiceBits,
704 BOOL bSetBitsOn,
705 BOOL bUpdateImmediately,
706 LPWSTR lpString)
707 {
708 BOOL bResult;
709
710 RpcTryExcept
711 {
712 /* Call to services.exe using RPC */
713 bResult = RI_ScSetServiceBitsW((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
714 dwServiceBits,
715 bSetBitsOn,
716 bUpdateImmediately,
717 lpString);
718 }
719 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
720 {
721 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
722 bResult = FALSE;
723 }
724 RpcEndExcept;
725
726 return bResult;
727 }
728
729
730 /**********************************************************************
731 * SetServiceBits
732 *
733 * @implemented
734 */
735 BOOL WINAPI
736 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus,
737 DWORD dwServiceBits,
738 BOOL bSetBitsOn,
739 BOOL bUpdateImmediately)
740 {
741 return I_ScSetServiceBitsW(hServiceStatus,
742 dwServiceBits,
743 bSetBitsOn,
744 bUpdateImmediately,
745 NULL);
746 }
747
748
749 /**********************************************************************
750 * SetServiceStatus
751 *
752 * @implemented
753 */
754 BOOL WINAPI
755 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus,
756 LPSERVICE_STATUS lpServiceStatus)
757 {
758 DWORD dwError;
759
760 TRACE("SetServiceStatus() called\n");
761 TRACE("hServiceStatus %lu\n", hServiceStatus);
762
763 RpcTryExcept
764 {
765 /* Call to services.exe using RPC */
766 dwError = RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
767 lpServiceStatus);
768 }
769 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
770 {
771 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
772 }
773 RpcEndExcept;
774
775 if (dwError != ERROR_SUCCESS)
776 {
777 ERR("ScmrSetServiceStatus() failed (Error %lu)\n", dwError);
778 SetLastError(dwError);
779 return FALSE;
780 }
781
782 TRACE("SetServiceStatus() done (ret %lu)\n", dwError);
783
784 return TRUE;
785 }
786
787
788 /**********************************************************************
789 * StartServiceCtrlDispatcherA
790 *
791 * @implemented
792 */
793 BOOL WINAPI
794 StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA * lpServiceStartTable)
795 {
796 ULONG i;
797 HANDLE hPipe;
798 DWORD dwError;
799 PUCHAR lpMessageBuffer;
800
801 TRACE("StartServiceCtrlDispatcherA() called\n");
802
803 i = 0;
804 while (lpServiceStartTable[i].lpServiceProc != NULL)
805 {
806 i++;
807 }
808
809 dwActiveServiceCount = i;
810 lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
811 HEAP_ZERO_MEMORY,
812 dwActiveServiceCount * sizeof(ACTIVE_SERVICE));
813 if (lpActiveServices == NULL)
814 {
815 return FALSE;
816 }
817
818 /* Copy service names and start procedure */
819 for (i = 0; i < dwActiveServiceCount; i++)
820 {
821 RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName,
822 lpServiceStartTable[i].lpServiceName);
823 lpActiveServices[i].Main.lpFuncA = lpServiceStartTable[i].lpServiceProc;
824 lpActiveServices[i].hServiceStatus = 0;
825 lpActiveServices[i].bUnicode = FALSE;
826 }
827
828 dwError = ScConnectControlPipe(&hPipe);
829 if (dwError != ERROR_SUCCESS)
830 {
831 /* Free the service table */
832 for (i = 0; i < dwActiveServiceCount; i++)
833 {
834 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
835 }
836 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
837 lpActiveServices = NULL;
838 dwActiveServiceCount = 0;
839 return FALSE;
840 }
841
842 lpMessageBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
843 HEAP_ZERO_MEMORY,
844 256);
845 if (lpMessageBuffer == NULL)
846 {
847 /* Free the service table */
848 for (i = 0; i < dwActiveServiceCount; i++)
849 {
850 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
851 }
852 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
853 lpActiveServices = NULL;
854 dwActiveServiceCount = 0;
855 CloseHandle(hPipe);
856 return FALSE;
857 }
858
859 ScCreateStatusBinding();
860
861 ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
862
863 ScDestroyStatusBinding();
864
865 CloseHandle(hPipe);
866
867 /* Free the message buffer */
868 RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer);
869
870 /* Free the service table */
871 for (i = 0; i < dwActiveServiceCount; i++)
872 {
873 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
874 }
875 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
876 lpActiveServices = NULL;
877 dwActiveServiceCount = 0;
878
879 return TRUE;
880 }
881
882
883 /**********************************************************************
884 * StartServiceCtrlDispatcherW
885 *
886 * @implemented
887 */
888 BOOL WINAPI
889 StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW * lpServiceStartTable)
890 {
891 ULONG i;
892 HANDLE hPipe;
893 DWORD dwError;
894 PUCHAR lpMessageBuffer;
895
896 TRACE("StartServiceCtrlDispatcherW() called\n");
897
898 i = 0;
899 while (lpServiceStartTable[i].lpServiceProc != NULL)
900 {
901 i++;
902 }
903
904 dwActiveServiceCount = i;
905 lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
906 HEAP_ZERO_MEMORY,
907 dwActiveServiceCount * sizeof(ACTIVE_SERVICE));
908 if (lpActiveServices == NULL)
909 {
910 return FALSE;
911 }
912
913 /* Copy service names and start procedure */
914 for (i = 0; i < dwActiveServiceCount; i++)
915 {
916 RtlCreateUnicodeString(&lpActiveServices[i].ServiceName,
917 lpServiceStartTable[i].lpServiceName);
918 lpActiveServices[i].Main.lpFuncW = lpServiceStartTable[i].lpServiceProc;
919 lpActiveServices[i].hServiceStatus = 0;
920 lpActiveServices[i].bUnicode = TRUE;
921 }
922
923 dwError = ScConnectControlPipe(&hPipe);
924 if (dwError != ERROR_SUCCESS)
925 {
926 /* Free the service table */
927 for (i = 0; i < dwActiveServiceCount; i++)
928 {
929 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
930 }
931 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
932 lpActiveServices = NULL;
933 dwActiveServiceCount = 0;
934 return FALSE;
935 }
936
937 lpMessageBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
938 HEAP_ZERO_MEMORY,
939 256);
940 if (lpMessageBuffer == NULL)
941 {
942 /* Free the service table */
943 for (i = 0; i < dwActiveServiceCount; i++)
944 {
945 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
946 }
947 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
948 lpActiveServices = NULL;
949 dwActiveServiceCount = 0;
950 CloseHandle(hPipe);
951 return FALSE;
952 }
953
954 ScCreateStatusBinding();
955
956 ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
957
958 ScDestroyStatusBinding();
959
960 CloseHandle(hPipe);
961
962 /* Free the message buffer */
963 RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer);
964
965 /* Free the service table */
966 for (i = 0; i < dwActiveServiceCount; i++)
967 {
968 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
969 }
970 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
971 lpActiveServices = NULL;
972 dwActiveServiceCount = 0;
973
974 return TRUE;
975 }
976
977 /* EOF */