[ADVAPI32]
[reactos.git] / reactos / dll / win32 / advapi32 / service / scm.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/advapi32/service/scm.c
5 * PURPOSE: Service control manager functions
6 * PROGRAMMER: Emanuele Aliberti
7 * Eric Kohl
8 * UPDATE HISTORY:
9 * 19990413 EA created
10 * 19990515 EA
11 */
12
13 /* INCLUDES ******************************************************************/
14
15 #include <advapi32.h>
16 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
17
18
19 /* FUNCTIONS *****************************************************************/
20
21 handle_t __RPC_USER
22 SVCCTL_HANDLEA_bind(SVCCTL_HANDLEA szMachineName)
23 {
24 handle_t hBinding = NULL;
25 UCHAR *pszStringBinding;
26 RPC_STATUS status;
27
28 TRACE("SVCCTL_HANDLEA_bind() called\n");
29
30 status = RpcStringBindingComposeA(NULL,
31 (UCHAR *)"ncacn_np",
32 (UCHAR *)szMachineName,
33 (UCHAR *)"\\pipe\\ntsvcs",
34 NULL,
35 (UCHAR **)&pszStringBinding);
36 if (status != RPC_S_OK)
37 {
38 ERR("RpcStringBindingCompose returned 0x%x\n", status);
39 return NULL;
40 }
41
42 /* Set the binding handle that will be used to bind to the server. */
43 status = RpcBindingFromStringBindingA(pszStringBinding,
44 &hBinding);
45 if (status != RPC_S_OK)
46 {
47 ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
48 }
49
50 status = RpcStringFreeA(&pszStringBinding);
51 if (status != RPC_S_OK)
52 {
53 ERR("RpcStringFree returned 0x%x\n", status);
54 }
55
56 return hBinding;
57 }
58
59
60 void __RPC_USER
61 SVCCTL_HANDLEA_unbind(SVCCTL_HANDLEA szMachineName,
62 handle_t hBinding)
63 {
64 RPC_STATUS status;
65
66 TRACE("SVCCTL_HANDLEA_unbind() called\n");
67
68 status = RpcBindingFree(&hBinding);
69 if (status != RPC_S_OK)
70 {
71 ERR("RpcBindingFree returned 0x%x\n", status);
72 }
73 }
74
75
76 handle_t __RPC_USER
77 SVCCTL_HANDLEW_bind(SVCCTL_HANDLEW szMachineName)
78 {
79 handle_t hBinding = NULL;
80 LPWSTR pszStringBinding;
81 RPC_STATUS status;
82
83 TRACE("SVCCTL_HANDLEW_bind() called\n");
84
85 status = RpcStringBindingComposeW(NULL,
86 L"ncacn_np",
87 szMachineName,
88 L"\\pipe\\ntsvcs",
89 NULL,
90 &pszStringBinding);
91 if (status != RPC_S_OK)
92 {
93 ERR("RpcStringBindingCompose returned 0x%x\n", status);
94 return NULL;
95 }
96
97 /* Set the binding handle that will be used to bind to the server. */
98 status = RpcBindingFromStringBindingW(pszStringBinding,
99 &hBinding);
100 if (status != RPC_S_OK)
101 {
102 ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
103 }
104
105 status = RpcStringFreeW(&pszStringBinding);
106 if (status != RPC_S_OK)
107 {
108 ERR("RpcStringFree returned 0x%x\n", status);
109 }
110
111 return hBinding;
112 }
113
114
115 void __RPC_USER
116 SVCCTL_HANDLEW_unbind(SVCCTL_HANDLEW szMachineName,
117 handle_t hBinding)
118 {
119 RPC_STATUS status;
120
121 TRACE("SVCCTL_HANDLEW_unbind() called\n");
122
123 status = RpcBindingFree(&hBinding);
124 if (status != RPC_S_OK)
125 {
126 ERR("RpcBindingFree returned 0x%x\n", status);
127 }
128 }
129
130
131 DWORD
132 ScmRpcStatusToWinError(RPC_STATUS Status)
133 {
134 switch (Status)
135 {
136 case 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 LPSTR lpStr;
292
293 TRACE("ChangeServiceConfigA() called\n");
294
295 /* Calculate the Dependencies length*/
296 if (lpDependencies != NULL)
297 {
298 lpStr = (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 LPWSTR lpStr;
366
367 TRACE("ChangeServiceConfigW() called\n");
368
369 /* Calculate the Dependencies length*/
370 if (lpDependencies != NULL)
371 {
372 lpStr = (LPWSTR)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 LPSTR 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 = (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 LPWSTR 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 = (LPWSTR)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 DWORD dwError;
2080
2081 TRACE("QueryServiceConfig2A(hService %p, dwInfoLevel %lu, lpBuffer %p, cbBufSize %lu, pcbBytesNeeded %p)\n",
2082 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
2083
2084 if (dwInfoLevel != SERVICE_CONFIG_DESCRIPTION &&
2085 dwInfoLevel != SERVICE_CONFIG_FAILURE_ACTIONS)
2086 {
2087 SetLastError(ERROR_INVALID_LEVEL);
2088 return FALSE;
2089 }
2090
2091 if ((lpBuffer == NULL && cbBufSize != 0) ||
2092 pcbBytesNeeded == NULL)
2093 {
2094 SetLastError(ERROR_INVALID_ADDRESS);
2095 return FALSE;
2096 }
2097
2098 RpcTryExcept
2099 {
2100 /* Call to services.exe using RPC */
2101 dwError = RQueryServiceConfig2A((SC_RPC_HANDLE)hService,
2102 dwInfoLevel,
2103 lpBuffer,
2104 cbBufSize,
2105 pcbBytesNeeded);
2106 }
2107 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2108 {
2109 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2110 }
2111 RpcEndExcept;
2112
2113 if (dwError != ERROR_SUCCESS)
2114 {
2115 TRACE("RQueryServiceConfig2A() failed (Error %lu)\n", dwError);
2116 SetLastError(dwError);
2117 return FALSE;
2118 }
2119
2120 switch (dwInfoLevel)
2121 {
2122 case SERVICE_CONFIG_DESCRIPTION:
2123 {
2124 LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpBuffer;
2125
2126 if (lpPtr->lpDescription != NULL)
2127 lpPtr->lpDescription =
2128 (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpDescription);
2129 }
2130 break;
2131
2132 case SERVICE_CONFIG_FAILURE_ACTIONS:
2133 {
2134 LPSERVICE_FAILURE_ACTIONSA lpPtr = (LPSERVICE_FAILURE_ACTIONSA)lpBuffer;
2135
2136 if (lpPtr->lpRebootMsg != NULL)
2137 lpPtr->lpRebootMsg =
2138 (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpRebootMsg);
2139
2140 if (lpPtr->lpCommand != NULL)
2141 lpPtr->lpCommand =
2142 (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpCommand);
2143
2144 if (lpPtr->lpsaActions != NULL)
2145 lpPtr->lpsaActions =
2146 (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
2147 }
2148 break;
2149
2150 default:
2151 ERR("Unknown info level 0x%lx\n", dwInfoLevel);
2152 SetLastError(ERROR_INVALID_PARAMETER);
2153 return FALSE;
2154 }
2155
2156 TRACE("QueryServiceConfig2A() done\n");
2157
2158 return TRUE;
2159 }
2160
2161
2162 /**********************************************************************
2163 * QueryServiceConfig2W
2164 *
2165 * @implemented
2166 */
2167 BOOL WINAPI
2168 QueryServiceConfig2W(SC_HANDLE hService,
2169 DWORD dwInfoLevel,
2170 LPBYTE lpBuffer,
2171 DWORD cbBufSize,
2172 LPDWORD pcbBytesNeeded)
2173 {
2174 DWORD dwError;
2175
2176 TRACE("QueryServiceConfig2W(%p, %lu, %p, %lu, %p)\n",
2177 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
2178
2179 if (dwInfoLevel != SERVICE_CONFIG_DESCRIPTION &&
2180 dwInfoLevel != SERVICE_CONFIG_FAILURE_ACTIONS)
2181 {
2182 SetLastError(ERROR_INVALID_LEVEL);
2183 return FALSE;
2184 }
2185
2186 if ((lpBuffer == NULL && cbBufSize != 0) ||
2187 pcbBytesNeeded == NULL)
2188 {
2189 SetLastError(ERROR_INVALID_ADDRESS);
2190 return FALSE;
2191 }
2192
2193 RpcTryExcept
2194 {
2195 /* Call to services.exe using RPC */
2196 dwError = RQueryServiceConfig2W((SC_RPC_HANDLE)hService,
2197 dwInfoLevel,
2198 lpBuffer,
2199 cbBufSize,
2200 pcbBytesNeeded);
2201 }
2202 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2203 {
2204 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2205 }
2206 RpcEndExcept;
2207
2208 if (dwError != ERROR_SUCCESS)
2209 {
2210 TRACE("RQueryServiceConfig2W() failed (Error %lu)\n", dwError);
2211 SetLastError(dwError);
2212 return FALSE;
2213 }
2214
2215 switch (dwInfoLevel)
2216 {
2217 case SERVICE_CONFIG_DESCRIPTION:
2218 {
2219 LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpBuffer;
2220
2221 if (lpPtr->lpDescription != NULL)
2222 lpPtr->lpDescription =
2223 (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpDescription);
2224 }
2225 break;
2226
2227 case SERVICE_CONFIG_FAILURE_ACTIONS:
2228 {
2229 LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer;
2230
2231 if (lpPtr->lpRebootMsg != NULL)
2232 lpPtr->lpRebootMsg =
2233 (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpRebootMsg);
2234
2235 if (lpPtr->lpCommand != NULL)
2236 lpPtr->lpCommand =
2237 (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpCommand);
2238
2239 if (lpPtr->lpsaActions != NULL)
2240 lpPtr->lpsaActions =
2241 (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
2242 }
2243 break;
2244
2245 default:
2246 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
2247 SetLastError(ERROR_INVALID_PARAMETER);
2248 return FALSE;
2249 }
2250
2251 TRACE("QueryServiceConfig2W() done\n");
2252
2253 return TRUE;
2254 }
2255
2256
2257 /**********************************************************************
2258 * QueryServiceLockStatusA
2259 *
2260 * @implemented
2261 */
2262 BOOL WINAPI
2263 QueryServiceLockStatusA(SC_HANDLE hSCManager,
2264 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
2265 DWORD cbBufSize,
2266 LPDWORD pcbBytesNeeded)
2267 {
2268 DWORD dwError;
2269
2270 TRACE("QueryServiceLockStatusA() called\n");
2271
2272 RpcTryExcept
2273 {
2274 /* Call to services.exe using RPC */
2275 dwError = RQueryServiceLockStatusA((SC_RPC_HANDLE)hSCManager,
2276 lpLockStatus,
2277 cbBufSize,
2278 pcbBytesNeeded);
2279 }
2280 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2281 {
2282 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2283 }
2284 RpcEndExcept;
2285
2286 if (dwError != ERROR_SUCCESS)
2287 {
2288 TRACE("RQueryServiceLockStatusA() failed (Error %lu)\n", dwError);
2289 SetLastError(dwError);
2290 return FALSE;
2291 }
2292
2293 if (lpLockStatus->lpLockOwner != NULL)
2294 {
2295 lpLockStatus->lpLockOwner =
2296 (LPSTR)((UINT_PTR)lpLockStatus + (UINT_PTR)lpLockStatus->lpLockOwner);
2297 }
2298
2299 TRACE("QueryServiceLockStatusA() done\n");
2300
2301 return TRUE;
2302 }
2303
2304
2305 /**********************************************************************
2306 * QueryServiceLockStatusW
2307 *
2308 * @implemented
2309 */
2310 BOOL WINAPI
2311 QueryServiceLockStatusW(SC_HANDLE hSCManager,
2312 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
2313 DWORD cbBufSize,
2314 LPDWORD pcbBytesNeeded)
2315 {
2316 DWORD dwError;
2317
2318 TRACE("QueryServiceLockStatusW() called\n");
2319
2320 RpcTryExcept
2321 {
2322 /* Call to services.exe using RPC */
2323 dwError = RQueryServiceLockStatusW((SC_RPC_HANDLE)hSCManager,
2324 lpLockStatus,
2325 cbBufSize,
2326 pcbBytesNeeded);
2327 }
2328 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2329 {
2330 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2331 }
2332 RpcEndExcept;
2333
2334 if (dwError != ERROR_SUCCESS)
2335 {
2336 TRACE("RQueryServiceLockStatusW() failed (Error %lu)\n", dwError);
2337 SetLastError(dwError);
2338 return FALSE;
2339 }
2340
2341 if (lpLockStatus->lpLockOwner != NULL)
2342 {
2343 lpLockStatus->lpLockOwner =
2344 (LPWSTR)((UINT_PTR)lpLockStatus + (UINT_PTR)lpLockStatus->lpLockOwner);
2345 }
2346
2347 TRACE("QueryServiceLockStatusW() done\n");
2348
2349 return TRUE;
2350 }
2351
2352
2353 /**********************************************************************
2354 * QueryServiceObjectSecurity
2355 *
2356 * @implemented
2357 */
2358 BOOL WINAPI
2359 QueryServiceObjectSecurity(SC_HANDLE hService,
2360 SECURITY_INFORMATION dwSecurityInformation,
2361 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2362 DWORD cbBufSize,
2363 LPDWORD pcbBytesNeeded)
2364 {
2365 DWORD dwError;
2366
2367 TRACE("QueryServiceObjectSecurity(%p, %lu, %p)\n",
2368 hService, dwSecurityInformation, lpSecurityDescriptor);
2369
2370 RpcTryExcept
2371 {
2372 /* Call to services.exe using RPC */
2373 dwError = RQueryServiceObjectSecurity((SC_RPC_HANDLE)hService,
2374 dwSecurityInformation,
2375 (LPBYTE)lpSecurityDescriptor,
2376 cbBufSize,
2377 pcbBytesNeeded);
2378 }
2379 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2380 {
2381 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2382 }
2383 RpcEndExcept;
2384
2385 if (dwError != ERROR_SUCCESS)
2386 {
2387 TRACE("QueryServiceObjectSecurity() failed (Error %lu)\n", dwError);
2388 SetLastError(dwError);
2389 return FALSE;
2390 }
2391
2392 return TRUE;
2393 }
2394
2395 /**********************************************************************
2396 * SetServiceObjectSecurity
2397 *
2398 * @implemented
2399 */
2400 BOOL WINAPI
2401 SetServiceObjectSecurity(SC_HANDLE hService,
2402 SECURITY_INFORMATION dwSecurityInformation,
2403 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2404 {
2405 PSECURITY_DESCRIPTOR SelfRelativeSD = NULL;
2406 ULONG Length;
2407 NTSTATUS Status;
2408 DWORD dwError;
2409
2410 Length = 0;
2411 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
2412 SelfRelativeSD,
2413 &Length);
2414 if (Status != STATUS_BUFFER_TOO_SMALL)
2415 {
2416 SetLastError(ERROR_INVALID_PARAMETER);
2417 return FALSE;
2418 }
2419
2420 SelfRelativeSD = HeapAlloc(GetProcessHeap(), 0, Length);
2421 if (SelfRelativeSD == NULL)
2422 {
2423 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2424 return FALSE;
2425 }
2426
2427 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
2428 SelfRelativeSD,
2429 &Length);
2430 if (!NT_SUCCESS(Status))
2431 {
2432 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
2433 SetLastError(RtlNtStatusToDosError(Status));
2434 return FALSE;
2435 }
2436
2437 RpcTryExcept
2438 {
2439 /* Call to services.exe using RPC */
2440 dwError = RSetServiceObjectSecurity((SC_RPC_HANDLE)hService,
2441 dwSecurityInformation,
2442 (LPBYTE)SelfRelativeSD,
2443 Length);
2444 }
2445 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2446 {
2447 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2448 }
2449 RpcEndExcept;
2450
2451 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
2452
2453 if (dwError != ERROR_SUCCESS)
2454 {
2455 TRACE("RServiceObjectSecurity() failed (Error %lu)\n", dwError);
2456 SetLastError(dwError);
2457 return FALSE;
2458 }
2459
2460 return TRUE;
2461 }
2462
2463
2464 /**********************************************************************
2465 * QueryServiceStatus
2466 *
2467 * @implemented
2468 */
2469 BOOL WINAPI
2470 QueryServiceStatus(SC_HANDLE hService,
2471 LPSERVICE_STATUS lpServiceStatus)
2472 {
2473 DWORD dwError;
2474
2475 TRACE("QueryServiceStatus(%p, %p)\n",
2476 hService, lpServiceStatus);
2477
2478 if (!hService)
2479 {
2480 SetLastError(ERROR_INVALID_HANDLE);
2481 return FALSE;
2482 }
2483
2484 RpcTryExcept
2485 {
2486 /* Call to services.exe using RPC */
2487 dwError = RQueryServiceStatus((SC_RPC_HANDLE)hService,
2488 lpServiceStatus);
2489 }
2490 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2491 {
2492 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2493 }
2494 RpcEndExcept;
2495
2496 if (dwError != ERROR_SUCCESS)
2497 {
2498 TRACE("RQueryServiceStatus() failed (Error %lu)\n", dwError);
2499 SetLastError(dwError);
2500 return FALSE;
2501 }
2502
2503 return TRUE;
2504 }
2505
2506
2507 /**********************************************************************
2508 * QueryServiceStatusEx
2509 *
2510 * @implemented
2511 */
2512 BOOL WINAPI
2513 QueryServiceStatusEx(SC_HANDLE hService,
2514 SC_STATUS_TYPE InfoLevel,
2515 LPBYTE lpBuffer,
2516 DWORD cbBufSize,
2517 LPDWORD pcbBytesNeeded)
2518 {
2519 DWORD dwError;
2520
2521 TRACE("QueryServiceStatusEx() called\n");
2522
2523 if (InfoLevel != SC_STATUS_PROCESS_INFO)
2524 {
2525 SetLastError(ERROR_INVALID_LEVEL);
2526 return FALSE;
2527 }
2528
2529 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
2530 {
2531 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
2532 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2533 return FALSE;
2534 }
2535
2536 RpcTryExcept
2537 {
2538 /* Call to services.exe using RPC */
2539 dwError = RQueryServiceStatusEx((SC_RPC_HANDLE)hService,
2540 InfoLevel,
2541 lpBuffer,
2542 cbBufSize,
2543 pcbBytesNeeded);
2544 }
2545 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2546 {
2547 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2548 }
2549 RpcEndExcept;
2550
2551 if (dwError != ERROR_SUCCESS)
2552 {
2553 TRACE("RQueryServiceStatusEx() failed (Error %lu)\n", dwError);
2554 SetLastError(dwError);
2555 return FALSE;
2556 }
2557
2558 return TRUE;
2559 }
2560
2561
2562 /**********************************************************************
2563 * StartServiceA
2564 *
2565 * @implemented
2566 */
2567 BOOL WINAPI
2568 StartServiceA(SC_HANDLE hService,
2569 DWORD dwNumServiceArgs,
2570 LPCSTR *lpServiceArgVectors)
2571 {
2572 DWORD dwError;
2573
2574 RpcTryExcept
2575 {
2576 dwError = RStartServiceA((SC_RPC_HANDLE)hService,
2577 dwNumServiceArgs,
2578 (LPSTRING_PTRSA)lpServiceArgVectors);
2579 }
2580 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2581 {
2582 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2583 }
2584 RpcEndExcept;
2585
2586 if (dwError != ERROR_SUCCESS)
2587 {
2588 ERR("RStartServiceA() failed (Error %lu)\n", dwError);
2589 SetLastError(dwError);
2590 return FALSE;
2591 }
2592
2593 return TRUE;
2594 }
2595
2596
2597 /**********************************************************************
2598 * StartServiceW
2599 *
2600 * @implemented
2601 */
2602 BOOL WINAPI
2603 StartServiceW(SC_HANDLE hService,
2604 DWORD dwNumServiceArgs,
2605 LPCWSTR *lpServiceArgVectors)
2606 {
2607 DWORD dwError;
2608
2609 RpcTryExcept
2610 {
2611 dwError = RStartServiceW((SC_RPC_HANDLE)hService,
2612 dwNumServiceArgs,
2613 (LPSTRING_PTRSW)lpServiceArgVectors);
2614 }
2615 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2616 {
2617 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2618 }
2619 RpcEndExcept;
2620
2621 if (dwError != ERROR_SUCCESS)
2622 {
2623 ERR("RStartServiceW() failed (Error %lu)\n", dwError);
2624 SetLastError(dwError);
2625 return FALSE;
2626 }
2627
2628 return TRUE;
2629 }
2630
2631
2632 /**********************************************************************
2633 * UnlockServiceDatabase
2634 *
2635 * @implemented
2636 */
2637 BOOL WINAPI
2638 UnlockServiceDatabase(SC_LOCK ScLock)
2639 {
2640 DWORD dwError;
2641
2642 TRACE("UnlockServiceDatabase(%x)\n", ScLock);
2643
2644 RpcTryExcept
2645 {
2646 /* Call to services.exe using RPC */
2647 dwError = RUnlockServiceDatabase((LPSC_RPC_LOCK)&ScLock);
2648 }
2649 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2650 {
2651 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2652 }
2653 RpcEndExcept;
2654
2655 if (dwError != ERROR_SUCCESS)
2656 {
2657 TRACE("RUnlockServiceDatabase() failed (Error %lu)\n", dwError);
2658 SetLastError(dwError);
2659 return FALSE;
2660 }
2661
2662 return TRUE;
2663 }
2664
2665
2666 /**********************************************************************
2667 * NotifyBootConfigStatus
2668 *
2669 * @implemented
2670 */
2671 BOOL WINAPI
2672 NotifyBootConfigStatus(BOOL BootAcceptable)
2673 {
2674 DWORD dwError;
2675
2676 TRACE("NotifyBootConfigStatus()\n");
2677
2678 RpcTryExcept
2679 {
2680 /* Call to services.exe using RPC */
2681 dwError = RNotifyBootConfigStatus(NULL,
2682 BootAcceptable);
2683 }
2684 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2685 {
2686 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2687 }
2688 RpcEndExcept;
2689
2690 if (dwError != ERROR_SUCCESS)
2691 {
2692 TRACE("NotifyBootConfigStatus() failed (Error %lu)\n", dwError);
2693 SetLastError(dwError);
2694 return FALSE;
2695 }
2696
2697 return TRUE;
2698 }
2699
2700 /* EOF */