[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 ScBuildUnicodeArgsVector(PSCM_CONTROL_PACKET ControlPacket,
282 LPDWORD lpArgCount,
283 LPWSTR **lpArgVector)
284 {
285 LPWSTR *lpVector;
286 LPWSTR *lpArg;
287 DWORD i;
288
289 *lpArgCount = 0;
290 *lpArgVector = NULL;
291
292 if (ControlPacket->dwArgumentsCount > 0)
293 {
294 lpVector = HeapAlloc(GetProcessHeap(),
295 HEAP_ZERO_MEMORY,
296 ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
297 if (lpVector == NULL)
298 return ERROR_OUTOFMEMORY;
299
300 memcpy(lpVector,
301 ((PBYTE)ControlPacket + ControlPacket->dwArgumentsOffset),
302 ControlPacket->dwSize - ControlPacket->dwArgumentsOffset);
303
304 lpArg = lpVector;
305 for (i = 0; i < ControlPacket->dwArgumentsCount; i++)
306 {
307 *lpArg = (LPWSTR)((ULONG_PTR)lpArg + (ULONG_PTR)*lpArg);
308 lpArg++;
309 }
310
311 *lpArgCount = ControlPacket->dwArgumentsCount;
312 *lpArgVector = lpVector;
313 }
314
315 return ERROR_SUCCESS;
316 }
317
318
319 static DWORD
320 ScBuildAnsiArgsVector(PSCM_CONTROL_PACKET ControlPacket,
321 LPDWORD lpArgCount,
322 LPSTR **lpArgVector)
323 {
324 LPSTR *lpVector;
325 LPSTR *lpPtr;
326 LPWSTR lpUnicodeString;
327 LPSTR lpAnsiString;
328 DWORD dwVectorSize;
329 DWORD dwUnicodeSize;
330 DWORD dwAnsiSize;
331 DWORD i;
332
333 *lpArgCount = 0;
334 *lpArgVector = NULL;
335
336 if (ControlPacket->dwArgumentsCount > 0)
337 {
338 dwVectorSize = ControlPacket->dwArgumentsCount * sizeof(LPWSTR);
339
340 lpUnicodeString = (LPWSTR)((PBYTE)ControlPacket +
341 ControlPacket->dwArgumentsOffset +
342 dwVectorSize);
343 dwUnicodeSize = (ControlPacket->dwSize -
344 ControlPacket->dwArgumentsOffset -
345 dwVectorSize) / sizeof(WCHAR);
346
347 dwAnsiSize = WideCharToMultiByte(CP_ACP,
348 0,
349 lpUnicodeString,
350 dwUnicodeSize,
351 NULL,
352 0,
353 NULL,
354 NULL);
355
356 lpVector = HeapAlloc(GetProcessHeap(),
357 HEAP_ZERO_MEMORY,
358 dwVectorSize + dwAnsiSize);
359 if (lpVector == NULL)
360 return ERROR_OUTOFMEMORY;
361
362 lpPtr = (LPSTR*)lpVector;
363 lpAnsiString = (LPSTR)((ULONG_PTR)lpVector + dwVectorSize);
364
365 WideCharToMultiByte(CP_ACP,
366 0,
367 lpUnicodeString,
368 dwUnicodeSize,
369 lpAnsiString,
370 dwAnsiSize,
371 NULL,
372 NULL);
373
374 for (i = 0; i < ControlPacket->dwArgumentsCount; i++)
375 {
376 *lpPtr = lpAnsiString;
377
378 lpPtr++;
379 lpAnsiString += (strlen(lpAnsiString) + 1);
380 }
381
382 *lpArgCount = ControlPacket->dwArgumentsCount;
383 *lpArgVector = lpVector;
384 }
385
386 return ERROR_SUCCESS;
387 }
388
389
390 static DWORD
391 ScStartService(PACTIVE_SERVICE lpService,
392 PSCM_CONTROL_PACKET ControlPacket)
393 {
394 HANDLE ThreadHandle;
395 DWORD ThreadId;
396 DWORD dwError;
397
398 TRACE("ScStartService() called\n");
399 TRACE("Size: %lu\n", ControlPacket->dwSize);
400 TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
401
402 /* Set the service status handle */
403 lpService->hServiceStatus = ControlPacket->hServiceStatus;
404
405 /* Build the arguments vector */
406 if (lpService->bUnicode == TRUE)
407 {
408 dwError = ScBuildUnicodeArgsVector(ControlPacket,
409 &lpService->ThreadParams.W.dwArgCount,
410 &lpService->ThreadParams.W.lpArgVector);
411 }
412 else
413 {
414 dwError = ScBuildAnsiArgsVector(ControlPacket,
415 &lpService->ThreadParams.A.dwArgCount,
416 &lpService->ThreadParams.A.lpArgVector);
417 }
418
419 if (dwError != ERROR_SUCCESS)
420 return dwError;
421
422 /* Invoke the services entry point and implement the command loop */
423 ThreadHandle = CreateThread(NULL,
424 0,
425 ScServiceMainStub,
426 lpService,
427 CREATE_SUSPENDED,
428 &ThreadId);
429 if (ThreadHandle == NULL)
430 {
431 /* Free the arguments vector */
432 if (lpService->bUnicode)
433 {
434 if (lpService->ThreadParams.W.lpArgVector != NULL)
435 {
436 HeapFree(GetProcessHeap(),
437 0,
438 lpService->ThreadParams.W.lpArgVector);
439 lpService->ThreadParams.W.lpArgVector = NULL;
440 lpService->ThreadParams.W.dwArgCount = 0;
441 }
442 }
443 else
444 {
445 if (lpService->ThreadParams.A.lpArgVector != NULL)
446 {
447 HeapFree(GetProcessHeap(),
448 0,
449 lpService->ThreadParams.A.lpArgVector);
450 lpService->ThreadParams.A.lpArgVector = NULL;
451 lpService->ThreadParams.A.dwArgCount = 0;
452 }
453 }
454
455 return ERROR_SERVICE_NO_THREAD;
456 }
457
458 ResumeThread(ThreadHandle);
459 CloseHandle(ThreadHandle);
460
461 return ERROR_SUCCESS;
462 }
463
464
465 static DWORD
466 ScControlService(PACTIVE_SERVICE lpService,
467 PSCM_CONTROL_PACKET ControlPacket)
468 {
469 TRACE("ScControlService() called\n");
470 TRACE("Size: %lu\n", ControlPacket->dwSize);
471 TRACE("Service: %S\n", (PWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset));
472
473 if (lpService->HandlerFunction)
474 {
475 (lpService->HandlerFunction)(ControlPacket->dwControl);
476 }
477 else if (lpService->HandlerFunctionEx)
478 {
479 /* FIXME: send correct params */
480 (lpService->HandlerFunctionEx)(ControlPacket->dwControl, 0, NULL, NULL);
481 }
482
483 TRACE("ScControlService() done\n");
484
485 return ERROR_SUCCESS;
486 }
487
488
489 static BOOL
490 ScServiceDispatcher(HANDLE hPipe,
491 PUCHAR lpBuffer,
492 DWORD dwBufferSize)
493 {
494 PSCM_CONTROL_PACKET ControlPacket;
495 DWORD Count;
496 BOOL bResult;
497 DWORD dwRunningServices = 0;
498 LPWSTR lpServiceName;
499 PACTIVE_SERVICE lpService;
500 SCM_REPLY_PACKET ReplyPacket;
501 DWORD dwError;
502
503 TRACE("ScDispatcherLoop() called\n");
504
505 ControlPacket = HeapAlloc(GetProcessHeap(),
506 HEAP_ZERO_MEMORY,
507 1024);
508 if (ControlPacket == NULL)
509 return FALSE;
510
511 while (TRUE)
512 {
513 /* Read command from the control pipe */
514 bResult = ReadFile(hPipe,
515 ControlPacket,
516 1024,
517 &Count,
518 NULL);
519 if (bResult == FALSE)
520 {
521 ERR("Pipe read failed (Error: %lu)\n", GetLastError());
522 return FALSE;
523 }
524
525 lpServiceName = (LPWSTR)((PBYTE)ControlPacket + ControlPacket->dwServiceNameOffset);
526 TRACE("Service: %S\n", lpServiceName);
527
528 lpService = ScLookupServiceByServiceName(lpServiceName);
529 if (lpService != NULL)
530 {
531 /* Execute command */
532 switch (ControlPacket->dwControl)
533 {
534 case SERVICE_CONTROL_START:
535 TRACE("Start command - recieved SERVICE_CONTROL_START\n");
536 dwError = ScStartService(lpService, ControlPacket);
537 if (dwError == ERROR_SUCCESS)
538 dwRunningServices++;
539 break;
540
541 case SERVICE_CONTROL_STOP:
542 TRACE("Stop command - recieved SERVICE_CONTROL_STOP\n");
543 dwError = ScControlService(lpService, ControlPacket);
544 if (dwError == ERROR_SUCCESS)
545 dwRunningServices--;
546 break;
547
548 default:
549 TRACE("Command %lu received", ControlPacket->dwControl);
550 dwError = ScControlService(lpService, ControlPacket);
551 break;
552 }
553 }
554 else
555 {
556 dwError = ERROR_SERVICE_DOES_NOT_EXIST;
557 }
558
559 ReplyPacket.dwError = dwError;
560
561 /* Send the reply packet */
562 bResult = WriteFile(hPipe,
563 &ReplyPacket,
564 sizeof(ReplyPacket),
565 &Count,
566 NULL);
567 if (bResult == FALSE)
568 {
569 ERR("Pipe write failed (Error: %lu)\n", GetLastError());
570 return FALSE;
571 }
572
573 if (dwRunningServices == 0)
574 break;
575 }
576
577 HeapFree(GetProcessHeap(),
578 0,
579 ControlPacket);
580
581 return TRUE;
582 }
583
584
585 /**********************************************************************
586 * RegisterServiceCtrlHandlerA
587 *
588 * @implemented
589 */
590 SERVICE_STATUS_HANDLE WINAPI
591 RegisterServiceCtrlHandlerA(LPCSTR lpServiceName,
592 LPHANDLER_FUNCTION lpHandlerProc)
593 {
594 ANSI_STRING ServiceNameA;
595 UNICODE_STRING ServiceNameU;
596 SERVICE_STATUS_HANDLE SHandle;
597
598 RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
599 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
600 {
601 SetLastError(ERROR_OUTOFMEMORY);
602 return (SERVICE_STATUS_HANDLE)0;
603 }
604
605 SHandle = RegisterServiceCtrlHandlerW(ServiceNameU.Buffer,
606 lpHandlerProc);
607
608 RtlFreeUnicodeString(&ServiceNameU);
609
610 return SHandle;
611 }
612
613
614 /**********************************************************************
615 * RegisterServiceCtrlHandlerW
616 *
617 * @implemented
618 */
619 SERVICE_STATUS_HANDLE WINAPI
620 RegisterServiceCtrlHandlerW(LPCWSTR lpServiceName,
621 LPHANDLER_FUNCTION lpHandlerProc)
622 {
623 PACTIVE_SERVICE Service;
624
625 Service = ScLookupServiceByServiceName((LPWSTR)lpServiceName);
626 if (Service == NULL)
627 {
628 return (SERVICE_STATUS_HANDLE)NULL;
629 }
630
631 Service->HandlerFunction = lpHandlerProc;
632 Service->HandlerFunctionEx = NULL;
633
634 TRACE("RegisterServiceCtrlHandler returning %lu\n", Service->hServiceStatus);
635
636 return Service->hServiceStatus;
637 }
638
639
640 /**********************************************************************
641 * RegisterServiceCtrlHandlerExA
642 *
643 * @implemented
644 */
645 SERVICE_STATUS_HANDLE WINAPI
646 RegisterServiceCtrlHandlerExA(LPCSTR lpServiceName,
647 LPHANDLER_FUNCTION_EX lpHandlerProc,
648 LPVOID lpContext)
649 {
650 ANSI_STRING ServiceNameA;
651 UNICODE_STRING ServiceNameU;
652 SERVICE_STATUS_HANDLE SHandle;
653
654 RtlInitAnsiString(&ServiceNameA, (LPSTR)lpServiceName);
655 if (!NT_SUCCESS(RtlAnsiStringToUnicodeString(&ServiceNameU, &ServiceNameA, TRUE)))
656 {
657 SetLastError(ERROR_OUTOFMEMORY);
658 return (SERVICE_STATUS_HANDLE)0;
659 }
660
661 SHandle = RegisterServiceCtrlHandlerExW(ServiceNameU.Buffer,
662 lpHandlerProc,
663 lpContext);
664
665 RtlFreeUnicodeString(&ServiceNameU);
666
667 return SHandle;
668 }
669
670
671 /**********************************************************************
672 * RegisterServiceCtrlHandlerExW
673 *
674 * @implemented
675 */
676 SERVICE_STATUS_HANDLE WINAPI
677 RegisterServiceCtrlHandlerExW(LPCWSTR lpServiceName,
678 LPHANDLER_FUNCTION_EX lpHandlerProc,
679 LPVOID lpContext)
680 {
681 PACTIVE_SERVICE Service;
682
683 Service = ScLookupServiceByServiceName(lpServiceName);
684 if (Service == NULL)
685 {
686 return (SERVICE_STATUS_HANDLE)NULL;
687 }
688
689 Service->HandlerFunction = NULL;
690 Service->HandlerFunctionEx = lpHandlerProc;
691 Service->HandlerContext = lpContext;
692
693 TRACE("RegisterServiceCtrlHandlerEx returning %lu\n", Service->hServiceStatus);
694
695 return Service->hServiceStatus;
696 }
697
698
699 /**********************************************************************
700 * I_ScSetServiceBitsA
701 *
702 * Undocumented
703 *
704 * @implemented
705 */
706 BOOL WINAPI
707 I_ScSetServiceBitsA(SERVICE_STATUS_HANDLE hServiceStatus,
708 DWORD dwServiceBits,
709 BOOL bSetBitsOn,
710 BOOL bUpdateImmediately,
711 LPSTR lpString)
712 {
713 BOOL bResult;
714
715 RpcTryExcept
716 {
717 /* Call to services.exe using RPC */
718 bResult = RI_ScSetServiceBitsA((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
719 dwServiceBits,
720 bSetBitsOn,
721 bUpdateImmediately,
722 lpString);
723 }
724 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
725 {
726 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
727 bResult = FALSE;
728 }
729 RpcEndExcept;
730
731 return bResult;
732 }
733
734
735 /**********************************************************************
736 * I_ScSetServiceBitsW
737 *
738 * Undocumented
739 *
740 * @implemented
741 */
742 BOOL WINAPI
743 I_ScSetServiceBitsW(SERVICE_STATUS_HANDLE hServiceStatus,
744 DWORD dwServiceBits,
745 BOOL bSetBitsOn,
746 BOOL bUpdateImmediately,
747 LPWSTR lpString)
748 {
749 BOOL bResult;
750
751 RpcTryExcept
752 {
753 /* Call to services.exe using RPC */
754 bResult = RI_ScSetServiceBitsW((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
755 dwServiceBits,
756 bSetBitsOn,
757 bUpdateImmediately,
758 lpString);
759 }
760 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
761 {
762 SetLastError(ScmRpcStatusToWinError(RpcExceptionCode()));
763 bResult = FALSE;
764 }
765 RpcEndExcept;
766
767 return bResult;
768 }
769
770
771 /**********************************************************************
772 * SetServiceBits
773 *
774 * @implemented
775 */
776 BOOL WINAPI
777 SetServiceBits(SERVICE_STATUS_HANDLE hServiceStatus,
778 DWORD dwServiceBits,
779 BOOL bSetBitsOn,
780 BOOL bUpdateImmediately)
781 {
782 return I_ScSetServiceBitsW(hServiceStatus,
783 dwServiceBits,
784 bSetBitsOn,
785 bUpdateImmediately,
786 NULL);
787 }
788
789
790 /**********************************************************************
791 * SetServiceStatus
792 *
793 * @implemented
794 */
795 BOOL WINAPI
796 SetServiceStatus(SERVICE_STATUS_HANDLE hServiceStatus,
797 LPSERVICE_STATUS lpServiceStatus)
798 {
799 DWORD dwError;
800
801 TRACE("SetServiceStatus() called\n");
802 TRACE("hServiceStatus %lu\n", hServiceStatus);
803
804 RpcTryExcept
805 {
806 /* Call to services.exe using RPC */
807 dwError = RSetServiceStatus((RPC_SERVICE_STATUS_HANDLE)hServiceStatus,
808 lpServiceStatus);
809 }
810 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
811 {
812 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
813 }
814 RpcEndExcept;
815
816 if (dwError != ERROR_SUCCESS)
817 {
818 ERR("ScmrSetServiceStatus() failed (Error %lu)\n", dwError);
819 SetLastError(dwError);
820 return FALSE;
821 }
822
823 TRACE("SetServiceStatus() done (ret %lu)\n", dwError);
824
825 return TRUE;
826 }
827
828
829 /**********************************************************************
830 * StartServiceCtrlDispatcherA
831 *
832 * @implemented
833 */
834 BOOL WINAPI
835 StartServiceCtrlDispatcherA(const SERVICE_TABLE_ENTRYA * lpServiceStartTable)
836 {
837 ULONG i;
838 HANDLE hPipe;
839 DWORD dwError;
840 PUCHAR lpMessageBuffer;
841
842 TRACE("StartServiceCtrlDispatcherA() called\n");
843
844 i = 0;
845 while (lpServiceStartTable[i].lpServiceProc != NULL)
846 {
847 i++;
848 }
849
850 dwActiveServiceCount = i;
851 lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
852 HEAP_ZERO_MEMORY,
853 dwActiveServiceCount * sizeof(ACTIVE_SERVICE));
854 if (lpActiveServices == NULL)
855 {
856 return FALSE;
857 }
858
859 /* Copy service names and start procedure */
860 for (i = 0; i < dwActiveServiceCount; i++)
861 {
862 RtlCreateUnicodeStringFromAsciiz(&lpActiveServices[i].ServiceName,
863 lpServiceStartTable[i].lpServiceName);
864 lpActiveServices[i].ThreadParams.A.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
865 lpActiveServices[i].hServiceStatus = 0;
866 lpActiveServices[i].bUnicode = FALSE;
867 }
868
869 dwError = ScConnectControlPipe(&hPipe);
870 if (dwError != ERROR_SUCCESS)
871 {
872 /* Free the service table */
873 for (i = 0; i < dwActiveServiceCount; i++)
874 {
875 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
876 }
877 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
878 lpActiveServices = NULL;
879 dwActiveServiceCount = 0;
880 return FALSE;
881 }
882
883 lpMessageBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
884 HEAP_ZERO_MEMORY,
885 256);
886 if (lpMessageBuffer == NULL)
887 {
888 /* Free the service table */
889 for (i = 0; i < dwActiveServiceCount; i++)
890 {
891 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
892 }
893 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
894 lpActiveServices = NULL;
895 dwActiveServiceCount = 0;
896 CloseHandle(hPipe);
897 return FALSE;
898 }
899
900 ScCreateStatusBinding();
901
902 ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
903
904 ScDestroyStatusBinding();
905
906 CloseHandle(hPipe);
907
908 /* Free the message buffer */
909 RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer);
910
911 /* Free the service table */
912 for (i = 0; i < dwActiveServiceCount; i++)
913 {
914 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
915 }
916 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
917 lpActiveServices = NULL;
918 dwActiveServiceCount = 0;
919
920 return TRUE;
921 }
922
923
924 /**********************************************************************
925 * StartServiceCtrlDispatcherW
926 *
927 * @implemented
928 */
929 BOOL WINAPI
930 StartServiceCtrlDispatcherW(const SERVICE_TABLE_ENTRYW * lpServiceStartTable)
931 {
932 ULONG i;
933 HANDLE hPipe;
934 DWORD dwError;
935 PUCHAR lpMessageBuffer;
936
937 TRACE("StartServiceCtrlDispatcherW() called\n");
938
939 i = 0;
940 while (lpServiceStartTable[i].lpServiceProc != NULL)
941 {
942 i++;
943 }
944
945 dwActiveServiceCount = i;
946 lpActiveServices = RtlAllocateHeap(RtlGetProcessHeap(),
947 HEAP_ZERO_MEMORY,
948 dwActiveServiceCount * sizeof(ACTIVE_SERVICE));
949 if (lpActiveServices == NULL)
950 {
951 return FALSE;
952 }
953
954 /* Copy service names and start procedure */
955 for (i = 0; i < dwActiveServiceCount; i++)
956 {
957 RtlCreateUnicodeString(&lpActiveServices[i].ServiceName,
958 lpServiceStartTable[i].lpServiceName);
959 lpActiveServices[i].ThreadParams.W.lpServiceMain = lpServiceStartTable[i].lpServiceProc;
960 lpActiveServices[i].hServiceStatus = 0;
961 lpActiveServices[i].bUnicode = TRUE;
962 }
963
964 dwError = ScConnectControlPipe(&hPipe);
965 if (dwError != ERROR_SUCCESS)
966 {
967 /* Free the service table */
968 for (i = 0; i < dwActiveServiceCount; i++)
969 {
970 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
971 }
972 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
973 lpActiveServices = NULL;
974 dwActiveServiceCount = 0;
975 return FALSE;
976 }
977
978 lpMessageBuffer = RtlAllocateHeap(RtlGetProcessHeap(),
979 HEAP_ZERO_MEMORY,
980 256);
981 if (lpMessageBuffer == NULL)
982 {
983 /* Free the service table */
984 for (i = 0; i < dwActiveServiceCount; i++)
985 {
986 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
987 }
988 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
989 lpActiveServices = NULL;
990 dwActiveServiceCount = 0;
991 CloseHandle(hPipe);
992 return FALSE;
993 }
994
995 ScCreateStatusBinding();
996
997 ScServiceDispatcher(hPipe, lpMessageBuffer, 256);
998
999 ScDestroyStatusBinding();
1000
1001 CloseHandle(hPipe);
1002
1003 /* Free the message buffer */
1004 RtlFreeHeap(RtlGetProcessHeap(), 0, lpMessageBuffer);
1005
1006 /* Free the service table */
1007 for (i = 0; i < dwActiveServiceCount; i++)
1008 {
1009 RtlFreeUnicodeString(&lpActiveServices[i].ServiceName);
1010 }
1011 RtlFreeHeap(RtlGetProcessHeap(), 0, lpActiveServices);
1012 lpActiveServices = NULL;
1013 dwActiveServiceCount = 0;
1014
1015 return TRUE;
1016 }
1017
1018 /* EOF */