- Go away STDCALL, time has come for WINAPI and NTAPI
[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 (Error %lu)\n", 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)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)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("Unknown command %lu", ControlPacket->dwControl);
399 continue;
400 }
401
402 if (dwRunningServices == 0)
403 break;
404 }
405
406 HeapFree(GetProcessHeap(),
407 0,
408 ControlPacket);
409
410 return TRUE;
411 }
412
413
414 /**********************************************************************
415 * RegisterServiceCtrlHandlerA
416 *
417 * @implemented
418 */
419 SERVICE_STATUS_HANDLE WINAPI
420 RegisterServiceCtrlHandlerA(LPCSTR lpServiceName,
421 LPHANDLER_FUNCTION lpHandlerProc)
422 {
423 ANSI_STRING ServiceNameA;
424 UNICODE_STRING ServiceNameU;
425 SERVICE_STATUS_HANDLE SHandle;
426
427 RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
428 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
429 {
430 SetLastError(ERROR_OUTOFMEMORY);
431 return (SERVICE_STATUS_HANDLE)0;
432 }
433
434 SHandle = RegisterServiceCtrlHandlerW(ServiceNameU.Buffer,
435 lpHandlerProc);
436
437 RtlFreeUnicodeString(&ServiceNameU);
438
439 return SHandle;
440 }
441
442
443 /**********************************************************************
444 * RegisterServiceCtrlHandlerW
445 *
446 * @implemented
447 */
448 SERVICE_STATUS_HANDLE WINAPI
449 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName,
450 LPHANDLER_FUNCTION lpHandlerProc)
451 {
452 PACTIVE_SERVICE Service;
453
454 Service = ScLookupServiceByServiceName((LPWSTR)lpServiceName);
455 if (Service == NULL)
456 {
457 return (SERVICE_STATUS_HANDLE)NULL;
458 }
459
460 Service->HandlerFunction = lpHandlerProc;
461 Service->HandlerFunctionEx = NULL;
462
463 TRACE("RegisterServiceCtrlHandler returning %lu\n", Service->hService);
464
465 return (SERVICE_STATUS_HANDLE)Service->hService;
466 }
467
468
469 /**********************************************************************
470 * RegisterServiceCtrlHandlerExA
471 *
472 * @implemented
473 */
474 SERVICE_STATUS_HANDLE WINAPI
475 RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName,
476 LPHANDLER_FUNCTION_EX lpHandlerProc,
477 LPVOID lpContext)
478 {
479 ANSI_STRING ServiceNameA;
480 UNICODE_STRING ServiceNameU;
481 SERVICE_STATUS_HANDLE SHandle;
482
483 RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
484 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
485 {
486 SetLastError(ERROR_OUTOFMEMORY);
487 return (SERVICE_STATUS_HANDLE)0;
488 }
489
490 SHandle = RegisterServiceCtrlHandlerExW(ServiceNameU.Buffer,
491 lpHandlerProc,
492 lpContext);
493
494 RtlFreeUnicodeString(&ServiceNameU);
495
496 return SHandle;
497 }
498
499
500 /**********************************************************************
501 * RegisterServiceCtrlHandlerExW
502 *
503 * @implemented
504 */
505 SERVICE_STATUS_HANDLE WINAPI
506 RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName,
507 LPHANDLER_FUNCTION_EX lpHandlerProc,
508 LPVOID lpContext)
509 {
510 PACTIVE_SERVICE Service;
511
512 Service = ScLookupServiceByServiceName(lpServiceName);
513 if (Service == NULL)
514 {
515 return (SERVICE_STATUS_HANDLE)NULL;
516 }
517
518 Service->HandlerFunction = NULL;
519 Service->HandlerFunctionEx = lpHandlerProc;
520 Service->HandlerContext = lpContext;
521
522 TRACE("RegisterServiceCtrlHandlerEx returning %lu", Service->hService);
523
524 return (SERVICE_STATUS_HANDLE)Service->hService;
525 }
526
527
528 /**********************************************************************
529 * I_ScSetServiceBitsA
530 *
531 * Undocumented
532 *
533 * @implemented
534 */
535 BOOL WINAPI
536 I_ScSetServiceBitsA(SERVICE_STATUS_HANDLE hServiceStatus,
537 DWORD dwServiceBits,
538 BOOL bSetBitsOn,
539 BOOL bUpdateImmediately,
540 LPSTR lpString)
541 {
542 BOOL bResult;
543
544 _SEH2_TRY
545 {
546 /* Call to services.exe using RPC */
547 bResult = RI_ScSetServiceBitsA((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
548 dwServiceBits,
549 bSetBitsOn,
550 bUpdateImmediately,
551 lpString);
552 }
553 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
554 {
555 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
556 bResult = FALSE;
557 }
558 _SEH2_END;
559
560 return bResult;
561 }
562
563
564 /**********************************************************************
565 * I_ScSetServiceBitsW
566 *
567 * Undocumented
568 *
569 * @implemented
570 */
571 BOOL WINAPI
572 I_ScSetServiceBitsW(SERVICE_STATUS_HANDLE hServiceStatus,
573 DWORD dwServiceBits,
574 BOOL bSetBitsOn,
575 BOOL bUpdateImmediately,
576 LPWSTR lpString)
577 {
578 BOOL bResult;
579
580 _SEH2_TRY
581 {
582 /* Call to services.exe using RPC */
583 bResult = RI_ScSetServiceBitsW((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
584 dwServiceBits,
585 bSetBitsOn,
586 bUpdateImmediately,
587 lpString);
588 }
589 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
590 {
591 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
592 bResult = FALSE;
593 }
594 _SEH2_END;
595
596 return bResult;
597 }
598
599
600 /**********************************************************************
601 * SetServiceBits
602 *
603 * @implemented
604 */
605 BOOL WINAPI
606 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus,
607 DWORD dwServiceBits,
608 BOOL bSetBitsOn,
609 BOOL bUpdateImmediately)
610 {
611 return I_ScSetServiceBitsW(hServiceStatus,
612 dwServiceBits,
613 bSetBitsOn,
614 bUpdateImmediately,
615 NULL);
616 }
617
618
619 /**********************************************************************
620 * SetServiceStatus
621 *
622 * @implemented
623 */
624 BOOL WINAPI
625 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus,
626 LPSERVICE_STATUS lpServiceStatus)
627 {
628 DWORD dwError;
629
630 TRACE("SetServiceStatus() called\n");
631 TRACE("hServiceStatus %lu\n", hServiceStatus);
632
633 /* Call to services.exe using RPC */
634 dwError = RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
635 lpServiceStatus);
636 if (dwError != ERROR_SUCCESS)
637 {
638 ERR("ScmrSetServiceStatus() failed (Error %lu)\n", dwError);
639 SetLastError(dwError);
640 return FALSE;
641 }
642
643 TRACE("SetServiceStatus() done (ret %lu)\n", dwError);
644
645 return TRUE;
646 }
647
648
649 /**********************************************************************
650 * StartServiceCtrlDispatcherA
651 *
652 * @implemented
653 */
654 BOOL WINAPI
655 StartServiceCtrlDispatcherA(LPSERVICE_TABLE_ENTRYA lpServiceStartTable)
656 {
657 ULONG i;
658 HANDLE hPipe;
659 DWORD dwError;
660 PUCHAR lpMessageBuffer;
661
662 TRACE("StartServiceCtrlDispatcherA() called\n");
663
664 i = 0;
665 while (lpServiceStartTable[i].lpServiceProc != NULL)
666 {
667 i++;
668 }
669
670 dwActiveServiceCount = i;
671 lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
672 HEAP_ZERO_MEMORY,
673 dwActiveServiceCount * sizeof(ACTIVE_SERVICE));
674 if (lpActiveServices == NULL)
675 {
676 return FALSE;
677 }
678
679 /* Copy service names and start procedure */
680 for (i = 0; i < dwActiveServiceCount; i++)
681 {
682 RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName,
683 lpServiceStartTable[i].lpServiceName);
684 lpActiveServices[i].Main.lpFuncA = lpServiceStartTable[i].lpServiceProc;
685 lpActiveServices[i].hService = (CLIENT_HANDLE)&lpActiveServices[i];
686 lpActiveServices[i].bUnicode = FALSE;
687 }
688
689 dwError = ScConnectControlPipe(&hPipe);
690 if (dwError != ERROR_SUCCESS)
691 {
692 /* Free the service table */
693 for (i = 0; i < dwActiveServiceCount; i++)
694 {
695 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
696 }
697 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
698 lpActiveServices = NULL;
699 dwActiveServiceCount = 0;
700 return FALSE;
701 }
702
703 lpMessageBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
704 HEAP_ZERO_MEMORY,
705 256);
706 if (lpMessageBuffer == NULL)
707 {
708 /* Free the service table */
709 for (i = 0; i < dwActiveServiceCount; i++)
710 {
711 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
712 }
713 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
714 lpActiveServices = NULL;
715 dwActiveServiceCount = 0;
716 CloseHandle(hPipe);
717 return FALSE;
718 }
719
720 ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
721 CloseHandle(hPipe);
722
723 /* Free the message buffer */
724 RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer);
725
726 /* Free the service table */
727 for (i = 0; i < dwActiveServiceCount; i++)
728 {
729 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
730 }
731 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
732 lpActiveServices = NULL;
733 dwActiveServiceCount = 0;
734
735 return TRUE;
736 }
737
738
739 /**********************************************************************
740 * StartServiceCtrlDispatcherW
741 *
742 * @implemented
743 */
744 BOOL WINAPI
745 StartServiceCtrlDispatcherW(LPSERVICE_TABLE_ENTRYW lpServiceStartTable)
746 {
747 ULONG i;
748 HANDLE hPipe;
749 DWORD dwError;
750 PUCHAR lpMessageBuffer;
751
752 TRACE("StartServiceCtrlDispatcherW() called\n");
753
754 i = 0;
755 while (lpServiceStartTable[i].lpServiceProc != NULL)
756 {
757 i++;
758 }
759
760 dwActiveServiceCount = i;
761 lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
762 HEAP_ZERO_MEMORY,
763 dwActiveServiceCount * sizeof(ACTIVE_SERVICE));
764 if (lpActiveServices == NULL)
765 {
766 return FALSE;
767 }
768
769 /* Copy service names and start procedure */
770 for (i = 0; i < dwActiveServiceCount; i++)
771 {
772 RtlCreateUnicodeString(&lpActiveServices[i].ServiceName,
773 lpServiceStartTable[i].lpServiceName);
774 lpActiveServices[i].Main.lpFuncW = lpServiceStartTable[i].lpServiceProc;
775 lpActiveServices[i].hService = (CLIENT_HANDLE)&lpActiveServices[i];
776 lpActiveServices[i].bUnicode = TRUE;
777 }
778
779 dwError = ScConnectControlPipe(&hPipe);
780 if (dwError != ERROR_SUCCESS)
781 {
782 /* Free the service table */
783 for (i = 0; i < dwActiveServiceCount; i++)
784 {
785 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
786 }
787 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
788 lpActiveServices = NULL;
789 dwActiveServiceCount = 0;
790 return FALSE;
791 }
792
793 lpMessageBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
794 HEAP_ZERO_MEMORY,
795 256);
796 if (lpMessageBuffer == NULL)
797 {
798 /* Free the service table */
799 for (i = 0; i < dwActiveServiceCount; i++)
800 {
801 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
802 }
803 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
804 lpActiveServices = NULL;
805 dwActiveServiceCount = 0;
806 CloseHandle(hPipe);
807 return FALSE;
808 }
809
810 ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
811 CloseHandle(hPipe);
812
813 /* Free the message buffer */
814 RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer);
815
816 /* Free the service table */
817 for (i = 0; i < dwActiveServiceCount; i++)
818 {
819 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
820 }
821 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
822 lpActiveServices = NULL;
823 dwActiveServiceCount = 0;
824
825 return TRUE;
826 }
827
828 /* EOF */