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