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