[REACTOS]
[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,
1677 FALSE,
1678 SCM_START_EVENT);
1679 if (hEvent == NULL)
1680 {
1681 if (GetLastError() != ERROR_FILE_NOT_FOUND)
1682 return;
1683
1684 /* Try to create a new event */
1685 hEvent = CreateEventW(NULL,
1686 TRUE,
1687 FALSE,
1688 SCM_START_EVENT);
1689 if (hEvent == NULL)
1690 {
1691 /* Try to open the existing event again */
1692 hEvent = OpenEventW(SYNCHRONIZE,
1693 FALSE,
1694 SCM_START_EVENT);
1695 if (hEvent == NULL)
1696 return;
1697 }
1698 }
1699
1700 /* Wait for 3 minutes */
1701 WaitForSingleObject(hEvent, 180000);
1702 CloseHandle(hEvent);
1703
1704 TRACE("ScmWaitForSCManager() done\n");
1705 }
1706
1707
1708 /**********************************************************************
1709 * OpenSCManagerA
1710 *
1711 * @implemented
1712 */
1713 SC_HANDLE WINAPI
1714 OpenSCManagerA(LPCSTR lpMachineName,
1715 LPCSTR lpDatabaseName,
1716 DWORD dwDesiredAccess)
1717 {
1718 SC_HANDLE hScm = NULL;
1719 DWORD dwError;
1720
1721 TRACE("OpenSCManagerA(%s, %s, %lx)\n",
1722 lpMachineName, lpDatabaseName, dwDesiredAccess);
1723
1724 WaitForSCManager();
1725
1726 RpcTryExcept
1727 {
1728 /* Call to services.exe using RPC */
1729 dwError = ROpenSCManagerA((LPSTR)lpMachineName,
1730 (LPSTR)lpDatabaseName,
1731 dwDesiredAccess,
1732 (SC_RPC_HANDLE *)&hScm);
1733 }
1734 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1735 {
1736 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1737 }
1738 RpcEndExcept;
1739
1740 if (dwError != ERROR_SUCCESS)
1741 {
1742 TRACE("ROpenSCManagerA() failed (Error %lu)\n", dwError);
1743 SetLastError(dwError);
1744 return NULL;
1745 }
1746
1747 TRACE("hScm = %p\n", hScm);
1748
1749 return hScm;
1750 }
1751
1752
1753 /**********************************************************************
1754 * OpenSCManagerW
1755 *
1756 * @implemented
1757 */
1758 SC_HANDLE WINAPI
1759 OpenSCManagerW(LPCWSTR lpMachineName,
1760 LPCWSTR lpDatabaseName,
1761 DWORD dwDesiredAccess)
1762 {
1763 SC_HANDLE hScm = NULL;
1764 DWORD dwError;
1765
1766 TRACE("OpenSCManagerW(%S, %S, %lx)\n",
1767 lpMachineName, lpDatabaseName, dwDesiredAccess);
1768
1769 WaitForSCManager();
1770
1771 RpcTryExcept
1772 {
1773 /* Call to services.exe using RPC */
1774 dwError = ROpenSCManagerW((LPWSTR)lpMachineName,
1775 (LPWSTR)lpDatabaseName,
1776 dwDesiredAccess,
1777 (SC_RPC_HANDLE *)&hScm);
1778 }
1779 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1780 {
1781 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1782 }
1783 RpcEndExcept;
1784
1785 if (dwError != ERROR_SUCCESS)
1786 {
1787 TRACE("ROpenSCManagerW() failed (Error %lu)\n", dwError);
1788 SetLastError(dwError);
1789 return NULL;
1790 }
1791
1792 TRACE("hScm = %p\n", hScm);
1793
1794 return hScm;
1795 }
1796
1797
1798 /**********************************************************************
1799 * OpenServiceA
1800 *
1801 * @implemented
1802 */
1803 SC_HANDLE WINAPI
1804 OpenServiceA(SC_HANDLE hSCManager,
1805 LPCSTR lpServiceName,
1806 DWORD dwDesiredAccess)
1807 {
1808 SC_HANDLE hService = NULL;
1809 DWORD dwError;
1810
1811 TRACE("OpenServiceA(%p, %s, %lx)\n",
1812 hSCManager, lpServiceName, dwDesiredAccess);
1813
1814 if (!hSCManager)
1815 {
1816 SetLastError(ERROR_INVALID_HANDLE);
1817 return NULL;
1818 }
1819
1820 RpcTryExcept
1821 {
1822 /* Call to services.exe using RPC */
1823 dwError = ROpenServiceA((SC_RPC_HANDLE)hSCManager,
1824 (LPSTR)lpServiceName,
1825 dwDesiredAccess,
1826 (SC_RPC_HANDLE *)&hService);
1827 }
1828 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1829 {
1830 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1831 }
1832 RpcEndExcept;
1833
1834 if (dwError != ERROR_SUCCESS)
1835 {
1836 TRACE("ROpenServiceA() failed (Error %lu)\n", dwError);
1837 SetLastError(dwError);
1838 return NULL;
1839 }
1840
1841 TRACE("hService = %p\n", hService);
1842
1843 return hService;
1844 }
1845
1846
1847 /**********************************************************************
1848 * OpenServiceW
1849 *
1850 * @implemented
1851 */
1852 SC_HANDLE WINAPI
1853 OpenServiceW(SC_HANDLE hSCManager,
1854 LPCWSTR lpServiceName,
1855 DWORD dwDesiredAccess)
1856 {
1857 SC_HANDLE hService = NULL;
1858 DWORD dwError;
1859
1860 TRACE("OpenServiceW(%p, %S, %lx)\n",
1861 hSCManager, lpServiceName, dwDesiredAccess);
1862
1863 if (!hSCManager)
1864 {
1865 SetLastError(ERROR_INVALID_HANDLE);
1866 return NULL;
1867 }
1868
1869 RpcTryExcept
1870 {
1871 /* Call to services.exe using RPC */
1872 dwError = ROpenServiceW((SC_RPC_HANDLE)hSCManager,
1873 (LPWSTR)lpServiceName,
1874 dwDesiredAccess,
1875 (SC_RPC_HANDLE *)&hService);
1876 }
1877 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1878 {
1879 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1880 }
1881 RpcEndExcept;
1882
1883 if (dwError != ERROR_SUCCESS)
1884 {
1885 TRACE("ROpenServiceW() failed (Error %lu)\n", dwError);
1886 SetLastError(dwError);
1887 return NULL;
1888 }
1889
1890 TRACE("hService = %p\n", hService);
1891
1892 return hService;
1893 }
1894
1895
1896 /**********************************************************************
1897 * QueryServiceConfigA
1898 *
1899 * @implemented
1900 */
1901 BOOL WINAPI
1902 QueryServiceConfigA(SC_HANDLE hService,
1903 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
1904 DWORD cbBufSize,
1905 LPDWORD pcbBytesNeeded)
1906 {
1907 QUERY_SERVICE_CONFIGA ServiceConfig;
1908 LPQUERY_SERVICE_CONFIGA lpConfigPtr;
1909 DWORD dwBufferSize;
1910 DWORD dwError;
1911
1912 TRACE("QueryServiceConfigA(%p, %p, %lu, %p)\n",
1913 hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
1914
1915 if (lpServiceConfig == NULL ||
1916 cbBufSize < sizeof(QUERY_SERVICE_CONFIGA))
1917 {
1918 lpConfigPtr = &ServiceConfig;
1919 dwBufferSize = sizeof(QUERY_SERVICE_CONFIGA);
1920 }
1921 else
1922 {
1923 lpConfigPtr = lpServiceConfig;
1924 dwBufferSize = cbBufSize;
1925 }
1926
1927 RpcTryExcept
1928 {
1929 /* Call to services.exe using RPC */
1930 dwError = RQueryServiceConfigA((SC_RPC_HANDLE)hService,
1931 (LPBYTE)lpConfigPtr,
1932 dwBufferSize,
1933 pcbBytesNeeded);
1934 }
1935 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
1936 {
1937 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
1938 }
1939 RpcEndExcept;
1940
1941 if (dwError != ERROR_SUCCESS)
1942 {
1943 TRACE("RQueryServiceConfigA() failed (Error %lu)\n", dwError);
1944 SetLastError(dwError);
1945 return FALSE;
1946 }
1947
1948 /* Adjust the pointers */
1949 if (lpConfigPtr->lpBinaryPathName)
1950 lpConfigPtr->lpBinaryPathName =
1951 (LPSTR)((ULONG_PTR)lpConfigPtr +
1952 (ULONG_PTR)lpConfigPtr->lpBinaryPathName);
1953
1954 if (lpConfigPtr->lpLoadOrderGroup)
1955 lpConfigPtr->lpLoadOrderGroup =
1956 (LPSTR)((ULONG_PTR)lpConfigPtr +
1957 (ULONG_PTR)lpConfigPtr->lpLoadOrderGroup);
1958
1959 if (lpConfigPtr->lpDependencies)
1960 lpConfigPtr->lpDependencies =
1961 (LPSTR)((ULONG_PTR)lpConfigPtr +
1962 (ULONG_PTR)lpConfigPtr->lpDependencies);
1963
1964 if (lpConfigPtr->lpServiceStartName)
1965 lpConfigPtr->lpServiceStartName =
1966 (LPSTR)((ULONG_PTR)lpConfigPtr +
1967 (ULONG_PTR)lpConfigPtr->lpServiceStartName);
1968
1969 if (lpConfigPtr->lpDisplayName)
1970 lpConfigPtr->lpDisplayName =
1971 (LPSTR)((ULONG_PTR)lpConfigPtr +
1972 (ULONG_PTR)lpConfigPtr->lpDisplayName);
1973
1974 TRACE("QueryServiceConfigA() done\n");
1975
1976 return TRUE;
1977 }
1978
1979
1980 /**********************************************************************
1981 * QueryServiceConfigW
1982 *
1983 * @implemented
1984 */
1985 BOOL WINAPI
1986 QueryServiceConfigW(SC_HANDLE hService,
1987 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1988 DWORD cbBufSize,
1989 LPDWORD pcbBytesNeeded)
1990 {
1991 QUERY_SERVICE_CONFIGW ServiceConfig;
1992 LPQUERY_SERVICE_CONFIGW lpConfigPtr;
1993 DWORD dwBufferSize;
1994 DWORD dwError;
1995
1996 TRACE("QueryServiceConfigW(%p, %p, %lu, %p)\n",
1997 hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
1998
1999 if (lpServiceConfig == NULL ||
2000 cbBufSize < sizeof(QUERY_SERVICE_CONFIGW))
2001 {
2002 lpConfigPtr = &ServiceConfig;
2003 dwBufferSize = sizeof(QUERY_SERVICE_CONFIGW);
2004 }
2005 else
2006 {
2007 lpConfigPtr = lpServiceConfig;
2008 dwBufferSize = cbBufSize;
2009 }
2010
2011 RpcTryExcept
2012 {
2013 /* Call to services.exe using RPC */
2014 dwError = RQueryServiceConfigW((SC_RPC_HANDLE)hService,
2015 (LPBYTE)lpConfigPtr,
2016 dwBufferSize,
2017 pcbBytesNeeded);
2018 }
2019 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2020 {
2021 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2022 }
2023 RpcEndExcept;
2024
2025 if (dwError != ERROR_SUCCESS)
2026 {
2027 TRACE("RQueryServiceConfigW() failed (Error %lu)\n", dwError);
2028 SetLastError(dwError);
2029 return FALSE;
2030 }
2031
2032 /* Adjust the pointers */
2033 if (lpConfigPtr->lpBinaryPathName)
2034 lpConfigPtr->lpBinaryPathName =
2035 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2036 (ULONG_PTR)lpConfigPtr->lpBinaryPathName);
2037
2038 if (lpConfigPtr->lpLoadOrderGroup)
2039 lpConfigPtr->lpLoadOrderGroup =
2040 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2041 (ULONG_PTR)lpConfigPtr->lpLoadOrderGroup);
2042
2043 if (lpConfigPtr->lpDependencies)
2044 lpConfigPtr->lpDependencies =
2045 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2046 (ULONG_PTR)lpConfigPtr->lpDependencies);
2047
2048 if (lpConfigPtr->lpServiceStartName)
2049 lpConfigPtr->lpServiceStartName =
2050 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2051 (ULONG_PTR)lpConfigPtr->lpServiceStartName);
2052
2053 if (lpConfigPtr->lpDisplayName)
2054 lpConfigPtr->lpDisplayName =
2055 (LPWSTR)((ULONG_PTR)lpConfigPtr +
2056 (ULONG_PTR)lpConfigPtr->lpDisplayName);
2057
2058 TRACE("QueryServiceConfigW() done\n");
2059
2060 return TRUE;
2061 }
2062
2063
2064 /**********************************************************************
2065 * QueryServiceConfig2A
2066 *
2067 * @implemented
2068 */
2069 BOOL WINAPI
2070 QueryServiceConfig2A(SC_HANDLE hService,
2071 DWORD dwInfoLevel,
2072 LPBYTE lpBuffer,
2073 DWORD cbBufSize,
2074 LPDWORD pcbBytesNeeded)
2075 {
2076 SERVICE_DESCRIPTIONA ServiceDescription;
2077 SERVICE_FAILURE_ACTIONSA ServiceFailureActions;
2078 LPBYTE lpTempBuffer;
2079 BOOL bUseTempBuffer = FALSE;
2080 DWORD dwBufferSize;
2081 DWORD dwError;
2082
2083 TRACE("QueryServiceConfig2A(hService %p, dwInfoLevel %lu, lpBuffer %p, cbBufSize %lu, pcbBytesNeeded %p)\n",
2084 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
2085
2086 lpTempBuffer = lpBuffer;
2087 dwBufferSize = cbBufSize;
2088
2089 switch (dwInfoLevel)
2090 {
2091 case SERVICE_CONFIG_DESCRIPTION:
2092 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_DESCRIPTIONA)))
2093 {
2094 lpTempBuffer = (LPBYTE)&ServiceDescription;
2095 dwBufferSize = sizeof(SERVICE_DESCRIPTIONA);
2096 bUseTempBuffer = TRUE;
2097 }
2098 break;
2099
2100 case SERVICE_CONFIG_FAILURE_ACTIONS:
2101 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSA)))
2102 {
2103 lpTempBuffer = (LPBYTE)&ServiceFailureActions;
2104 dwBufferSize = sizeof(SERVICE_FAILURE_ACTIONSA);
2105 bUseTempBuffer = TRUE;
2106 }
2107 break;
2108
2109 default:
2110 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
2111 SetLastError(ERROR_INVALID_LEVEL);
2112 return FALSE;
2113 }
2114
2115 RpcTryExcept
2116 {
2117 /* Call to services.exe using RPC */
2118 dwError = RQueryServiceConfig2A((SC_RPC_HANDLE)hService,
2119 dwInfoLevel,
2120 lpTempBuffer,
2121 dwBufferSize,
2122 pcbBytesNeeded);
2123 }
2124 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2125 {
2126 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2127 }
2128 RpcEndExcept;
2129
2130 if (dwError != ERROR_SUCCESS)
2131 {
2132 TRACE("RQueryServiceConfig2A() failed (Error %lu)\n", dwError);
2133 SetLastError(dwError);
2134 return FALSE;
2135 }
2136
2137 if (bUseTempBuffer == TRUE)
2138 {
2139 TRACE("RQueryServiceConfig2A() returns ERROR_INSUFFICIENT_BUFFER\n");
2140 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2141 return FALSE;
2142 }
2143
2144 switch (dwInfoLevel)
2145 {
2146 case SERVICE_CONFIG_DESCRIPTION:
2147 {
2148 LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpTempBuffer;
2149
2150 if (lpPtr->lpDescription != NULL)
2151 lpPtr->lpDescription =
2152 (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription);
2153 }
2154 break;
2155
2156 case SERVICE_CONFIG_FAILURE_ACTIONS:
2157 {
2158 LPSERVICE_FAILURE_ACTIONSA lpPtr = (LPSERVICE_FAILURE_ACTIONSA)lpTempBuffer;
2159
2160 if (lpPtr->lpRebootMsg != NULL)
2161 lpPtr->lpRebootMsg =
2162 (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg);
2163
2164 if (lpPtr->lpCommand != NULL)
2165 lpPtr->lpCommand =
2166 (LPSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand);
2167
2168 if (lpPtr->lpsaActions != NULL)
2169 lpPtr->lpsaActions =
2170 (LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions);
2171 }
2172 break;
2173 }
2174
2175 TRACE("QueryServiceConfig2A() done\n");
2176
2177 return TRUE;
2178 }
2179
2180
2181 /**********************************************************************
2182 * QueryServiceConfig2W
2183 *
2184 * @implemented
2185 */
2186 BOOL WINAPI
2187 QueryServiceConfig2W(SC_HANDLE hService,
2188 DWORD dwInfoLevel,
2189 LPBYTE lpBuffer,
2190 DWORD cbBufSize,
2191 LPDWORD pcbBytesNeeded)
2192 {
2193 SERVICE_DESCRIPTIONW ServiceDescription;
2194 SERVICE_FAILURE_ACTIONSW ServiceFailureActions;
2195 LPBYTE lpTempBuffer;
2196 BOOL bUseTempBuffer = FALSE;
2197 DWORD dwBufferSize;
2198 DWORD dwError;
2199
2200 TRACE("QueryServiceConfig2W(%p, %lu, %p, %lu, %p)\n",
2201 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
2202
2203 lpTempBuffer = lpBuffer;
2204 dwBufferSize = cbBufSize;
2205
2206 switch (dwInfoLevel)
2207 {
2208 case SERVICE_CONFIG_DESCRIPTION:
2209 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_DESCRIPTIONW)))
2210 {
2211 lpTempBuffer = (LPBYTE)&ServiceDescription;
2212 dwBufferSize = sizeof(SERVICE_DESCRIPTIONW);
2213 bUseTempBuffer = TRUE;
2214 }
2215 break;
2216
2217 case SERVICE_CONFIG_FAILURE_ACTIONS:
2218 if ((lpBuffer == NULL) || (cbBufSize < sizeof(SERVICE_FAILURE_ACTIONSW)))
2219 {
2220 lpTempBuffer = (LPBYTE)&ServiceFailureActions;
2221 dwBufferSize = sizeof(SERVICE_FAILURE_ACTIONSW);
2222 bUseTempBuffer = TRUE;
2223 }
2224 break;
2225
2226 default:
2227 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
2228 SetLastError(ERROR_INVALID_LEVEL);
2229 return FALSE;
2230 }
2231
2232 RpcTryExcept
2233 {
2234 /* Call to services.exe using RPC */
2235 dwError = RQueryServiceConfig2W((SC_RPC_HANDLE)hService,
2236 dwInfoLevel,
2237 lpTempBuffer,
2238 dwBufferSize,
2239 pcbBytesNeeded);
2240 }
2241 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2242 {
2243 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2244 }
2245 RpcEndExcept;
2246
2247 if (dwError != ERROR_SUCCESS)
2248 {
2249 TRACE("RQueryServiceConfig2W() failed (Error %lu)\n", dwError);
2250 SetLastError(dwError);
2251 return FALSE;
2252 }
2253
2254 if (bUseTempBuffer == TRUE)
2255 {
2256 TRACE("RQueryServiceConfig2W() returns ERROR_INSUFFICIENT_BUFFER\n");
2257 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2258 return FALSE;
2259 }
2260
2261 switch (dwInfoLevel)
2262 {
2263 case SERVICE_CONFIG_DESCRIPTION:
2264 {
2265 LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpTempBuffer;
2266
2267 if (lpPtr->lpDescription != NULL)
2268 lpPtr->lpDescription =
2269 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpDescription);
2270 }
2271 break;
2272
2273 case SERVICE_CONFIG_FAILURE_ACTIONS:
2274 {
2275 LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpTempBuffer;
2276
2277 if (lpPtr->lpRebootMsg != NULL)
2278 lpPtr->lpRebootMsg =
2279 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpRebootMsg);
2280
2281 if (lpPtr->lpCommand != NULL)
2282 lpPtr->lpCommand =
2283 (LPWSTR)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpCommand);
2284
2285 if (lpPtr->lpsaActions != NULL)
2286 lpPtr->lpsaActions =
2287 (LPSC_ACTION)((ULONG_PTR)lpPtr + (ULONG_PTR)lpPtr->lpsaActions);
2288 }
2289 break;
2290 }
2291
2292 TRACE("QueryServiceConfig2W() done\n");
2293
2294 return TRUE;
2295 }
2296
2297
2298 /**********************************************************************
2299 * QueryServiceLockStatusA
2300 *
2301 * @implemented
2302 */
2303 BOOL WINAPI
2304 QueryServiceLockStatusA(SC_HANDLE hSCManager,
2305 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
2306 DWORD cbBufSize,
2307 LPDWORD pcbBytesNeeded)
2308 {
2309 QUERY_SERVICE_LOCK_STATUSA LockStatus;
2310 LPQUERY_SERVICE_LOCK_STATUSA lpStatusPtr;
2311 DWORD dwBufferSize;
2312 DWORD dwError;
2313
2314 TRACE("QueryServiceLockStatusA() called\n");
2315
2316 if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSA))
2317 {
2318 lpStatusPtr = &LockStatus;
2319 dwBufferSize = sizeof(QUERY_SERVICE_LOCK_STATUSA);
2320 }
2321 else
2322 {
2323 lpStatusPtr = lpLockStatus;
2324 dwBufferSize = cbBufSize;
2325 }
2326
2327 RpcTryExcept
2328 {
2329 /* Call to services.exe using RPC */
2330 dwError = RQueryServiceLockStatusA((SC_RPC_HANDLE)hSCManager,
2331 (LPBYTE)lpStatusPtr,
2332 dwBufferSize,
2333 pcbBytesNeeded);
2334 }
2335 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2336 {
2337 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2338 }
2339 RpcEndExcept;
2340
2341 if (dwError != ERROR_SUCCESS)
2342 {
2343 TRACE("RQueryServiceLockStatusA() failed (Error %lu)\n", dwError);
2344 SetLastError(dwError);
2345 return FALSE;
2346 }
2347
2348 if (lpStatusPtr->lpLockOwner != NULL)
2349 {
2350 lpStatusPtr->lpLockOwner =
2351 (LPSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner);
2352 }
2353
2354 TRACE("QueryServiceLockStatusA() done\n");
2355
2356 return TRUE;
2357 }
2358
2359
2360 /**********************************************************************
2361 * QueryServiceLockStatusW
2362 *
2363 * @implemented
2364 */
2365 BOOL WINAPI
2366 QueryServiceLockStatusW(SC_HANDLE hSCManager,
2367 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
2368 DWORD cbBufSize,
2369 LPDWORD pcbBytesNeeded)
2370 {
2371 QUERY_SERVICE_LOCK_STATUSW LockStatus;
2372 LPQUERY_SERVICE_LOCK_STATUSW lpStatusPtr;
2373 DWORD dwBufferSize;
2374 DWORD dwError;
2375
2376 TRACE("QueryServiceLockStatusW() called\n");
2377
2378 if (lpLockStatus == NULL || cbBufSize < sizeof(QUERY_SERVICE_LOCK_STATUSW))
2379 {
2380 lpStatusPtr = &LockStatus;
2381 dwBufferSize = sizeof(QUERY_SERVICE_LOCK_STATUSW);
2382 }
2383 else
2384 {
2385 lpStatusPtr = lpLockStatus;
2386 dwBufferSize = cbBufSize;
2387 }
2388
2389 RpcTryExcept
2390 {
2391 /* Call to services.exe using RPC */
2392 dwError = RQueryServiceLockStatusW((SC_RPC_HANDLE)hSCManager,
2393 (LPBYTE)lpStatusPtr,
2394 dwBufferSize,
2395 pcbBytesNeeded);
2396 }
2397 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2398 {
2399 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2400 }
2401 RpcEndExcept;
2402
2403 if (dwError != ERROR_SUCCESS)
2404 {
2405 TRACE("RQueryServiceLockStatusW() failed (Error %lu)\n", dwError);
2406 SetLastError(dwError);
2407 return FALSE;
2408 }
2409
2410 if (lpStatusPtr->lpLockOwner != NULL)
2411 {
2412 lpStatusPtr->lpLockOwner =
2413 (LPWSTR)((ULONG_PTR)lpStatusPtr + (ULONG_PTR)lpStatusPtr->lpLockOwner);
2414 }
2415
2416 TRACE("QueryServiceLockStatusW() done\n");
2417
2418 return TRUE;
2419 }
2420
2421
2422 /**********************************************************************
2423 * QueryServiceObjectSecurity
2424 *
2425 * @implemented
2426 */
2427 BOOL WINAPI
2428 QueryServiceObjectSecurity(SC_HANDLE hService,
2429 SECURITY_INFORMATION dwSecurityInformation,
2430 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
2431 DWORD cbBufSize,
2432 LPDWORD pcbBytesNeeded)
2433 {
2434 DWORD dwError;
2435
2436 TRACE("QueryServiceObjectSecurity(%p, %lu, %p)\n",
2437 hService, dwSecurityInformation, lpSecurityDescriptor);
2438
2439 RpcTryExcept
2440 {
2441 /* Call to services.exe using RPC */
2442 dwError = RQueryServiceObjectSecurity((SC_RPC_HANDLE)hService,
2443 dwSecurityInformation,
2444 (LPBYTE)lpSecurityDescriptor,
2445 cbBufSize,
2446 pcbBytesNeeded);
2447 }
2448 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2449 {
2450 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2451 }
2452 RpcEndExcept;
2453
2454 if (dwError != ERROR_SUCCESS)
2455 {
2456 TRACE("QueryServiceObjectSecurity() failed (Error %lu)\n", dwError);
2457 SetLastError(dwError);
2458 return FALSE;
2459 }
2460
2461 return TRUE;
2462 }
2463
2464 /**********************************************************************
2465 * SetServiceObjectSecurity
2466 *
2467 * @implemented
2468 */
2469 BOOL WINAPI
2470 SetServiceObjectSecurity(SC_HANDLE hService,
2471 SECURITY_INFORMATION dwSecurityInformation,
2472 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
2473 {
2474 PSECURITY_DESCRIPTOR SelfRelativeSD = NULL;
2475 ULONG Length;
2476 NTSTATUS Status;
2477 DWORD dwError;
2478
2479 Length = 0;
2480 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
2481 SelfRelativeSD,
2482 &Length);
2483 if (Status != STATUS_BUFFER_TOO_SMALL)
2484 {
2485 SetLastError(ERROR_INVALID_PARAMETER);
2486 return FALSE;
2487 }
2488
2489 SelfRelativeSD = HeapAlloc(GetProcessHeap(), 0, Length);
2490 if (SelfRelativeSD == NULL)
2491 {
2492 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2493 return FALSE;
2494 }
2495
2496 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
2497 SelfRelativeSD,
2498 &Length);
2499 if (!NT_SUCCESS(Status))
2500 {
2501 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
2502 SetLastError(RtlNtStatusToDosError(Status));
2503 return FALSE;
2504 }
2505
2506 RpcTryExcept
2507 {
2508 /* Call to services.exe using RPC */
2509 dwError = RSetServiceObjectSecurity((SC_RPC_HANDLE)hService,
2510 dwSecurityInformation,
2511 (LPBYTE)SelfRelativeSD,
2512 Length);
2513 }
2514 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2515 {
2516 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2517 }
2518 RpcEndExcept;
2519
2520 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
2521
2522 if (dwError != ERROR_SUCCESS)
2523 {
2524 TRACE("RServiceObjectSecurity() failed (Error %lu)\n", dwError);
2525 SetLastError(dwError);
2526 return FALSE;
2527 }
2528
2529 return TRUE;
2530 }
2531
2532
2533 /**********************************************************************
2534 * QueryServiceStatus
2535 *
2536 * @implemented
2537 */
2538 BOOL WINAPI
2539 QueryServiceStatus(SC_HANDLE hService,
2540 LPSERVICE_STATUS lpServiceStatus)
2541 {
2542 DWORD dwError;
2543
2544 TRACE("QueryServiceStatus(%p, %p)\n",
2545 hService, lpServiceStatus);
2546
2547 if (!hService)
2548 {
2549 SetLastError(ERROR_INVALID_HANDLE);
2550 return FALSE;
2551 }
2552
2553 RpcTryExcept
2554 {
2555 /* Call to services.exe using RPC */
2556 dwError = RQueryServiceStatus((SC_RPC_HANDLE)hService,
2557 lpServiceStatus);
2558 }
2559 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2560 {
2561 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2562 }
2563 RpcEndExcept;
2564
2565 if (dwError != ERROR_SUCCESS)
2566 {
2567 TRACE("RQueryServiceStatus() failed (Error %lu)\n", dwError);
2568 SetLastError(dwError);
2569 return FALSE;
2570 }
2571
2572 return TRUE;
2573 }
2574
2575
2576 /**********************************************************************
2577 * QueryServiceStatusEx
2578 *
2579 * @implemented
2580 */
2581 BOOL WINAPI
2582 QueryServiceStatusEx(SC_HANDLE hService,
2583 SC_STATUS_TYPE InfoLevel,
2584 LPBYTE lpBuffer,
2585 DWORD cbBufSize,
2586 LPDWORD pcbBytesNeeded)
2587 {
2588 DWORD dwError;
2589
2590 TRACE("QueryServiceStatusEx() called\n");
2591
2592 if (InfoLevel != SC_STATUS_PROCESS_INFO)
2593 {
2594 SetLastError(ERROR_INVALID_LEVEL);
2595 return FALSE;
2596 }
2597
2598 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
2599 {
2600 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
2601 SetLastError(ERROR_INSUFFICIENT_BUFFER);
2602 return FALSE;
2603 }
2604
2605 RpcTryExcept
2606 {
2607 /* Call to services.exe using RPC */
2608 dwError = RQueryServiceStatusEx((SC_RPC_HANDLE)hService,
2609 InfoLevel,
2610 lpBuffer,
2611 cbBufSize,
2612 pcbBytesNeeded);
2613 }
2614 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2615 {
2616 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2617 }
2618 RpcEndExcept;
2619
2620 if (dwError != ERROR_SUCCESS)
2621 {
2622 TRACE("RQueryServiceStatusEx() failed (Error %lu)\n", dwError);
2623 SetLastError(dwError);
2624 return FALSE;
2625 }
2626
2627 return TRUE;
2628 }
2629
2630
2631 /**********************************************************************
2632 * StartServiceA
2633 *
2634 * @implemented
2635 */
2636 BOOL WINAPI
2637 StartServiceA(SC_HANDLE hService,
2638 DWORD dwNumServiceArgs,
2639 LPCSTR *lpServiceArgVectors)
2640 {
2641 DWORD dwError;
2642
2643 RpcTryExcept
2644 {
2645 dwError = RStartServiceA((SC_RPC_HANDLE)hService,
2646 dwNumServiceArgs,
2647 (LPSTRING_PTRSA)lpServiceArgVectors);
2648 }
2649 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2650 {
2651 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2652 }
2653 RpcEndExcept;
2654
2655 if (dwError != ERROR_SUCCESS)
2656 {
2657 ERR("RStartServiceA() failed (Error %lu)\n", dwError);
2658 SetLastError(dwError);
2659 return FALSE;
2660 }
2661
2662 return TRUE;
2663 }
2664
2665
2666 /**********************************************************************
2667 * StartServiceW
2668 *
2669 * @implemented
2670 */
2671 BOOL WINAPI
2672 StartServiceW(SC_HANDLE hService,
2673 DWORD dwNumServiceArgs,
2674 LPCWSTR *lpServiceArgVectors)
2675 {
2676 DWORD dwError;
2677
2678 RpcTryExcept
2679 {
2680 dwError = RStartServiceW((SC_RPC_HANDLE)hService,
2681 dwNumServiceArgs,
2682 (LPSTRING_PTRSW)lpServiceArgVectors);
2683 }
2684 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2685 {
2686 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2687 }
2688 RpcEndExcept;
2689
2690 if (dwError != ERROR_SUCCESS)
2691 {
2692 ERR("RStartServiceW() failed (Error %lu)\n", dwError);
2693 SetLastError(dwError);
2694 return FALSE;
2695 }
2696
2697 return TRUE;
2698 }
2699
2700
2701 /**********************************************************************
2702 * UnlockServiceDatabase
2703 *
2704 * @implemented
2705 */
2706 BOOL WINAPI
2707 UnlockServiceDatabase(SC_LOCK ScLock)
2708 {
2709 DWORD dwError;
2710
2711 TRACE("UnlockServiceDatabase(%x)\n", ScLock);
2712
2713 RpcTryExcept
2714 {
2715 /* Call to services.exe using RPC */
2716 dwError = RUnlockServiceDatabase((LPSC_RPC_LOCK)&ScLock);
2717 }
2718 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2719 {
2720 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2721 }
2722 RpcEndExcept;
2723
2724 if (dwError != ERROR_SUCCESS)
2725 {
2726 TRACE("RUnlockServiceDatabase() failed (Error %lu)\n", dwError);
2727 SetLastError(dwError);
2728 return FALSE;
2729 }
2730
2731 return TRUE;
2732 }
2733
2734
2735 /**********************************************************************
2736 * NotifyBootConfigStatus
2737 *
2738 * @implemented
2739 */
2740 BOOL WINAPI
2741 NotifyBootConfigStatus(BOOL BootAcceptable)
2742 {
2743 DWORD dwError;
2744
2745 TRACE("NotifyBootConfigStatus()\n");
2746
2747 RpcTryExcept
2748 {
2749 /* Call to services.exe using RPC */
2750 dwError = RNotifyBootConfigStatus(NULL,
2751 BootAcceptable);
2752 }
2753 RpcExcept(EXCEPTION_EXECUTE_HANDLER)
2754 {
2755 dwError = ScmRpcStatusToWinError(RpcExceptionCode());
2756 }
2757 RpcEndExcept;
2758
2759 if (dwError != ERROR_SUCCESS)
2760 {
2761 TRACE("NotifyBootConfigStatus() failed (Error %lu)\n", dwError);
2762 SetLastError(dwError);
2763 return FALSE;
2764 }
2765
2766 return TRUE;
2767 }
2768
2769 /* EOF */