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