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