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