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