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