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