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