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