92f71691cdc618e8a6d668c11ebc0a05b77ebd9c
[reactos.git] / reactos / dll / win32 / advapi32 / service / scm.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/advapi32/service/scm.c
5 * PURPOSE: Service control manager functions
6 * PROGRAMMER: Emanuele Aliberti
7 * Eric Kohl
8 * UPDATE HISTORY:
9 * 19990413 EA created
10 * 19990515 EA
11 */
12
13 /* INCLUDES ******************************************************************/
14
15 #include <advapi32.h>
16 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
17
18
19 /* FUNCTIONS *****************************************************************/
20
21 handle_t __RPC_USER
22 SVCCTL_HANDLEA_bind(SVCCTL_HANDLEA szMachineName)
23 {
24 handle_t hBinding = NULL;
25 UCHAR *pszStringBinding;
26 RPC_STATUS status;
27
28 TRACE("SVCCTL_HANDLEA_bind() called\n");
29
30 status = RpcStringBindingComposeA(NULL,
31 (UCHAR *)"ncacn_np",
32 (UCHAR *)szMachineName,
33 (UCHAR *)"\\pipe\\ntsvcs",
34 NULL,
35 (UCHAR **)&pszStringBinding);
36 if (status != RPC_S_OK)
37 {
38 ERR("RpcStringBindingCompose returned 0x%x\n", status);
39 return NULL;
40 }
41
42 /* Set the binding handle that will be used to bind to the server. */
43 status = RpcBindingFromStringBindingA(pszStringBinding,
44 &hBinding);
45 if (status != RPC_S_OK)
46 {
47 ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
48 }
49
50 status = RpcStringFreeA(&pszStringBinding);
51 if (status != RPC_S_OK)
52 {
53 ERR("RpcStringFree returned 0x%x\n", status);
54 }
55
56 return hBinding;
57 }
58
59
60 void __RPC_USER
61 SVCCTL_HANDLEA_unbind(SVCCTL_HANDLEA szMachineName,
62 handle_t hBinding)
63 {
64 RPC_STATUS status;
65
66 TRACE("SVCCTL_HANDLEA_unbind() called\n");
67
68 status = RpcBindingFree(&hBinding);
69 if (status != RPC_S_OK)
70 {
71 ERR("RpcBindingFree returned 0x%x\n", status);
72 }
73 }
74
75
76 handle_t __RPC_USER
77 SVCCTL_HANDLEW_bind(SVCCTL_HANDLEW szMachineName)
78 {
79 handle_t hBinding = NULL;
80 LPWSTR pszStringBinding;
81 RPC_STATUS status;
82
83 TRACE("SVCCTL_HANDLEW_bind() called\n");
84
85 status = RpcStringBindingComposeW(NULL,
86 L"ncacn_np",
87 szMachineName,
88 L"\\pipe\\ntsvcs",
89 NULL,
90 &pszStringBinding);
91 if (status != RPC_S_OK)
92 {
93 ERR("RpcStringBindingCompose returned 0x%x\n", status);
94 return NULL;
95 }
96
97 /* Set the binding handle that will be used to bind to the server. */
98 status = RpcBindingFromStringBindingW(pszStringBinding,
99 &hBinding);
100 if (status != RPC_S_OK)
101 {
102 ERR("RpcBindingFromStringBinding returned 0x%x\n", status);
103 }
104
105 status = RpcStringFreeW(&pszStringBinding);
106 if (status != RPC_S_OK)
107 {
108 ERR("RpcStringFree returned 0x%x\n", status);
109 }
110
111 return hBinding;
112 }
113
114
115 void __RPC_USER
116 SVCCTL_HANDLEW_unbind(SVCCTL_HANDLEW szMachineName,
117 handle_t hBinding)
118 {
119 RPC_STATUS status;
120
121 TRACE("SVCCTL_HANDLEW_unbind() called\n");
122
123 status = RpcBindingFree(&hBinding);
124 if (status != RPC_S_OK)
125 {
126 ERR("RpcBindingFree returned 0x%x\n", status);
127 }
128 }
129
130
131 DWORD
132 ScmRpcStatusToWinError(RPC_STATUS Status)
133 {
134 switch (Status)
135 {
136 case RPC_S_INVALID_BINDING:
137 case RPC_X_SS_IN_NULL_CONTEXT:
138 return ERROR_INVALID_HANDLE;
139
140 case RPC_X_ENUM_VALUE_OUT_OF_RANGE:
141 case RPC_X_BYTE_COUNT_TOO_SMALL:
142 return ERROR_INVALID_PARAMETER;
143
144 case RPC_X_NULL_REF_POINTER:
145 return ERROR_INVALID_ADDRESS;
146
147 default:
148 return (DWORD)Status;
149 }
150 }
151
152
153 /**********************************************************************
154 * ChangeServiceConfig2A
155 *
156 * @implemented
157 */
158 BOOL WINAPI
159 ChangeServiceConfig2A(SC_HANDLE hService,
160 DWORD dwInfoLevel,
161 LPVOID lpInfo)
162 {
163 SC_RPC_CONFIG_INFOA Info;
164 DWORD dwError;
165
166 TRACE("ChangeServiceConfig2A() called\n");
167
168 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 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 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2244 return FALSE;
2245 }
2246
2247 switch (dwInfoLevel)
2248 {
2249 case SERVICE_CONFIG_DESCRIPTION:
2250 {
2251 LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpTempBuffer;
2252
2253 if (lpPtr->lpDescription != NULL)
2254 lpPtr->lpDescription =
2255 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription);
2256 }
2257 break;
2258
2259 case SERVICE_CONFIG_FAILURE_ACTIONS:
2260 {
2261 LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpTempBuffer;
2262
2263 if (lpPtr->lpRebootMsg != NULL)
2264 lpPtr->lpRebootMsg =
2265 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg);
2266
2267 if (lpPtr->lpCommand != NULL)
2268 lpPtr->lpCommand =
2269 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand);
2270
2271 if (lpPtr->lpsaActions != NULL)
2272 lpPtr->lpsaActions =
2273 (LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions);
2274 }
2275 break;
2276 }
2277
2278 TRACE("QueryServiceConfig2W() done\n");
2279
2280 return TRUE;
2281 }
2282
2283
2284 /**********************************************************************
2285 * QueryServiceLockStatusA
2286 *
2287 * @implemented
2288 */
2289 BOOL WINAPI
2290 QueryServiceLockStatusA(SC_HANDLE hSCManager,
2291 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
2292 DWORD cbBufSize,
2293 LPDWORD pcbBytesNeeded)
2294 {
2295 QUERY_SERVICE_LOCK_STATUSA LockStatus;
2296 LPQUERY_SERVICE_LOCK_STATUSA lpStatusPtr;
2297 DWORD dwBufferSize;
2298 DWORD dwError;
2299
2300 TRACE("QueryServiceLockStatusA() called\n");
2301
2302 if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSA))
2303 {
2304 lpStatusPtr = &LockStatus;
2305 dwBufferSize = sizeof(QUERY_SERVICE_LOCK_STATUSA);
2306 }
2307 else
2308 {
2309 lpStatusPtr = lpLockStatus;
2310 dwBufferSize = cbBufSize;
2311 }
2312
2313 RpcTryExcept
2314 {
2315 /* Call to services.exe using RPC */
2316 dwError = RQueryServiceLockStatusA((SC_RPC_HANDLE)hSCManager,
2317 (LPBYTE)lpStatusPtr,
2318 dwBufferSize,
2319 pcbBytesNeeded);
2320 }
2321 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2322 {
2323 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2324 }
2325 RpcEndExcept;
2326
2327 if (dwError != ERROR_SUCCESS)
2328 {
2329 TRACE("RQueryServiceLockStatusA() failed (Error %lu)\n", dwError);
2330 SetLastError(dwError);
2331 return FALSE;
2332 }
2333
2334 if (lpStatusPtr->lpLockOwner != NULL)
2335 {
2336 lpStatusPtr->lpLockOwner =
2337 (LPSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner);
2338 }
2339
2340 TRACE("QueryServiceLockStatusA() done\n");
2341
2342 return TRUE;
2343 }
2344
2345
2346 /**********************************************************************
2347 * QueryServiceLockStatusW
2348 *
2349 * @implemented
2350 */
2351 BOOL WINAPI
2352 QueryServiceLockStatusW(SC_HANDLE hSCManager,
2353 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
2354 DWORD cbBufSize,
2355 LPDWORD pcbBytesNeeded)
2356 {
2357 QUERY_SERVICE_LOCK_STATUSW LockStatus;
2358 LPQUERY_SERVICE_LOCK_STATUSW lpStatusPtr;
2359 DWORD dwBufferSize;
2360 DWORD dwError;
2361
2362 TRACE("QueryServiceLockStatusW() called\n");
2363
2364 if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSW))
2365 {
2366 lpStatusPtr = &LockStatus;
2367 dwBufferSize = sizeof(QUERY_SERVICE_LOCK_STATUSW);
2368 }
2369 else
2370 {
2371 lpStatusPtr = lpLockStatus;
2372 dwBufferSize = cbBufSize;
2373 }
2374
2375 RpcTryExcept
2376 {
2377 /* Call to services.exe using RPC */
2378 dwError = RQueryServiceLockStatusW((SC_RPC_HANDLE)hSCManager,
2379 (LPBYTE)lpStatusPtr,
2380 dwBufferSize,
2381 pcbBytesNeeded);
2382 }
2383 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2384 {
2385 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2386 }
2387 RpcEndExcept;
2388
2389 if (dwError != ERROR_SUCCESS)
2390 {
2391 TRACE("RQueryServiceLockStatusW() failed (Error %lu)\n", dwError);
2392 SetLastError(dwError);
2393 return FALSE;
2394 }
2395
2396 if (lpStatusPtr->lpLockOwner != NULL)
2397 {
2398 lpStatusPtr->lpLockOwner =
2399 (LPWSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner);
2400 }
2401
2402 TRACE("QueryServiceLockStatusW() done\n");
2403
2404 return TRUE;
2405 }
2406
2407
2408 /**********************************************************************
2409 * QueryServiceObjectSecurity
2410 *
2411 * @implemented
2412 */
2413 BOOL WINAPI
2414 QueryServiceObjectSecurity(SC_HANDLE hService,
2415 SECURITY_INFORMATION dwSecurityInformation,
2416 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2417 DWORD cbBufSize,
2418 LPDWORD pcbBytesNeeded)
2419 {
2420 DWORD dwError;
2421
2422 TRACE("QueryServiceObjectSecurity(%p, %lu, %p)\n",
2423 hService, dwSecurityInformation, lpSecurityDescriptor);
2424
2425 RpcTryExcept
2426 {
2427 /* Call to services.exe using RPC */
2428 dwError = RQueryServiceObjectSecurity((SC_RPC_HANDLE)hService,
2429 dwSecurityInformation,
2430 (LPBYTE)lpSecurityDescriptor,
2431 cbBufSize,
2432 pcbBytesNeeded);
2433 }
2434 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2435 {
2436 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2437 }
2438 RpcEndExcept;
2439
2440 if (dwError != ERROR_SUCCESS)
2441 {
2442 TRACE("QueryServiceObjectSecurity() failed (Error %lu)\n", dwError);
2443 SetLastError(dwError);
2444 return FALSE;
2445 }
2446
2447 return TRUE;
2448 }
2449
2450 /**********************************************************************
2451 * SetServiceObjectSecurity
2452 *
2453 * @implemented
2454 */
2455 BOOL WINAPI
2456 SetServiceObjectSecurity(SC_HANDLE hService,
2457 SECURITY_INFORMATION dwSecurityInformation,
2458 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2459 {
2460 PSECURITY_DESCRIPTOR SelfRelativeSD = NULL;
2461 ULONG Length;
2462 NTSTATUS Status;
2463 DWORD dwError;
2464
2465 Length = 0;
2466 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
2467 SelfRelativeSD,
2468 &Length);
2469 if (Status != STATUS_BUFFER_TOO_SMALL)
2470 {
2471 SetLastError(ERROR_INVALID_PARAMETER);
2472 return FALSE;
2473 }
2474
2475 SelfRelativeSD = HeapAlloc(GetProcessHeap(), 0, Length);
2476 if (SelfRelativeSD == NULL)
2477 {
2478 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2479 return FALSE;
2480 }
2481
2482 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
2483 SelfRelativeSD,
2484 &Length);
2485 if (!NT_SUCCESS(Status))
2486 {
2487 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
2488 SetLastError(RtlNtStatusToDosError(Status));
2489 return FALSE;
2490 }
2491
2492 RpcTryExcept
2493 {
2494 /* Call to services.exe using RPC */
2495 dwError = RSetServiceObjectSecurity((SC_RPC_HANDLE)hService,
2496 dwSecurityInformation,
2497 (LPBYTE)SelfRelativeSD,
2498 Length);
2499 }
2500 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2501 {
2502 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2503 }
2504 RpcEndExcept;
2505
2506 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
2507
2508 if (dwError != ERROR_SUCCESS)
2509 {
2510 TRACE("RServiceObjectSecurity() failed (Error %lu)\n", dwError);
2511 SetLastError(dwError);
2512 return FALSE;
2513 }
2514
2515 return TRUE;
2516 }
2517
2518
2519 /**********************************************************************
2520 * QueryServiceStatus
2521 *
2522 * @implemented
2523 */
2524 BOOL WINAPI
2525 QueryServiceStatus(SC_HANDLE hService,
2526 LPSERVICE_STATUS lpServiceStatus)
2527 {
2528 DWORD dwError;
2529
2530 TRACE("QueryServiceStatus(%p, %p)\n",
2531 hService, lpServiceStatus);
2532
2533 if (!hService)
2534 {
2535 SetLastError(ERROR_INVALID_HANDLE);
2536 return FALSE;
2537 }
2538
2539 RpcTryExcept
2540 {
2541 /* Call to services.exe using RPC */
2542 dwError = RQueryServiceStatus((SC_RPC_HANDLE)hService,
2543 lpServiceStatus);
2544 }
2545 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2546 {
2547 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2548 }
2549 RpcEndExcept;
2550
2551 if (dwError != ERROR_SUCCESS)
2552 {
2553 TRACE("RQueryServiceStatus() failed (Error %lu)\n", dwError);
2554 SetLastError(dwError);
2555 return FALSE;
2556 }
2557
2558 return TRUE;
2559 }
2560
2561
2562 /**********************************************************************
2563 * QueryServiceStatusEx
2564 *
2565 * @implemented
2566 */
2567 BOOL WINAPI
2568 QueryServiceStatusEx(SC_HANDLE hService,
2569 SC_STATUS_TYPE InfoLevel,
2570 LPBYTE lpBuffer,
2571 DWORD cbBufSize,
2572 LPDWORD pcbBytesNeeded)
2573 {
2574 DWORD dwError;
2575
2576 TRACE("QueryServiceStatusEx() called\n");
2577
2578 if (InfoLevel != SC_STATUS_PROCESS_INFO)
2579 {
2580 SetLastError(ERROR_INVALID_LEVEL);
2581 return FALSE;
2582 }
2583
2584 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
2585 {
2586 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
2587 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2588 return FALSE;
2589 }
2590
2591 RpcTryExcept
2592 {
2593 /* Call to services.exe using RPC */
2594 dwError = RQueryServiceStatusEx((SC_RPC_HANDLE)hService,
2595 InfoLevel,
2596 lpBuffer,
2597 cbBufSize,
2598 pcbBytesNeeded);
2599 }
2600 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2601 {
2602 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2603 }
2604 RpcEndExcept;
2605
2606 if (dwError != ERROR_SUCCESS)
2607 {
2608 TRACE("RQueryServiceStatusEx() failed (Error %lu)\n", dwError);
2609 SetLastError(dwError);
2610 return FALSE;
2611 }
2612
2613 return TRUE;
2614 }
2615
2616
2617 /**********************************************************************
2618 * StartServiceA
2619 *
2620 * @implemented
2621 */
2622 BOOL WINAPI
2623 StartServiceA(SC_HANDLE hService,
2624 DWORD dwNumServiceArgs,
2625 LPCSTR *lpServiceArgVectors)
2626 {
2627 DWORD dwError;
2628
2629 RpcTryExcept
2630 {
2631 dwError = RStartServiceA((SC_RPC_HANDLE)hService,
2632 dwNumServiceArgs,
2633 (LPSTRING_PTRSA)lpServiceArgVectors);
2634 }
2635 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2636 {
2637 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2638 }
2639 RpcEndExcept;
2640
2641 if (dwError != ERROR_SUCCESS)
2642 {
2643 ERR("RStartServiceA() failed (Error %lu)\n", dwError);
2644 SetLastError(dwError);
2645 return FALSE;
2646 }
2647
2648 return TRUE;
2649 }
2650
2651
2652 /**********************************************************************
2653 * StartServiceW
2654 *
2655 * @implemented
2656 */
2657 BOOL WINAPI
2658 StartServiceW(SC_HANDLE hService,
2659 DWORD dwNumServiceArgs,
2660 LPCWSTR *lpServiceArgVectors)
2661 {
2662 DWORD dwError;
2663
2664 RpcTryExcept
2665 {
2666 dwError = RStartServiceW((SC_RPC_HANDLE)hService,
2667 dwNumServiceArgs,
2668 (LPSTRING_PTRSW)lpServiceArgVectors);
2669 }
2670 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2671 {
2672 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2673 }
2674 RpcEndExcept;
2675
2676 if (dwError != ERROR_SUCCESS)
2677 {
2678 ERR("RStartServiceW() failed (Error %lu)\n", dwError);
2679 SetLastError(dwError);
2680 return FALSE;
2681 }
2682
2683 return TRUE;
2684 }
2685
2686
2687 /**********************************************************************
2688 * UnlockServiceDatabase
2689 *
2690 * @implemented
2691 */
2692 BOOL WINAPI
2693 UnlockServiceDatabase(SC_LOCK ScLock)
2694 {
2695 DWORD dwError;
2696
2697 TRACE("UnlockServiceDatabase(%x)\n", ScLock);
2698
2699 RpcTryExcept
2700 {
2701 /* Call to services.exe using RPC */
2702 dwError = RUnlockServiceDatabase((LPSC_RPC_LOCK)&ScLock);
2703 }
2704 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2705 {
2706 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2707 }
2708 RpcEndExcept;
2709
2710 if (dwError != ERROR_SUCCESS)
2711 {
2712 TRACE("RUnlockServiceDatabase() failed (Error %lu)\n", dwError);
2713 SetLastError(dwError);
2714 return FALSE;
2715 }
2716
2717 return TRUE;
2718 }
2719
2720
2721 /**********************************************************************
2722 * NotifyBootConfigStatus
2723 *
2724 * @implemented
2725 */
2726 BOOL WINAPI
2727 NotifyBootConfigStatus(BOOL BootAcceptable)
2728 {
2729 DWORD dwError;
2730
2731 TRACE("NotifyBootConfigStatus()\n");
2732
2733 RpcTryExcept
2734 {
2735 /* Call to services.exe using RPC */
2736 dwError = RNotifyBootConfigStatus(NULL,
2737 BootAcceptable);
2738 }
2739 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2740 {
2741 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2742 }
2743 RpcEndExcept;
2744
2745 if (dwError != ERROR_SUCCESS)
2746 {
2747 TRACE("NotifyBootConfigStatus() failed (Error %lu)\n", dwError);
2748 SetLastError(dwError);
2749 return FALSE;
2750 }
2751
2752 return TRUE;
2753 }
2754
2755 /* EOF */