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