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