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