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