26c9ce9efca6517cbf1bed789a07f33028f92b7d
[reactos.git] / reactos / dll / win32 / advapi32 / service / scm.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/advapi32/service/scm.c
5 * PURPOSE: Service control manager functions
6 * PROGRAMMER: Emanuele Aliberti
7 * Eric Kohl
8 * UPDATE HISTORY:
9 * 19990413 EA created
10 * 19990515 EA
11 */
12
13 /* INCLUDES ******************************************************************/
14
15 #include <advapi32.h>
16
17 #include "wine/debug.h"
18
19 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
20
21
22 /* FUNCTIONS *****************************************************************/
23
24 handle_t __RPC_USER
25 SVCCTL_HANDLEA_bind(SVCCTL_HANDLEA szMachineName)
26 {
27 handle_t hBinding = NULL;
28 UCHAR *pszStringBinding;
29 RPC_STATUS status;
30
31 ERR("SVCCTL_HANDLEA_bind() called\n");
32
33 status = RpcStringBindingComposeA((UCHAR *)szMachineName,
34 (UCHAR *)"ncacn_np",
35 NULL,
36 (UCHAR *)"\\pipe\\ntsvcs",
37 NULL,
38 (UCHAR **)&pszStringBinding);
39 if (status)
40 {
41 ERR("RpcStringBindingCompose returned 0x%x\n", status);
42 return NULL;
43 }
44
45 /* Set the binding handle that will be used to bind to the server. */
46 status = RpcBindingFromStringBindingA(pszStringBinding,
47 &hBinding);
48 if (status)
49 {
50 ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
51 }
52
53 status = RpcStringFreeA(&pszStringBinding);
54 if (status)
55 {
56 ERR("RpcStringFree returned 0x%x\n", status);
57 }
58
59 return hBinding;
60 }
61
62
63 void __RPC_USER
64 SVCCTL_HANDLEA_unbind(SVCCTL_HANDLEA szMachineName,
65 handle_t hBinding)
66 {
67 RPC_STATUS status;
68
69 ERR("SVCCTL_HANDLEA_unbind() called\n");
70
71 status = RpcBindingFree(&hBinding);
72 if (status)
73 {
74 ERR("RpcBindingFree returned 0x%x\n", status);
75 }
76 }
77
78
79 handle_t __RPC_USER
80 SVCCTL_HANDLEW_bind(SVCCTL_HANDLEW szMachineName)
81 {
82 handle_t hBinding = NULL;
83 LPWSTR pszStringBinding;
84 RPC_STATUS status;
85
86 ERR("SVCCTL_HANDLEW_bind() called\n");
87
88
89 status = RpcStringBindingComposeW(szMachineName,
90 L"ncacn_np",
91 NULL,
92 L"\\pipe\\ntsvcs",
93 NULL,
94 &pszStringBinding);
95 if (status)
96 {
97 ERR("RpcStringBindingCompose returned 0x%x\n", status);
98 return NULL;
99 }
100
101 /* Set the binding handle that will be used to bind to the server. */
102 status = RpcBindingFromStringBindingW(pszStringBinding,
103 &hBinding);
104 if (status)
105 {
106 ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
107 }
108
109 status = RpcStringFreeW(&pszStringBinding);
110 if (status)
111 {
112 ERR("RpcStringFree returned 0x%x\n", status);
113 }
114
115 return hBinding;
116 }
117
118
119 void __RPC_USER
120 SVCCTL_HANDLEW_unbind(SVCCTL_HANDLEW szMachineName,
121 handle_t hBinding)
122 {
123 RPC_STATUS status;
124
125 ERR("SVCCTL_HANDLEW_unbind() called\n");
126
127 status = RpcBindingFree(&hBinding);
128 if (status)
129 {
130 ERR("RpcBindingFree returned 0x%x\n", status);
131 }
132 }
133
134
135 handle_t __RPC_USER
136 RPC_SERVICE_STATUS_HANDLE_bind(RPC_SERVICE_STATUS_HANDLE hServiceStatus)
137 {
138 handle_t hBinding = NULL;
139 LPWSTR pszStringBinding;
140 RPC_STATUS status;
141
142 ERR("RPC_SERVICE_STATUS_HANDLE_bind() called\n");
143
144
145 status = RpcStringBindingComposeW(NULL,
146 L"ncacn_np",
147 NULL,
148 L"\\pipe\\ntsvcs",
149 NULL,
150 &pszStringBinding);
151 if (status)
152 {
153 ERR("RpcStringBindingCompose returned 0x%x\n", status);
154 return NULL;
155 }
156
157 /* Set the binding handle that will be used to bind to the server. */
158 status = RpcBindingFromStringBindingW(pszStringBinding,
159 &hBinding);
160 if (status)
161 {
162 ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
163 }
164
165 status = RpcStringFreeW(&pszStringBinding);
166 if (status)
167 {
168 ERR("RpcStringFree returned 0x%x\n", status);
169 }
170
171 return hBinding;
172 }
173
174
175 void __RPC_USER
176 RPC_SERVICE_STATUS_HANDLE_unbind(RPC_SERVICE_STATUS_HANDLE hServiceStatus,
177 handle_t hBinding)
178 {
179 RPC_STATUS status;
180
181 ERR("RPC_SERVICE_STATUS_HANDLE_unbind() called\n");
182
183 status = RpcBindingFree(&hBinding);
184 if (status)
185 {
186 ERR("RpcBindingFree returned 0x%x\n", status);
187 }
188 }
189
190
191 DWORD
192 ScmRpcStatusToWinError(RPC_STATUS Status)
193 {
194 switch (Status)
195 {
196 case RPC_X_SS_IN_NULL_CONTEXT:
197 return ERROR_INVALID_HANDLE;
198
199 case RPC_X_NULL_REF_POINTER:
200 return ERROR_INVALID_PARAMETER;
201
202 case STATUS_ACCESS_VIOLATION:
203 return ERROR_INVALID_ADDRESS;
204
205 default:
206 return (DWORD)Status;
207 }
208 }
209
210
211 /**********************************************************************
212 * ChangeServiceConfig2A
213 *
214 * @implemented
215 */
216 BOOL WINAPI
217 ChangeServiceConfig2A(SC_HANDLE hService,
218 DWORD dwInfoLevel,
219 LPVOID lpInfo)
220 {
221 SC_RPC_CONFIG_INFOA Info;
222 DWORD dwError;
223
224 TRACE("ChangeServiceConfig2A() called\n");
225
226 /* Fill relevent field of the Info structure */
227 Info.dwInfoLevel = dwInfoLevel;
228 switch (dwInfoLevel)
229 {
230 case SERVICE_CONFIG_DESCRIPTION:
231 Info.psd = (LPSERVICE_DESCRIPTIONA)&lpInfo;
232 break;
233
234 case SERVICE_CONFIG_FAILURE_ACTIONS:
235 Info.psfa = (LPSERVICE_FAILURE_ACTIONSA)&lpInfo;
236 break;
237
238 default:
239 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
240 SetLastError(ERROR_INVALID_PARAMETER);
241 return FALSE;
242 }
243
244 if (lpInfo == NULL)
245 return TRUE;
246
247 _SEH_TRY
248 {
249 dwError = RChangeServiceConfig2A((SC_RPC_HANDLE)hService,
250 Info);
251 }
252 _SEH_HANDLE
253 {
254 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
255 }
256 _SEH_END;
257
258 if (dwError != ERROR_SUCCESS)
259 {
260 ERR("RChangeServiceConfig2A() failed (Error %lu)\n", dwError);
261 SetLastError(dwError);
262 return FALSE;
263 }
264
265 return TRUE;
266 }
267
268
269 /**********************************************************************
270 * ChangeServiceConfig2W
271 *
272 * @implemented
273 */
274 BOOL WINAPI
275 ChangeServiceConfig2W(SC_HANDLE hService,
276 DWORD dwInfoLevel,
277 LPVOID lpInfo)
278 {
279 SC_RPC_CONFIG_INFOW Info;
280 DWORD dwError;
281
282 TRACE("ChangeServiceConfig2W() called\n");
283
284 /* Fill relevent field of the Info structure */
285 Info.dwInfoLevel = dwInfoLevel;
286 switch (dwInfoLevel)
287 {
288 case SERVICE_CONFIG_DESCRIPTION:
289 {
290 Info.psd = (LPSERVICE_DESCRIPTIONW)&lpInfo;
291 break;
292 }
293
294 case SERVICE_CONFIG_FAILURE_ACTIONS:
295 Info.psfa = (LPSERVICE_FAILURE_ACTIONSW)&lpInfo;
296 break;
297
298 default:
299 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
300 SetLastError(ERROR_INVALID_PARAMETER);
301 return FALSE;
302 }
303
304 if (lpInfo == NULL)
305 return TRUE;
306
307 _SEH_TRY
308 {
309 dwError = RChangeServiceConfig2W((SC_RPC_HANDLE)hService,
310 Info);
311 }
312 _SEH_HANDLE
313 {
314 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
315 }
316 _SEH_END;
317
318 if (dwError != ERROR_SUCCESS)
319 {
320 ERR("RChangeServiceConfig2W() failed (Error %lu)\n", dwError);
321 SetLastError(dwError);
322 return FALSE;
323 }
324
325 return TRUE;
326 }
327
328
329 /**********************************************************************
330 * ChangeServiceConfigA
331 *
332 * @implemented
333 */
334 BOOL STDCALL
335 ChangeServiceConfigA(SC_HANDLE hService,
336 DWORD dwServiceType,
337 DWORD dwStartType,
338 DWORD dwErrorControl,
339 LPCSTR lpBinaryPathName,
340 LPCSTR lpLoadOrderGroup,
341 LPDWORD lpdwTagId,
342 LPCSTR lpDependencies,
343 LPCSTR lpServiceStartName,
344 LPCSTR lpPassword,
345 LPCSTR lpDisplayName)
346 {
347 DWORD dwError;
348 DWORD dwDependenciesLength = 0;
349 DWORD dwLength;
350 LPSTR lpStr;
351
352 TRACE("ChangeServiceConfigA() called\n");
353
354 /* Calculate the Dependencies length*/
355 if (lpDependencies != NULL)
356 {
357 lpStr = (LPSTR)lpDependencies;
358 while (*lpStr)
359 {
360 dwLength = strlen(lpStr) + 1;
361 dwDependenciesLength += dwLength;
362 lpStr = lpStr + dwLength;
363 }
364 dwDependenciesLength++;
365 }
366
367 /* FIXME: Encrypt the password */
368
369 _SEH_TRY
370 {
371 /* Call to services.exe using RPC */
372 dwError = RChangeServiceConfigA((SC_RPC_HANDLE)hService,
373 dwServiceType,
374 dwStartType,
375 dwErrorControl,
376 (LPSTR)lpBinaryPathName,
377 (LPSTR)lpLoadOrderGroup,
378 lpdwTagId,
379 (LPSTR)lpDependencies,
380 dwDependenciesLength,
381 (LPSTR)lpServiceStartName,
382 NULL, /* FIXME: lpPassword */
383 0, /* FIXME: dwPasswordLength */
384 (LPSTR)lpDisplayName);
385 }
386 _SEH_HANDLE
387 {
388 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
389 }
390 _SEH_END;
391
392 if (dwError != ERROR_SUCCESS)
393 {
394 ERR("RChangeServiceConfigA() failed (Error %lu)\n", dwError);
395 SetLastError(dwError);
396 return FALSE;
397 }
398
399 return TRUE;
400 }
401
402
403 /**********************************************************************
404 * ChangeServiceConfigW
405 *
406 * @implemented
407 */
408 BOOL STDCALL
409 ChangeServiceConfigW(SC_HANDLE hService,
410 DWORD dwServiceType,
411 DWORD dwStartType,
412 DWORD dwErrorControl,
413 LPCWSTR lpBinaryPathName,
414 LPCWSTR lpLoadOrderGroup,
415 LPDWORD lpdwTagId,
416 LPCWSTR lpDependencies,
417 LPCWSTR lpServiceStartName,
418 LPCWSTR lpPassword,
419 LPCWSTR lpDisplayName)
420 {
421 DWORD dwError;
422 DWORD dwDependenciesLength = 0;
423 DWORD dwLength;
424 LPWSTR lpStr;
425
426 TRACE("ChangeServiceConfigW() called\n");
427
428 /* Calculate the Dependencies length*/
429 if (lpDependencies != NULL)
430 {
431 lpStr = (LPWSTR)lpDependencies;
432 while (*lpStr)
433 {
434 dwLength = wcslen(lpStr) + 1;
435 dwDependenciesLength += dwLength;
436 lpStr = lpStr + dwLength;
437 }
438 dwDependenciesLength++;
439 }
440
441 /* FIXME: Encrypt the password */
442
443 _SEH_TRY
444 {
445 /* Call to services.exe using RPC */
446 dwError = RChangeServiceConfigW((SC_RPC_HANDLE)hService,
447 dwServiceType,
448 dwStartType,
449 dwErrorControl,
450 (LPWSTR)lpBinaryPathName,
451 (LPWSTR)lpLoadOrderGroup,
452 lpdwTagId,
453 (LPBYTE)lpDependencies,
454 dwDependenciesLength,
455 (LPWSTR)lpServiceStartName,
456 NULL, /* FIXME: lpPassword */
457 0, /* FIXME: dwPasswordLength */
458 (LPWSTR)lpDisplayName);
459 }
460 _SEH_HANDLE
461 {
462 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
463 }
464 _SEH_END;
465
466 if (dwError != ERROR_SUCCESS)
467 {
468 ERR("RChangeServiceConfigW() failed (Error %lu)\n", dwError);
469 SetLastError(dwError);
470 return FALSE;
471 }
472
473 return TRUE;
474 }
475
476
477 /**********************************************************************
478 * CloseServiceHandle
479 *
480 * @implemented
481 */
482 BOOL STDCALL
483 CloseServiceHandle(SC_HANDLE hSCObject)
484 {
485 DWORD dwError;
486
487 TRACE("CloseServiceHandle() called\n");
488
489 _SEH_TRY
490 {
491 /* Call to services.exe using RPC */
492 dwError = RCloseServiceHandle((LPSC_RPC_HANDLE)&hSCObject);
493 }
494 _SEH_HANDLE
495 {
496 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
497 }
498 _SEH_END;
499
500 if (dwError)
501 {
502 ERR("RCloseServiceHandle() failed (Error %lu)\n", dwError);
503 SetLastError(dwError);
504 return FALSE;
505 }
506
507 TRACE("CloseServiceHandle() done\n");
508
509 return TRUE;
510 }
511
512
513 /**********************************************************************
514 * ControlService
515 *
516 * @implemented
517 */
518 BOOL STDCALL
519 ControlService(SC_HANDLE hService,
520 DWORD dwControl,
521 LPSERVICE_STATUS lpServiceStatus)
522 {
523 DWORD dwError;
524
525 TRACE("ControlService(%x, %x, %p)\n",
526 hService, dwControl, lpServiceStatus);
527
528 _SEH_TRY
529 {
530 /* Call to services.exe using RPC */
531 dwError = RControlService((SC_RPC_HANDLE)hService,
532 dwControl,
533 lpServiceStatus);
534 }
535 _SEH_HANDLE
536 {
537 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
538 }
539 _SEH_END;
540
541 if (dwError != ERROR_SUCCESS)
542 {
543 ERR("RControlService() failed (Error %lu)\n", dwError);
544 SetLastError(dwError);
545 return FALSE;
546 }
547
548 TRACE("ControlService() done\n");
549
550 return TRUE;
551 }
552
553
554 /**********************************************************************
555 * ControlServiceEx
556 *
557 * @unimplemented
558 */
559 BOOL STDCALL
560 ControlServiceEx(IN SC_HANDLE hService,
561 IN DWORD dwControl,
562 IN DWORD dwInfoLevel,
563 IN OUT PVOID pControlParams)
564 {
565 FIXME("ControlServiceEx(0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n",
566 hService, dwControl, dwInfoLevel, pControlParams);
567 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
568 return FALSE;
569 }
570
571
572 /**********************************************************************
573 * CreateServiceA
574 *
575 * @implemented
576 */
577 SC_HANDLE STDCALL
578 CreateServiceA(SC_HANDLE hSCManager,
579 LPCSTR lpServiceName,
580 LPCSTR lpDisplayName,
581 DWORD dwDesiredAccess,
582 DWORD dwServiceType,
583 DWORD dwStartType,
584 DWORD dwErrorControl,
585 LPCSTR lpBinaryPathName,
586 LPCSTR lpLoadOrderGroup,
587 LPDWORD lpdwTagId,
588 LPCSTR lpDependencies,
589 LPCSTR lpServiceStartName,
590 LPCSTR lpPassword)
591 {
592 SC_HANDLE RetVal = NULL;
593 LPWSTR lpServiceNameW = NULL;
594 LPWSTR lpDisplayNameW = NULL;
595 LPWSTR lpBinaryPathNameW = NULL;
596 LPWSTR lpLoadOrderGroupW = NULL;
597 LPWSTR lpDependenciesW = NULL;
598 LPWSTR lpServiceStartNameW = NULL;
599 LPWSTR lpPasswordW = NULL;
600 DWORD dwDependenciesLength = 0;
601 DWORD dwLength;
602 int len;
603 LPSTR lpStr;
604
605 if (lpServiceName)
606 {
607 len = MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, NULL, 0);
608 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
609 if (!lpServiceNameW)
610 {
611 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
612 goto cleanup;
613 }
614 MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, lpServiceNameW, len);
615 }
616
617 if (lpDisplayName)
618 {
619 len = MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, NULL, 0);
620 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
621 if (!lpDisplayNameW)
622 {
623 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
624 goto cleanup;
625 }
626 MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len);
627 }
628
629 if (lpBinaryPathName)
630 {
631 len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0);
632 lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
633 if (!lpBinaryPathNameW)
634 {
635 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
636 goto cleanup;
637 }
638 MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, len);
639 }
640
641 if (lpLoadOrderGroup)
642 {
643 len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0);
644 lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
645 if (!lpLoadOrderGroupW)
646 {
647 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
648 goto cleanup;
649 }
650 MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len);
651 }
652
653 if (lpDependencies)
654 {
655 lpStr = (LPSTR)lpDependencies;
656 while (*lpStr)
657 {
658 dwLength = strlen(lpStr) + 1;
659 dwDependenciesLength += dwLength;
660 lpStr = lpStr + dwLength;
661 }
662 dwDependenciesLength++;
663
664 lpDependenciesW = HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength * sizeof(WCHAR));
665 if (!lpDependenciesW)
666 {
667 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
668 goto cleanup;
669 }
670 MultiByteToWideChar(CP_ACP, 0, lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength);
671 }
672
673 if (lpServiceStartName)
674 {
675 len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0);
676 lpServiceStartNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
677 if (!lpServiceStartNameW)
678 {
679 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
680 goto cleanup;
681 }
682 MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len);
683 }
684
685 if (lpPassword)
686 {
687 len = MultiByteToWideChar(CP_ACP, 0, lpPassword, -1, NULL, 0);
688 lpPasswordW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
689 if (!lpPasswordW)
690 {
691 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
692 goto cleanup;
693 }
694 MultiByteToWideChar(CP_ACP, 0, lpPassword, -1, lpPasswordW, len);
695 }
696
697 RetVal = CreateServiceW(hSCManager,
698 lpServiceNameW,
699 lpDisplayNameW,
700 dwDesiredAccess,
701 dwServiceType,
702 dwStartType,
703 dwErrorControl,
704 lpBinaryPathNameW,
705 lpLoadOrderGroupW,
706 lpdwTagId,
707 lpDependenciesW,
708 lpServiceStartNameW,
709 lpPasswordW);
710
711 cleanup:
712 if (lpServiceNameW !=NULL)
713 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
714
715 if (lpDisplayNameW != NULL)
716 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
717
718 if (lpBinaryPathNameW != NULL)
719 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW);
720
721 if (lpLoadOrderGroupW != NULL)
722 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
723
724 if (lpDependenciesW != NULL)
725 HeapFree(GetProcessHeap(), 0, lpDependenciesW);
726
727 if (lpServiceStartNameW != NULL)
728 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW);
729
730 if (lpPasswordW != NULL)
731 HeapFree(GetProcessHeap(), 0, lpPasswordW);
732
733 return RetVal;
734 }
735
736
737 /**********************************************************************
738 * CreateServiceW
739 *
740 * @implemented
741 */
742 SC_HANDLE STDCALL
743 CreateServiceW(SC_HANDLE hSCManager,
744 LPCWSTR lpServiceName,
745 LPCWSTR lpDisplayName,
746 DWORD dwDesiredAccess,
747 DWORD dwServiceType,
748 DWORD dwStartType,
749 DWORD dwErrorControl,
750 LPCWSTR lpBinaryPathName,
751 LPCWSTR lpLoadOrderGroup,
752 LPDWORD lpdwTagId,
753 LPCWSTR lpDependencies,
754 LPCWSTR lpServiceStartName,
755 LPCWSTR lpPassword)
756 {
757 SC_HANDLE hService = NULL;
758 DWORD dwDependenciesLength = 0;
759 DWORD dwError;
760 DWORD dwLength;
761 LPWSTR lpStr;
762
763 TRACE("CreateServiceW() called\n");
764
765 /* Calculate the Dependencies length*/
766 if (lpDependencies != NULL)
767 {
768 lpStr = (LPWSTR)lpDependencies;
769 while (*lpStr)
770 {
771 dwLength = wcslen(lpStr) + 1;
772 dwDependenciesLength += dwLength;
773 lpStr = lpStr + dwLength;
774 }
775 dwDependenciesLength++;
776
777 dwDependenciesLength *= sizeof(WCHAR);
778 }
779
780 /* FIXME: Encrypt the password */
781
782 _SEH_TRY
783 {
784 /* Call to services.exe using RPC */
785 dwError = RCreateServiceW((SC_RPC_HANDLE)hSCManager,
786 (LPWSTR)lpServiceName,
787 (LPWSTR)lpDisplayName,
788 dwDesiredAccess,
789 dwServiceType,
790 dwStartType,
791 dwErrorControl,
792 (LPWSTR)lpBinaryPathName,
793 (LPWSTR)lpLoadOrderGroup,
794 lpdwTagId,
795 (LPBYTE)lpDependencies,
796 dwDependenciesLength,
797 (LPWSTR)lpServiceStartName,
798 NULL, /* FIXME: lpPassword */
799 0, /* FIXME: dwPasswordLength */
800 (SC_RPC_HANDLE *)&hService);
801 }
802 _SEH_HANDLE
803 {
804 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
805 }
806 _SEH_END;
807
808 if (dwError != ERROR_SUCCESS)
809 {
810 ERR("RCreateServiceW() failed (Error %lu)\n", dwError);
811 SetLastError(dwError);
812 return NULL;
813 }
814
815 return hService;
816 }
817
818
819 /**********************************************************************
820 * DeleteService
821 *
822 * @implemented
823 */
824 BOOL STDCALL
825 DeleteService(SC_HANDLE hService)
826 {
827 DWORD dwError;
828
829 TRACE("DeleteService(%x)\n", hService);
830
831 _SEH_TRY
832 {
833 /* Call to services.exe using RPC */
834 dwError = RDeleteService((SC_RPC_HANDLE)hService);
835 }
836 _SEH_HANDLE
837 {
838 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
839 }
840 _SEH_END;
841
842 if (dwError != ERROR_SUCCESS)
843 {
844 ERR("RDeleteService() failed (Error %lu)\n", dwError);
845 SetLastError(dwError);
846 return FALSE;
847 }
848
849 return TRUE;
850 }
851
852
853 /**********************************************************************
854 * EnumDependentServicesA
855 *
856 * @implemented
857 */
858 BOOL STDCALL
859 EnumDependentServicesA(SC_HANDLE hService,
860 DWORD dwServiceState,
861 LPENUM_SERVICE_STATUSA lpServices,
862 DWORD cbBufSize,
863 LPDWORD pcbBytesNeeded,
864 LPDWORD lpServicesReturned)
865 {
866 LPENUM_SERVICE_STATUSA lpStatusPtr;
867 DWORD dwError;
868 DWORD dwCount;
869
870 TRACE("EnumServicesStatusA() called\n");
871
872 _SEH_TRY
873 {
874 dwError = REnumDependentServicesA((SC_RPC_HANDLE)hService,
875 dwServiceState,
876 (LPBYTE)lpServices,
877 cbBufSize,
878 pcbBytesNeeded,
879 lpServicesReturned);
880 }
881 _SEH_HANDLE
882 {
883 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
884 }
885 _SEH_END;
886
887 if (dwError != ERROR_SUCCESS)
888 {
889 ERR("REnumDependentServicesA() failed (Error %lu)\n", dwError);
890 SetLastError(dwError);
891 return FALSE;
892 }
893
894 lpStatusPtr = (LPENUM_SERVICE_STATUSA)lpServices;
895 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
896 {
897 if (lpStatusPtr->lpServiceName)
898 lpStatusPtr->lpServiceName =
899 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
900
901 if (lpStatusPtr->lpDisplayName)
902 lpStatusPtr->lpDisplayName =
903 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
904
905 lpStatusPtr++;
906 }
907
908 TRACE("EnumDependentServicesA() done\n");
909
910 return TRUE;
911 }
912
913
914 /**********************************************************************
915 * EnumDependentServicesW
916 *
917 * @implemented
918 */
919 BOOL STDCALL
920 EnumDependentServicesW(SC_HANDLE hService,
921 DWORD dwServiceState,
922 LPENUM_SERVICE_STATUSW lpServices,
923 DWORD cbBufSize,
924 LPDWORD pcbBytesNeeded,
925 LPDWORD lpServicesReturned)
926 {
927 LPENUM_SERVICE_STATUSW lpStatusPtr;
928 DWORD dwError;
929 DWORD dwCount;
930
931 TRACE("EnumServicesStatusW() called\n");
932
933 _SEH_TRY
934 {
935 dwError = REnumDependentServicesW((SC_RPC_HANDLE)hService,
936 dwServiceState,
937 (LPBYTE)lpServices,
938 cbBufSize,
939 pcbBytesNeeded,
940 lpServicesReturned);
941 }
942 _SEH_HANDLE
943 {
944 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
945 }
946 _SEH_END;
947
948 if (dwError != ERROR_SUCCESS)
949 {
950 ERR("REnumDependentServicesW() failed (Error %lu)\n", dwError);
951 SetLastError(dwError);
952 return FALSE;
953 }
954
955 lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpServices;
956 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
957 {
958 if (lpStatusPtr->lpServiceName)
959 lpStatusPtr->lpServiceName =
960 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
961
962 if (lpStatusPtr->lpDisplayName)
963 lpStatusPtr->lpDisplayName =
964 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
965
966 lpStatusPtr++;
967 }
968
969 TRACE("EnumDependentServicesW() done\n");
970
971 return TRUE;
972 }
973
974
975 /**********************************************************************
976 * EnumServiceGroupW
977 *
978 * @unimplemented
979 */
980 BOOL
981 STDCALL
982 EnumServiceGroupW(
983 SC_HANDLE hSCManager,
984 DWORD dwServiceType,
985 DWORD dwServiceState,
986 LPENUM_SERVICE_STATUSW lpServices,
987 DWORD cbBufSize,
988 LPDWORD pcbBytesNeeded,
989 LPDWORD lpServicesReturned,
990 LPDWORD lpResumeHandle,
991 LPCWSTR lpGroup)
992 {
993 FIXME("EnumServiceGroupW is unimplemented\n");
994 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
995 return FALSE;
996 }
997
998
999 /**********************************************************************
1000 * EnumServicesStatusA
1001 *
1002 * @implemented
1003 */
1004 BOOL STDCALL
1005 EnumServicesStatusA(SC_HANDLE hSCManager,
1006 DWORD dwServiceType,
1007 DWORD dwServiceState,
1008 LPENUM_SERVICE_STATUSA lpServices,
1009 DWORD cbBufSize,
1010 LPDWORD pcbBytesNeeded,
1011 LPDWORD lpServicesReturned,
1012 LPDWORD lpResumeHandle)
1013 {
1014 LPENUM_SERVICE_STATUSA lpStatusPtr;
1015 DWORD dwError;
1016 DWORD dwCount;
1017
1018 TRACE("EnumServicesStatusA() called\n");
1019
1020 _SEH_TRY
1021 {
1022 dwError = REnumServicesStatusA((SC_RPC_HANDLE)hSCManager,
1023 dwServiceType,
1024 dwServiceState,
1025 (LPBYTE)lpServices,
1026 cbBufSize,
1027 pcbBytesNeeded,
1028 lpServicesReturned,
1029 lpResumeHandle);
1030 }
1031 _SEH_HANDLE
1032 {
1033 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1034 }
1035 _SEH_END;
1036
1037 if (dwError != ERROR_SUCCESS)
1038 {
1039 ERR("REnumServicesStatusA() failed (Error %lu)\n", dwError);
1040 SetLastError(dwError);
1041 return FALSE;
1042 }
1043
1044 lpStatusPtr = (LPENUM_SERVICE_STATUSA)lpServices;
1045 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
1046 {
1047 if (lpStatusPtr->lpServiceName)
1048 lpStatusPtr->lpServiceName =
1049 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
1050
1051 if (lpStatusPtr->lpDisplayName)
1052 lpStatusPtr->lpDisplayName =
1053 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
1054
1055 lpStatusPtr++;
1056 }
1057
1058 TRACE("EnumServicesStatusA() done\n");
1059
1060 return TRUE;
1061 }
1062
1063
1064 /**********************************************************************
1065 * EnumServicesStatusW
1066 *
1067 * @implemented
1068 */
1069 BOOL STDCALL
1070 EnumServicesStatusW(SC_HANDLE hSCManager,
1071 DWORD dwServiceType,
1072 DWORD dwServiceState,
1073 LPENUM_SERVICE_STATUSW lpServices,
1074 DWORD cbBufSize,
1075 LPDWORD pcbBytesNeeded,
1076 LPDWORD lpServicesReturned,
1077 LPDWORD lpResumeHandle)
1078 {
1079 LPENUM_SERVICE_STATUSW lpStatusPtr;
1080 DWORD dwError;
1081 DWORD dwCount;
1082
1083 TRACE("EnumServicesStatusW() called\n");
1084
1085 _SEH_TRY
1086 {
1087 dwError = REnumServicesStatusW((SC_RPC_HANDLE)hSCManager,
1088 dwServiceType,
1089 dwServiceState,
1090 (LPBYTE)lpServices,
1091 cbBufSize,
1092 pcbBytesNeeded,
1093 lpServicesReturned,
1094 lpResumeHandle);
1095 }
1096 _SEH_HANDLE
1097 {
1098 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1099 }
1100 _SEH_END;
1101
1102 if (dwError != ERROR_SUCCESS)
1103 {
1104 ERR("REnumServicesStatusW() failed (Error %lu)\n", dwError);
1105 SetLastError(dwError);
1106 return FALSE;
1107 }
1108
1109 lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpServices;
1110 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
1111 {
1112 if (lpStatusPtr->lpServiceName)
1113 lpStatusPtr->lpServiceName =
1114 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
1115
1116 if (lpStatusPtr->lpDisplayName)
1117 lpStatusPtr->lpDisplayName =
1118 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
1119
1120 lpStatusPtr++;
1121 }
1122
1123 TRACE("EnumServicesStatusW() done\n");
1124
1125 return TRUE;
1126 }
1127
1128
1129 /**********************************************************************
1130 * EnumServicesStatusExA
1131 *
1132 * @implemented
1133 */
1134 BOOL STDCALL
1135 EnumServicesStatusExA(SC_HANDLE hSCManager,
1136 SC_ENUM_TYPE InfoLevel,
1137 DWORD dwServiceType,
1138 DWORD dwServiceState,
1139 LPBYTE lpServices,
1140 DWORD cbBufSize,
1141 LPDWORD pcbBytesNeeded,
1142 LPDWORD lpServicesReturned,
1143 LPDWORD lpResumeHandle,
1144 LPCSTR pszGroupName)
1145 {
1146 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtr;
1147 DWORD dwError;
1148 DWORD dwCount;
1149
1150 TRACE("EnumServicesStatusExA() called\n");
1151
1152 _SEH_TRY
1153 {
1154 dwError = REnumServicesStatusExA((SC_RPC_HANDLE)hSCManager,
1155 InfoLevel,
1156 dwServiceType,
1157 dwServiceState,
1158 (LPBYTE)lpServices,
1159 cbBufSize,
1160 pcbBytesNeeded,
1161 lpServicesReturned,
1162 lpResumeHandle,
1163 (LPSTR)pszGroupName);
1164 }
1165 _SEH_HANDLE
1166 {
1167 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1168 }
1169 _SEH_END;
1170
1171 if (dwError == ERROR_MORE_DATA)
1172 {
1173 WARN("Required buffer size %ul\n", *pcbBytesNeeded);
1174 SetLastError(dwError);
1175 return FALSE;
1176 }
1177 else if (dwError == ERROR_SUCCESS)
1178 {
1179 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSA)lpServices;
1180 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
1181 {
1182 if (lpStatusPtr->lpServiceName)
1183 lpStatusPtr->lpServiceName =
1184 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
1185
1186 if (lpStatusPtr->lpDisplayName)
1187 lpStatusPtr->lpDisplayName =
1188 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
1189
1190 lpStatusPtr++;
1191 }
1192 }
1193 else
1194 {
1195 ERR("REnumServicesStatusExA() failed (Error %lu)\n", dwError);
1196 SetLastError(dwError);
1197 return FALSE;
1198 }
1199
1200 TRACE("EnumServicesStatusExA() done\n");
1201
1202 return TRUE;
1203 }
1204
1205
1206 /**********************************************************************
1207 * EnumServicesStatusExW
1208 *
1209 * @implemented
1210 */
1211 BOOL STDCALL
1212 EnumServicesStatusExW(SC_HANDLE hSCManager,
1213 SC_ENUM_TYPE InfoLevel,
1214 DWORD dwServiceType,
1215 DWORD dwServiceState,
1216 LPBYTE lpServices,
1217 DWORD cbBufSize,
1218 LPDWORD pcbBytesNeeded,
1219 LPDWORD lpServicesReturned,
1220 LPDWORD lpResumeHandle,
1221 LPCWSTR pszGroupName)
1222 {
1223 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
1224 DWORD dwError;
1225 DWORD dwCount;
1226
1227 TRACE("EnumServicesStatusExW() called\n");
1228
1229 _SEH_TRY
1230 {
1231 dwError = REnumServicesStatusExW((SC_RPC_HANDLE)hSCManager,
1232 InfoLevel,
1233 dwServiceType,
1234 dwServiceState,
1235 (LPBYTE)lpServices,
1236 cbBufSize,
1237 pcbBytesNeeded,
1238 lpServicesReturned,
1239 lpResumeHandle,
1240 (LPWSTR)pszGroupName);
1241 }
1242 _SEH_HANDLE
1243 {
1244 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1245 }
1246 _SEH_END;
1247
1248 if (dwError == ERROR_MORE_DATA)
1249 {
1250 WARN("Required buffer size %ul\n", *pcbBytesNeeded);
1251 SetLastError(dwError);
1252 return FALSE;
1253 }
1254 else if (dwError == ERROR_SUCCESS)
1255 {
1256 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices;
1257 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
1258 {
1259 if (lpStatusPtr->lpServiceName)
1260 lpStatusPtr->lpServiceName =
1261 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
1262
1263 if (lpStatusPtr->lpDisplayName)
1264 lpStatusPtr->lpDisplayName =
1265 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
1266
1267 lpStatusPtr++;
1268 }
1269 }
1270 else
1271 {
1272 ERR("REnumServicesStatusExW() failed (Error %lu)\n", dwError);
1273 SetLastError(dwError);
1274 return FALSE;
1275 }
1276
1277 TRACE("EnumServicesStatusExW() done\n");
1278
1279 return TRUE;
1280 }
1281
1282
1283 /**********************************************************************
1284 * GetServiceDisplayNameA
1285 *
1286 * @implemented
1287 */
1288 BOOL STDCALL
1289 GetServiceDisplayNameA(SC_HANDLE hSCManager,
1290 LPCSTR lpServiceName,
1291 LPSTR lpDisplayName,
1292 LPDWORD lpcchBuffer)
1293 {
1294 DWORD dwError;
1295
1296 TRACE("GetServiceDisplayNameA() called\n");
1297
1298 if (!lpDisplayName)
1299 *lpcchBuffer = 0;
1300
1301 _SEH_TRY
1302 {
1303 dwError = RGetServiceDisplayNameA((SC_RPC_HANDLE)hSCManager,
1304 (LPSTR)lpServiceName,
1305 lpDisplayName,
1306 lpcchBuffer);
1307 }
1308 _SEH_HANDLE
1309 {
1310 /* HACK: because of a problem with rpcrt4, rpcserver is hacked to return 6 for ERROR_SERVICE_DOES_NOT_EXIST */
1311 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1312 }
1313
1314
1315 _SEH_END;
1316
1317 if (dwError != ERROR_SUCCESS)
1318 {
1319 ERR("RGetServiceDisplayNameA() failed (Error %lu)\n", dwError);
1320 SetLastError(dwError);
1321 return FALSE;
1322 }
1323
1324 return TRUE;
1325 }
1326
1327
1328 /**********************************************************************
1329 * GetServiceDisplayNameW
1330 *
1331 * @implemented
1332 */
1333 BOOL STDCALL
1334 GetServiceDisplayNameW(SC_HANDLE hSCManager,
1335 LPCWSTR lpServiceName,
1336 LPWSTR lpDisplayName,
1337 LPDWORD lpcchBuffer)
1338 {
1339 DWORD dwError;
1340
1341 TRACE("GetServiceDisplayNameW() called\n");
1342
1343 if (!lpDisplayName)
1344 *lpcchBuffer = 0;
1345
1346 _SEH_TRY
1347 {
1348 dwError = RGetServiceDisplayNameW((SC_RPC_HANDLE)hSCManager,
1349 (LPWSTR)lpServiceName,
1350 lpDisplayName,
1351 lpcchBuffer);
1352 }
1353 _SEH_HANDLE
1354 {
1355 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1356 }
1357 _SEH_END;
1358
1359 if (dwError != ERROR_SUCCESS)
1360 {
1361 ERR("RGetServiceDisplayNameW() failed (Error %lu)\n", dwError);
1362 SetLastError(dwError);
1363 return FALSE;
1364 }
1365
1366 return TRUE;
1367 }
1368
1369
1370 /**********************************************************************
1371 * GetServiceKeyNameA
1372 *
1373 * @implemented
1374 */
1375 BOOL STDCALL
1376 GetServiceKeyNameA(SC_HANDLE hSCManager,
1377 LPCSTR lpDisplayName,
1378 LPSTR lpServiceName,
1379 LPDWORD lpcchBuffer)
1380 {
1381 DWORD dwError;
1382
1383 TRACE("GetServiceKeyNameA() called\n");
1384
1385 if (!lpServiceName)
1386 *lpcchBuffer = 0;
1387
1388 _SEH_TRY
1389 {
1390 dwError = RGetServiceKeyNameA((SC_RPC_HANDLE)hSCManager,
1391 (LPSTR)lpDisplayName,
1392 lpServiceName,
1393 lpcchBuffer);
1394 }
1395 _SEH_HANDLE
1396 {
1397 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1398 }
1399 _SEH_END;
1400
1401 if (dwError != ERROR_SUCCESS)
1402 {
1403 ERR("RGetServiceKeyNameA() failed (Error %lu)\n", dwError);
1404 SetLastError(dwError);
1405 return FALSE;
1406 }
1407
1408 return TRUE;
1409 }
1410
1411
1412 /**********************************************************************
1413 * GetServiceKeyNameW
1414 *
1415 * @implemented
1416 */
1417 BOOL STDCALL
1418 GetServiceKeyNameW(SC_HANDLE hSCManager,
1419 LPCWSTR lpDisplayName,
1420 LPWSTR lpServiceName,
1421 LPDWORD lpcchBuffer)
1422 {
1423 DWORD dwError;
1424
1425 TRACE("GetServiceKeyNameW() called\n");
1426
1427 if (!lpDisplayName)
1428 *lpcchBuffer = 0;
1429
1430 _SEH_TRY
1431 {
1432 dwError = RGetServiceKeyNameW((SC_RPC_HANDLE)hSCManager,
1433 (LPWSTR)lpDisplayName,
1434 lpServiceName,
1435 lpcchBuffer);
1436 }
1437 _SEH_HANDLE
1438 {
1439 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1440 }
1441 _SEH_END;
1442
1443 if (dwError != ERROR_SUCCESS)
1444 {
1445 ERR("RGetServiceKeyNameW() failed (Error %lu)\n", dwError);
1446 SetLastError(dwError);
1447 return FALSE;
1448 }
1449
1450 return TRUE;
1451 }
1452
1453
1454 /**********************************************************************
1455 * LockServiceDatabase
1456 *
1457 * @implemented
1458 */
1459 SC_LOCK STDCALL
1460 LockServiceDatabase(SC_HANDLE hSCManager)
1461 {
1462 SC_LOCK hLock;
1463 DWORD dwError;
1464
1465 TRACE("LockServiceDatabase(%x)\n", hSCManager);
1466
1467 _SEH_TRY
1468 {
1469 /* Call to services.exe using RPC */
1470 dwError = RLockServiceDatabase((SC_RPC_HANDLE)hSCManager,
1471 (SC_RPC_LOCK *)&hLock);
1472 }
1473 _SEH_HANDLE
1474 {
1475 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1476 }
1477 _SEH_END;
1478
1479 if (dwError != ERROR_SUCCESS)
1480 {
1481 ERR("RLockServiceDatabase() failed (Error %lu)\n", dwError);
1482 SetLastError(dwError);
1483 return NULL;
1484 }
1485
1486 TRACE("hLock = %p\n", hLock);
1487
1488 return hLock;
1489 }
1490
1491
1492 static VOID
1493 WaitForSCManager(VOID)
1494 {
1495 HANDLE hEvent;
1496
1497 TRACE("WaitForSCManager() called\n");
1498
1499 /* Try to open the existing event */
1500 hEvent = OpenEventW(SYNCHRONIZE,
1501 FALSE,
1502 L"SvcctrlStartEvent_A3752DX");
1503 if (hEvent == NULL)
1504 {
1505 if (GetLastError() != ERROR_FILE_NOT_FOUND)
1506 return;
1507
1508 /* Try to create a new event */
1509 hEvent = CreateEventW(NULL,
1510 TRUE,
1511 FALSE,
1512 L"SvcctrlStartEvent_A3752DX");
1513 if (hEvent == NULL)
1514 {
1515 /* Try to open the existing event again */
1516 hEvent = OpenEventW(SYNCHRONIZE,
1517 FALSE,
1518 L"SvcctrlStartEvent_A3752DX");
1519 if (hEvent == NULL)
1520 return;
1521 }
1522 }
1523
1524 /* Wait for 3 minutes */
1525 WaitForSingleObject(hEvent, 180000);
1526 CloseHandle(hEvent);
1527
1528 TRACE("ScmWaitForSCManager() done\n");
1529 }
1530
1531
1532 /**********************************************************************
1533 * OpenSCManagerA
1534 *
1535 * @implemented
1536 */
1537 SC_HANDLE STDCALL
1538 OpenSCManagerA(LPCSTR lpMachineName,
1539 LPCSTR lpDatabaseName,
1540 DWORD dwDesiredAccess)
1541 {
1542 SC_HANDLE hScm = NULL;
1543 DWORD dwError;
1544
1545 TRACE("OpenSCManagerA(%s, %s, %lx)\n",
1546 lpMachineName, lpDatabaseName, dwDesiredAccess);
1547
1548 WaitForSCManager();
1549
1550 _SEH_TRY
1551 {
1552 /* Call to services.exe using RPC */
1553 dwError = ROpenSCManagerA((LPSTR)lpMachineName,
1554 (LPSTR)lpDatabaseName,
1555 dwDesiredAccess,
1556 (SC_RPC_HANDLE *)&hScm);
1557 }
1558 _SEH_HANDLE
1559 {
1560 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1561 }
1562 _SEH_END;
1563
1564 if (dwError != ERROR_SUCCESS)
1565 {
1566 ERR("ROpenSCManagerA() failed (Error %lu)\n", dwError);
1567 SetLastError(dwError);
1568 return NULL;
1569 }
1570
1571 TRACE("hScm = %p\n", hScm);
1572
1573 return hScm;
1574 }
1575
1576
1577 /**********************************************************************
1578 * OpenSCManagerW
1579 *
1580 * @implemented
1581 */
1582 SC_HANDLE STDCALL
1583 OpenSCManagerW(LPCWSTR lpMachineName,
1584 LPCWSTR lpDatabaseName,
1585 DWORD dwDesiredAccess)
1586 {
1587 SC_HANDLE hScm = NULL;
1588 DWORD dwError;
1589
1590 TRACE("OpenSCManagerW(%S, %S, %lx)\n",
1591 lpMachineName, lpDatabaseName, dwDesiredAccess);
1592
1593 WaitForSCManager();
1594
1595 _SEH_TRY
1596 {
1597 /* Call to services.exe using RPC */
1598 dwError = ROpenSCManagerW((LPWSTR)lpMachineName,
1599 (LPWSTR)lpDatabaseName,
1600 dwDesiredAccess,
1601 (SC_RPC_HANDLE *)&hScm);
1602 }
1603 _SEH_HANDLE
1604 {
1605 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1606 }
1607 _SEH_END;
1608
1609 if (dwError != ERROR_SUCCESS)
1610 {
1611 ERR("ROpenSCManagerW() failed (Error %lu)\n", dwError);
1612 SetLastError(dwError);
1613 return NULL;
1614 }
1615
1616 TRACE("hScm = %p\n", hScm);
1617
1618 return hScm;
1619 }
1620
1621
1622 /**********************************************************************
1623 * OpenServiceA
1624 *
1625 * @implemented
1626 */
1627 SC_HANDLE STDCALL
1628 OpenServiceA(SC_HANDLE hSCManager,
1629 LPCSTR lpServiceName,
1630 DWORD dwDesiredAccess)
1631 {
1632 SC_HANDLE hService = NULL;
1633 DWORD dwError;
1634
1635 TRACE("OpenServiceA(%p, %s, %lx)\n",
1636 hSCManager, lpServiceName, dwDesiredAccess);
1637
1638 _SEH_TRY
1639 {
1640 /* Call to services.exe using RPC */
1641 dwError = ROpenServiceA((SC_RPC_HANDLE)hSCManager,
1642 (LPSTR)lpServiceName,
1643 dwDesiredAccess,
1644 (SC_RPC_HANDLE *)&hService);
1645 }
1646 _SEH_HANDLE
1647 {
1648 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1649 }
1650 _SEH_END;
1651
1652 if (dwError != ERROR_SUCCESS)
1653 {
1654 ERR("ROpenServiceA() failed (Error %lu)\n", dwError);
1655 SetLastError(dwError);
1656 return NULL;
1657 }
1658
1659 TRACE("hService = %p\n", hService);
1660
1661 return hService;
1662 }
1663
1664
1665 /**********************************************************************
1666 * OpenServiceW
1667 *
1668 * @implemented
1669 */
1670 SC_HANDLE STDCALL
1671 OpenServiceW(SC_HANDLE hSCManager,
1672 LPCWSTR lpServiceName,
1673 DWORD dwDesiredAccess)
1674 {
1675 SC_HANDLE hService = NULL;
1676 DWORD dwError;
1677
1678 TRACE("OpenServiceW(%p, %S, %lx)\n",
1679 hSCManager, lpServiceName, dwDesiredAccess);
1680
1681 _SEH_TRY
1682 {
1683 /* Call to services.exe using RPC */
1684 dwError = ROpenServiceW((SC_RPC_HANDLE)hSCManager,
1685 (LPWSTR)lpServiceName,
1686 dwDesiredAccess,
1687 (SC_RPC_HANDLE *)&hService);
1688 }
1689 _SEH_HANDLE
1690 {
1691 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1692 }
1693 _SEH_END;
1694
1695 if (dwError != ERROR_SUCCESS)
1696 {
1697 if (dwError == ERROR_SERVICE_DOES_NOT_EXIST)
1698 WARN("ROpenServiceW() failed (Error %lu)\n", dwError);
1699 else
1700 ERR("ROpenServiceW() failed (Error %lu)\n", dwError);
1701 SetLastError(dwError);
1702 return NULL;
1703 }
1704
1705 TRACE("hService = %p\n", hService);
1706
1707 return hService;
1708 }
1709
1710
1711 /**********************************************************************
1712 * QueryServiceConfigA
1713 *
1714 * @implemented
1715 */
1716 BOOL STDCALL
1717 QueryServiceConfigA(SC_HANDLE hService,
1718 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
1719 DWORD cbBufSize,
1720 LPDWORD pcbBytesNeeded)
1721 {
1722 DWORD dwError;
1723
1724 TRACE("QueryServiceConfigA(%p, %p, %lu, %p)\n",
1725 hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
1726
1727 _SEH_TRY
1728 {
1729 /* Call to services.exe using RPC */
1730 dwError = RQueryServiceConfigA((SC_RPC_HANDLE)hService,
1731 (LPBYTE)lpServiceConfig,
1732 cbBufSize,
1733 pcbBytesNeeded);
1734 }
1735 _SEH_HANDLE
1736 {
1737 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1738 }
1739 _SEH_END;
1740
1741 if (dwError != ERROR_SUCCESS)
1742 {
1743 ERR("RQueryServiceConfigA() failed (Error %lu)\n", dwError);
1744 SetLastError(dwError);
1745 return FALSE;
1746 }
1747
1748 /* Adjust the pointers */
1749 if (lpServiceConfig->lpBinaryPathName)
1750 lpServiceConfig->lpBinaryPathName =
1751 (LPSTR)((ULONG_PTR)lpServiceConfig +
1752 (ULONG_PTR)lpServiceConfig->lpBinaryPathName);
1753
1754 if (lpServiceConfig->lpLoadOrderGroup)
1755 lpServiceConfig->lpLoadOrderGroup =
1756 (LPSTR)((ULONG_PTR)lpServiceConfig +
1757 (ULONG_PTR)lpServiceConfig->lpLoadOrderGroup);
1758
1759 if (lpServiceConfig->lpDependencies)
1760 lpServiceConfig->lpDependencies =
1761 (LPSTR)((ULONG_PTR)lpServiceConfig +
1762 (ULONG_PTR)lpServiceConfig->lpDependencies);
1763
1764 if (lpServiceConfig->lpServiceStartName)
1765 lpServiceConfig->lpServiceStartName =
1766 (LPSTR)((ULONG_PTR)lpServiceConfig +
1767 (ULONG_PTR)lpServiceConfig->lpServiceStartName);
1768
1769 if (lpServiceConfig->lpDisplayName)
1770 lpServiceConfig->lpDisplayName =
1771 (LPSTR)((ULONG_PTR)lpServiceConfig +
1772 (ULONG_PTR)lpServiceConfig->lpDisplayName);
1773
1774 TRACE("QueryServiceConfigA() done\n");
1775
1776 return TRUE;
1777 }
1778
1779
1780 /**********************************************************************
1781 * QueryServiceConfigW
1782 *
1783 * @implemented
1784 */
1785 BOOL STDCALL
1786 QueryServiceConfigW(SC_HANDLE hService,
1787 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1788 DWORD cbBufSize,
1789 LPDWORD pcbBytesNeeded)
1790 {
1791 DWORD dwError;
1792
1793 TRACE("QueryServiceConfigW(%p, %p, %lu, %p)\n",
1794 hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
1795
1796 _SEH_TRY
1797 {
1798 /* Call to services.exe using RPC */
1799 dwError = RQueryServiceConfigW((SC_RPC_HANDLE)hService,
1800 (LPBYTE)lpServiceConfig,
1801 cbBufSize,
1802 pcbBytesNeeded);
1803 }
1804 _SEH_HANDLE
1805 {
1806 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1807 }
1808 _SEH_END;
1809
1810 if (dwError != ERROR_SUCCESS)
1811 {
1812 if (dwError == ERROR_INSUFFICIENT_BUFFER)
1813 WARN("RQueryServiceConfigW() failed (Error %lu)\n", dwError);
1814 else
1815 ERR("RQueryServiceConfigW() failed (Error %lu)\n", dwError);
1816 SetLastError(dwError);
1817 return FALSE;
1818 }
1819
1820 /* Adjust the pointers */
1821 if (lpServiceConfig->lpBinaryPathName)
1822 lpServiceConfig->lpBinaryPathName =
1823 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1824 (ULONG_PTR)lpServiceConfig->lpBinaryPathName);
1825
1826 if (lpServiceConfig->lpLoadOrderGroup)
1827 lpServiceConfig->lpLoadOrderGroup =
1828 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1829 (ULONG_PTR)lpServiceConfig->lpLoadOrderGroup);
1830
1831 if (lpServiceConfig->lpDependencies)
1832 lpServiceConfig->lpDependencies =
1833 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1834 (ULONG_PTR)lpServiceConfig->lpDependencies);
1835
1836 if (lpServiceConfig->lpServiceStartName)
1837 lpServiceConfig->lpServiceStartName =
1838 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1839 (ULONG_PTR)lpServiceConfig->lpServiceStartName);
1840
1841 if (lpServiceConfig->lpDisplayName)
1842 lpServiceConfig->lpDisplayName =
1843 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1844 (ULONG_PTR)lpServiceConfig->lpDisplayName);
1845
1846 TRACE("QueryServiceConfigW() done\n");
1847
1848 return TRUE;
1849 }
1850
1851
1852 /**********************************************************************
1853 * QueryServiceConfig2A
1854 *
1855 * @implemented
1856 */
1857 BOOL STDCALL
1858 QueryServiceConfig2A(SC_HANDLE hService,
1859 DWORD dwInfoLevel,
1860 LPBYTE lpBuffer,
1861 DWORD cbBufSize,
1862 LPDWORD pcbBytesNeeded)
1863 {
1864 DWORD dwError;
1865
1866 TRACE("QueryServiceConfig2A(%p, %lu, %p, %lu, %p)\n",
1867 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1868
1869 if (dwInfoLevel != SERVICE_CONFIG_DESCRIPTION &&
1870 dwInfoLevel != SERVICE_CONFIG_FAILURE_ACTIONS)
1871 {
1872 SetLastError(ERROR_INVALID_LEVEL);
1873 return FALSE;
1874 }
1875
1876 if ((lpBuffer == NULL && cbBufSize != 0) ||
1877 pcbBytesNeeded == NULL)
1878 {
1879 SetLastError(ERROR_INVALID_ADDRESS);
1880 return FALSE;
1881 }
1882
1883 _SEH_TRY
1884 {
1885 /* Call to services.exe using RPC */
1886 dwError = RQueryServiceConfig2A((SC_RPC_HANDLE)hService,
1887 dwInfoLevel,
1888 lpBuffer,
1889 cbBufSize,
1890 pcbBytesNeeded);
1891 }
1892 _SEH_HANDLE
1893 {
1894 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1895 }
1896 _SEH_END;
1897
1898 if (dwError != ERROR_SUCCESS)
1899 {
1900 ERR("RQueryServiceConfig2A() failed (Error %lu)\n", dwError);
1901 SetLastError(dwError);
1902 return FALSE;
1903 }
1904
1905 switch (dwInfoLevel)
1906 {
1907 case SERVICE_CONFIG_DESCRIPTION:
1908 {
1909 LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpBuffer;
1910
1911 if (lpPtr->lpDescription != NULL)
1912 lpPtr->lpDescription =
1913 (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpDescription);
1914 }
1915 break;
1916
1917 case SERVICE_CONFIG_FAILURE_ACTIONS:
1918 {
1919 LPSERVICE_FAILURE_ACTIONSA lpPtr = (LPSERVICE_FAILURE_ACTIONSA)lpBuffer;
1920
1921 if (lpPtr->lpRebootMsg != NULL)
1922 lpPtr->lpRebootMsg =
1923 (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpRebootMsg);
1924
1925 if (lpPtr->lpCommand != NULL)
1926 lpPtr->lpCommand =
1927 (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpCommand);
1928
1929 if (lpPtr->lpsaActions != NULL)
1930 lpPtr->lpsaActions =
1931 (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
1932 }
1933 break;
1934
1935 default:
1936 ERR("Unknown info level 0x%lx\n", dwInfoLevel);
1937 SetLastError(ERROR_INVALID_PARAMETER);
1938 return FALSE;
1939 }
1940
1941 TRACE("QueryServiceConfig2A() done\n");
1942
1943 return TRUE;
1944 }
1945
1946
1947 /**********************************************************************
1948 * QueryServiceConfig2W
1949 *
1950 * @implemented
1951 */
1952 BOOL STDCALL
1953 QueryServiceConfig2W(SC_HANDLE hService,
1954 DWORD dwInfoLevel,
1955 LPBYTE lpBuffer,
1956 DWORD cbBufSize,
1957 LPDWORD pcbBytesNeeded)
1958 {
1959 DWORD dwError;
1960
1961 TRACE("QueryServiceConfig2W(%p, %lu, %p, %lu, %p)\n",
1962 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1963
1964 if (dwInfoLevel != SERVICE_CONFIG_DESCRIPTION &&
1965 dwInfoLevel != SERVICE_CONFIG_FAILURE_ACTIONS)
1966 {
1967 SetLastError(ERROR_INVALID_LEVEL);
1968 return FALSE;
1969 }
1970
1971 if ((lpBuffer == NULL && cbBufSize != 0) ||
1972 pcbBytesNeeded == NULL)
1973 {
1974 SetLastError(ERROR_INVALID_ADDRESS);
1975 return FALSE;
1976 }
1977
1978 _SEH_TRY
1979 {
1980 /* Call to services.exe using RPC */
1981 dwError = RQueryServiceConfig2W((SC_RPC_HANDLE)hService,
1982 dwInfoLevel,
1983 lpBuffer,
1984 cbBufSize,
1985 pcbBytesNeeded);
1986 }
1987 _SEH_HANDLE
1988 {
1989 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1990 }
1991 _SEH_END;
1992
1993 if (dwError != ERROR_SUCCESS)
1994 {
1995 ERR("RQueryServiceConfig2W() failed (Error %lu)\n", dwError);
1996 SetLastError(dwError);
1997 return FALSE;
1998 }
1999
2000 switch (dwInfoLevel)
2001 {
2002 case SERVICE_CONFIG_DESCRIPTION:
2003 {
2004 LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpBuffer;
2005
2006 if (lpPtr->lpDescription != NULL)
2007 lpPtr->lpDescription =
2008 (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpDescription);
2009 }
2010 break;
2011
2012 case SERVICE_CONFIG_FAILURE_ACTIONS:
2013 {
2014 LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer;
2015
2016 if (lpPtr->lpRebootMsg != NULL)
2017 lpPtr->lpRebootMsg =
2018 (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpRebootMsg);
2019
2020 if (lpPtr->lpCommand != NULL)
2021 lpPtr->lpCommand =
2022 (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpCommand);
2023
2024 if (lpPtr->lpsaActions != NULL)
2025 lpPtr->lpsaActions =
2026 (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
2027 }
2028 break;
2029
2030 default:
2031 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
2032 SetLastError(ERROR_INVALID_PARAMETER);
2033 return FALSE;
2034 }
2035
2036 TRACE("QueryServiceConfig2W() done\n");
2037
2038 return TRUE;
2039 }
2040
2041
2042 /**********************************************************************
2043 * QueryServiceLockStatusA
2044 *
2045 * @implemented
2046 */
2047 BOOL STDCALL
2048 QueryServiceLockStatusA(SC_HANDLE hSCManager,
2049 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
2050 DWORD cbBufSize,
2051 LPDWORD pcbBytesNeeded)
2052 {
2053 DWORD dwError;
2054
2055 TRACE("QueryServiceLockStatusA() called\n");
2056
2057 _SEH_TRY
2058 {
2059 /* Call to services.exe using RPC */
2060 dwError = RQueryServiceLockStatusA((SC_RPC_HANDLE)hSCManager,
2061 lpLockStatus,
2062 cbBufSize,
2063 pcbBytesNeeded);
2064 }
2065 _SEH_HANDLE
2066 {
2067 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2068 }
2069 _SEH_END;
2070
2071 if (dwError != ERROR_SUCCESS)
2072 {
2073 ERR("RQueryServiceLockStatusA() failed (Error %lu)\n", dwError);
2074 SetLastError(dwError);
2075 return FALSE;
2076 }
2077
2078 if (lpLockStatus->lpLockOwner != NULL)
2079 {
2080 lpLockStatus->lpLockOwner =
2081 (LPSTR)((UINT_PTR)lpLockStatus + (UINT_PTR)lpLockStatus->lpLockOwner);
2082 }
2083
2084 TRACE("QueryServiceLockStatusA() done\n");
2085
2086 return TRUE;
2087 }
2088
2089
2090 /**********************************************************************
2091 * QueryServiceLockStatusW
2092 *
2093 * @implemented
2094 */
2095 BOOL STDCALL
2096 QueryServiceLockStatusW(SC_HANDLE hSCManager,
2097 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
2098 DWORD cbBufSize,
2099 LPDWORD pcbBytesNeeded)
2100 {
2101 DWORD dwError;
2102
2103 TRACE("QueryServiceLockStatusW() called\n");
2104
2105 _SEH_TRY
2106 {
2107 /* Call to services.exe using RPC */
2108 dwError = RQueryServiceLockStatusW((SC_RPC_HANDLE)hSCManager,
2109 lpLockStatus,
2110 cbBufSize,
2111 pcbBytesNeeded);
2112 }
2113 _SEH_HANDLE
2114 {
2115 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2116 }
2117 _SEH_END;
2118
2119 if (dwError != ERROR_SUCCESS)
2120 {
2121 ERR("RQueryServiceLockStatusW() failed (Error %lu)\n", dwError);
2122 SetLastError(dwError);
2123 return FALSE;
2124 }
2125
2126 if (lpLockStatus->lpLockOwner != NULL)
2127 {
2128 lpLockStatus->lpLockOwner =
2129 (LPWSTR)((UINT_PTR)lpLockStatus + (UINT_PTR)lpLockStatus->lpLockOwner);
2130 }
2131
2132 TRACE("QueryServiceLockStatusW() done\n");
2133
2134 return TRUE;
2135 }
2136
2137
2138 /**********************************************************************
2139 * QueryServiceObjectSecurity
2140 *
2141 * @implemented
2142 */
2143 BOOL STDCALL
2144 QueryServiceObjectSecurity(SC_HANDLE hService,
2145 SECURITY_INFORMATION dwSecurityInformation,
2146 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2147 DWORD cbBufSize,
2148 LPDWORD pcbBytesNeeded)
2149 {
2150 DWORD dwError;
2151
2152 TRACE("QueryServiceObjectSecurity(%p, %lu, %p)\n",
2153 hService, dwSecurityInformation, lpSecurityDescriptor);
2154
2155 _SEH_TRY
2156 {
2157 /* Call to services.exe using RPC */
2158 dwError = RQueryServiceObjectSecurity((SC_RPC_HANDLE)hService,
2159 dwSecurityInformation,
2160 (LPBYTE)lpSecurityDescriptor,
2161 cbBufSize,
2162 pcbBytesNeeded);
2163 }
2164 _SEH_HANDLE
2165 {
2166 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2167 }
2168 _SEH_END;
2169
2170 if (dwError != ERROR_SUCCESS)
2171 {
2172 ERR("QueryServiceObjectSecurity() failed (Error %lu)\n", dwError);
2173 SetLastError(dwError);
2174 return FALSE;
2175 }
2176
2177 return TRUE;
2178 }
2179
2180 /**********************************************************************
2181 * SetServiceObjectSecurity
2182 *
2183 * @implemented
2184 */
2185 BOOL STDCALL
2186 SetServiceObjectSecurity(SC_HANDLE hService,
2187 SECURITY_INFORMATION dwSecurityInformation,
2188 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2189 {
2190 PSECURITY_DESCRIPTOR SelfRelativeSD = NULL;
2191 ULONG Length;
2192 NTSTATUS Status;
2193 DWORD dwError;
2194
2195 Length = 0;
2196 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
2197 SelfRelativeSD,
2198 &Length);
2199 if (Status != STATUS_BUFFER_TOO_SMALL)
2200 {
2201 SetLastError(ERROR_INVALID_PARAMETER);
2202 return FALSE;
2203 }
2204
2205 SelfRelativeSD = HeapAlloc(GetProcessHeap(), 0, Length);
2206 if (SelfRelativeSD == NULL)
2207 {
2208 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2209 return FALSE;
2210 }
2211
2212 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
2213 SelfRelativeSD,
2214 &Length);
2215 if (!NT_SUCCESS(Status))
2216 {
2217 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
2218 SetLastError(RtlNtStatusToDosError(Status));
2219 return FALSE;
2220 }
2221
2222 _SEH_TRY
2223 {
2224 /* Call to services.exe using RPC */
2225 dwError = RSetServiceObjectSecurity((SC_RPC_HANDLE)hService,
2226 dwSecurityInformation,
2227 (LPBYTE)SelfRelativeSD,
2228 Length);
2229 }
2230 _SEH_HANDLE
2231 {
2232 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2233 }
2234 _SEH_END;
2235
2236 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
2237
2238 if (dwError != ERROR_SUCCESS)
2239 {
2240 ERR("RServiceObjectSecurity() failed (Error %lu)\n", dwError);
2241 SetLastError(dwError);
2242 return FALSE;
2243 }
2244
2245 return TRUE;
2246 }
2247
2248
2249 /**********************************************************************
2250 * QueryServiceStatus
2251 *
2252 * @implemented
2253 */
2254 BOOL STDCALL
2255 QueryServiceStatus(SC_HANDLE hService,
2256 LPSERVICE_STATUS lpServiceStatus)
2257 {
2258 DWORD dwError;
2259
2260 TRACE("QueryServiceStatus(%p, %p)\n",
2261 hService, lpServiceStatus);
2262
2263 _SEH_TRY
2264 {
2265 /* Call to services.exe using RPC */
2266 dwError = RQueryServiceStatus((SC_RPC_HANDLE)hService,
2267 lpServiceStatus);
2268 }
2269 _SEH_HANDLE
2270 {
2271 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2272 }
2273 _SEH_END;
2274
2275 if (dwError != ERROR_SUCCESS)
2276 {
2277 ERR("RQueryServiceStatus() failed (Error %lu)\n", dwError);
2278 SetLastError(dwError);
2279 return FALSE;
2280 }
2281
2282 return TRUE;
2283 }
2284
2285
2286 /**********************************************************************
2287 * QueryServiceStatusEx
2288 *
2289 * @implemented
2290 */
2291 BOOL STDCALL
2292 QueryServiceStatusEx(SC_HANDLE hService,
2293 SC_STATUS_TYPE InfoLevel,
2294 LPBYTE lpBuffer,
2295 DWORD cbBufSize,
2296 LPDWORD pcbBytesNeeded)
2297 {
2298 DWORD dwError;
2299
2300 TRACE("QueryServiceStatusEx() called\n");
2301
2302 _SEH_TRY
2303 {
2304 /* Call to services.exe using RPC */
2305 dwError = RQueryServiceStatusEx((SC_RPC_HANDLE)hService,
2306 InfoLevel,
2307 lpBuffer,
2308 cbBufSize,
2309 pcbBytesNeeded);
2310 }
2311 _SEH_HANDLE
2312 {
2313 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2314 }
2315 _SEH_END;
2316
2317 if (dwError != ERROR_SUCCESS)
2318 {
2319 ERR("RQueryServiceStatusEx() failed (Error %lu)\n", dwError);
2320 SetLastError(dwError);
2321 return FALSE;
2322 }
2323
2324 return TRUE;
2325 }
2326
2327
2328 /**********************************************************************
2329 * StartServiceA
2330 *
2331 * @implemented
2332 */
2333 BOOL STDCALL
2334 StartServiceA(SC_HANDLE hService,
2335 DWORD dwNumServiceArgs,
2336 LPCSTR *lpServiceArgVectors)
2337 {
2338 DWORD dwError;
2339
2340 _SEH_TRY
2341 {
2342 dwError = RStartServiceA((SC_RPC_HANDLE)hService,
2343 dwNumServiceArgs,
2344 (LPSTRING_PTRSA)lpServiceArgVectors);
2345 }
2346 _SEH_HANDLE
2347 {
2348 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2349 }
2350 _SEH_END;
2351
2352 if (dwError != ERROR_SUCCESS)
2353 {
2354 ERR("RStartServiceA() failed (Error %lu)\n", dwError);
2355 SetLastError(dwError);
2356 return FALSE;
2357 }
2358
2359 return TRUE;
2360 }
2361
2362
2363 /**********************************************************************
2364 * StartServiceW
2365 *
2366 * @implemented
2367 */
2368 BOOL STDCALL
2369 StartServiceW(SC_HANDLE hService,
2370 DWORD dwNumServiceArgs,
2371 LPCWSTR *lpServiceArgVectors)
2372 {
2373 DWORD dwError;
2374
2375 _SEH_TRY
2376 {
2377 dwError = RStartServiceW((SC_RPC_HANDLE)hService,
2378 dwNumServiceArgs,
2379 (LPSTRING_PTRSW)lpServiceArgVectors);
2380 }
2381 _SEH_HANDLE
2382 {
2383 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2384 }
2385 _SEH_END;
2386
2387 if (dwError != ERROR_SUCCESS)
2388 {
2389 ERR("RStartServiceW() failed (Error %lu)\n", dwError);
2390 SetLastError(dwError);
2391 return FALSE;
2392 }
2393
2394 return TRUE;
2395 }
2396
2397
2398 /**********************************************************************
2399 * UnlockServiceDatabase
2400 *
2401 * @implemented
2402 */
2403 BOOL STDCALL
2404 UnlockServiceDatabase(SC_LOCK ScLock)
2405 {
2406 DWORD dwError;
2407
2408 TRACE("UnlockServiceDatabase(%x)\n", ScLock);
2409
2410 _SEH_TRY
2411 {
2412 /* Call to services.exe using RPC */
2413 dwError = RUnlockServiceDatabase((LPSC_RPC_LOCK)&ScLock);
2414 }
2415 _SEH_HANDLE
2416 {
2417 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2418 }
2419 _SEH_END;
2420
2421 if (dwError != ERROR_SUCCESS)
2422 {
2423 ERR("RUnlockServiceDatabase() failed (Error %lu)\n", dwError);
2424 SetLastError(dwError);
2425 return FALSE;
2426 }
2427
2428 return TRUE;
2429 }
2430
2431
2432 /**********************************************************************
2433 * NotifyBootConfigStatus
2434 *
2435 * @implemented
2436 */
2437 BOOL STDCALL
2438 NotifyBootConfigStatus(BOOL BootAcceptable)
2439 {
2440 DWORD dwError;
2441
2442 TRACE("NotifyBootConfigStatus()\n");
2443
2444 _SEH_TRY
2445 {
2446 /* Call to services.exe using RPC */
2447 dwError = RNotifyBootConfigStatus(NULL,
2448 BootAcceptable);
2449 }
2450 _SEH_HANDLE
2451 {
2452 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2453 }
2454 _SEH_END;
2455
2456 if (dwError != ERROR_SUCCESS)
2457 {
2458 ERR("NotifyBootConfigStatus() failed (Error %lu)\n", dwError);
2459 SetLastError(dwError);
2460 return FALSE;
2461 }
2462
2463 return TRUE;
2464 }
2465
2466 /* EOF */