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