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