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