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