Create a branch for network fixes.
[reactos.git] / dll / win32 / advapi32 / service / scm.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: ReactOS system libraries
4 * FILE: lib/advapi32/service/scm.c
5 * PURPOSE: Service control manager functions
6 * PROGRAMMER: Emanuele Aliberti
7 * Eric Kohl
8 * UPDATE HISTORY:
9 * 19990413 EA created
10 * 19990515 EA
11 */
12
13 /* INCLUDES ******************************************************************/
14
15 #include <advapi32.h>
16
17 #include "wine/debug.h"
18
19 WINE_DEFAULT_DEBUG_CHANNEL(advapi);
20
21
22 /* FUNCTIONS *****************************************************************/
23
24 handle_t BindingHandle = NULL;
25
26 VOID
27 HandleBind(VOID)
28 {
29 LPWSTR pszStringBinding;
30 RPC_STATUS status;
31
32 if (BindingHandle != NULL)
33 return;
34
35 status = RpcStringBindingComposeW(NULL,
36 L"ncacn_np",
37 NULL,
38 L"\\pipe\\ntsvcs",
39 NULL,
40 &pszStringBinding);
41 if (status)
42 {
43 TRACE("RpcStringBindingCompose returned 0x%x\n", status);
44 return;
45 }
46
47 /* Set the binding handle that will be used to bind to the server. */
48 status = RpcBindingFromStringBindingW(pszStringBinding,
49 &BindingHandle);
50 if (status)
51 {
52 TRACE("RpcBindingFromStringBinding returned 0x%x\n", status);
53 }
54
55 status = RpcStringFreeW(&pszStringBinding);
56 if (status)
57 {
58 TRACE("RpcStringFree returned 0x%x\n", status);
59 }
60 }
61
62
63 #if 0
64 static VOID
65 HandleUnbind(VOID)
66 {
67 RPC_STATUS status;
68
69 if (BindingHandle == NULL)
70 return;
71
72 status = RpcBindingFree(&BindingHandle);
73 if (status)
74 {
75 TRACE("RpcBindingFree returned 0x%x\n", status);
76 }
77 }
78 #endif
79
80
81 /**********************************************************************
82 * ChangeServiceConfig2A
83 *
84 * @implemented
85 */
86 BOOL WINAPI
87 ChangeServiceConfig2A(SC_HANDLE hService,
88 DWORD dwInfoLevel,
89 LPVOID lpInfo)
90 {
91 SC_RPC_CONFIG_INFOA Info;
92 DWORD dwError;
93
94 TRACE("ChangeServiceConfig2A() called\n");
95
96 /* Fill relevent field of the Info structure */
97 Info.dwInfoLevel = dwInfoLevel;
98 switch (dwInfoLevel)
99 {
100 case SERVICE_CONFIG_DESCRIPTION:
101 Info.psd = (LPSERVICE_DESCRIPTIONA)&lpInfo;
102 break;
103
104 case SERVICE_CONFIG_FAILURE_ACTIONS:
105 Info.psfa = (LPSERVICE_FAILURE_ACTIONSA)&lpInfo;
106 break;
107
108 default:
109 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
110 SetLastError(ERROR_INVALID_PARAMETER);
111 return FALSE;
112 }
113
114 if (lpInfo == NULL)
115 return TRUE;
116
117 HandleBind();
118
119 dwError = RChangeServiceConfig2A(BindingHandle,
120 (SC_RPC_HANDLE)hService,
121 Info);
122 if (dwError != ERROR_SUCCESS)
123 {
124 ERR("RChangeServiceConfig2A() failed (Error %lu)\n", dwError);
125 SetLastError(dwError);
126 return FALSE;
127 }
128
129 return TRUE;
130 }
131
132
133 /**********************************************************************
134 * ChangeServiceConfig2W
135 *
136 * @implemented
137 */
138 BOOL WINAPI
139 ChangeServiceConfig2W(SC_HANDLE hService,
140 DWORD dwInfoLevel,
141 LPVOID lpInfo)
142 {
143 SC_RPC_CONFIG_INFOW Info;
144 DWORD dwError;
145
146 TRACE("ChangeServiceConfig2W() called\n");
147
148 /* Fill relevent field of the Info structure */
149 Info.dwInfoLevel = dwInfoLevel;
150 switch (dwInfoLevel)
151 {
152 case SERVICE_CONFIG_DESCRIPTION:
153 {
154 Info.psd = (LPSERVICE_DESCRIPTIONW)&lpInfo;
155 break;
156 }
157
158 case SERVICE_CONFIG_FAILURE_ACTIONS:
159 Info.psfa = (LPSERVICE_FAILURE_ACTIONSW)&lpInfo;
160 break;
161
162 default:
163 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
164 SetLastError(ERROR_INVALID_PARAMETER);
165 return FALSE;
166 }
167
168 if (lpInfo == NULL)
169 return TRUE;
170
171 HandleBind();
172
173 dwError = RChangeServiceConfig2W(BindingHandle,
174 (SC_RPC_HANDLE)hService,
175 Info);
176 if (dwError != ERROR_SUCCESS)
177 {
178 ERR("RChangeServiceConfig2W() failed (Error %lu)\n", dwError);
179 SetLastError(dwError);
180 return FALSE;
181 }
182
183 return TRUE;
184 }
185
186
187 /**********************************************************************
188 * ChangeServiceConfigA
189 *
190 * @implemented
191 */
192 BOOL STDCALL
193 ChangeServiceConfigA(SC_HANDLE hService,
194 DWORD dwServiceType,
195 DWORD dwStartType,
196 DWORD dwErrorControl,
197 LPCSTR lpBinaryPathName,
198 LPCSTR lpLoadOrderGroup,
199 LPDWORD lpdwTagId,
200 LPCSTR lpDependencies,
201 LPCSTR lpServiceStartName,
202 LPCSTR lpPassword,
203 LPCSTR lpDisplayName)
204 {
205 DWORD dwError;
206 DWORD dwDependenciesLength = 0;
207 DWORD dwLength;
208 LPSTR lpStr;
209
210 TRACE("ChangeServiceConfigA() called\n");
211
212 /* Calculate the Dependencies length*/
213 if (lpDependencies != NULL)
214 {
215 lpStr = (LPSTR)lpDependencies;
216 while (*lpStr)
217 {
218 dwLength = strlen(lpStr) + 1;
219 dwDependenciesLength += dwLength;
220 lpStr = lpStr + dwLength;
221 }
222 dwDependenciesLength++;
223 }
224
225 /* FIXME: Encrypt the password */
226
227 HandleBind();
228
229 /* Call to services.exe using RPC */
230 dwError = RChangeServiceConfigA(BindingHandle,
231 (SC_RPC_HANDLE)hService,
232 dwServiceType,
233 dwStartType,
234 dwErrorControl,
235 (LPSTR)lpBinaryPathName,
236 (LPSTR)lpLoadOrderGroup,
237 lpdwTagId,
238 (LPSTR)lpDependencies,
239 dwDependenciesLength,
240 (LPSTR)lpServiceStartName,
241 NULL, /* FIXME: lpPassword */
242 0, /* FIXME: dwPasswordLength */
243 (LPSTR)lpDisplayName);
244 if (dwError != ERROR_SUCCESS)
245 {
246 ERR("RChangeServiceConfigA() failed (Error %lu)\n", dwError);
247 SetLastError(dwError);
248 return FALSE;
249 }
250
251 return TRUE;
252 }
253
254
255 /**********************************************************************
256 * ChangeServiceConfigW
257 *
258 * @implemented
259 */
260 BOOL STDCALL
261 ChangeServiceConfigW(SC_HANDLE hService,
262 DWORD dwServiceType,
263 DWORD dwStartType,
264 DWORD dwErrorControl,
265 LPCWSTR lpBinaryPathName,
266 LPCWSTR lpLoadOrderGroup,
267 LPDWORD lpdwTagId,
268 LPCWSTR lpDependencies,
269 LPCWSTR lpServiceStartName,
270 LPCWSTR lpPassword,
271 LPCWSTR lpDisplayName)
272 {
273 DWORD dwError;
274 DWORD dwDependenciesLength = 0;
275 DWORD dwLength;
276 LPWSTR lpStr;
277
278 TRACE("ChangeServiceConfigW() called\n");
279
280 /* Calculate the Dependencies length*/
281 if (lpDependencies != NULL)
282 {
283 lpStr = (LPWSTR)lpDependencies;
284 while (*lpStr)
285 {
286 dwLength = wcslen(lpStr) + 1;
287 dwDependenciesLength += dwLength;
288 lpStr = lpStr + dwLength;
289 }
290 dwDependenciesLength++;
291 }
292
293 /* FIXME: Encrypt the password */
294
295 HandleBind();
296
297 /* Call to services.exe using RPC */
298 dwError = RChangeServiceConfigW(BindingHandle,
299 (SC_RPC_HANDLE)hService,
300 dwServiceType,
301 dwStartType,
302 dwErrorControl,
303 (LPWSTR)lpBinaryPathName,
304 (LPWSTR)lpLoadOrderGroup,
305 lpdwTagId,
306 (LPBYTE)lpDependencies,
307 dwDependenciesLength,
308 (LPWSTR)lpServiceStartName,
309 NULL, /* FIXME: lpPassword */
310 0, /* FIXME: dwPasswordLength */
311 (LPWSTR)lpDisplayName);
312 if (dwError != ERROR_SUCCESS)
313 {
314 ERR("RChangeServiceConfigW() failed (Error %lu)\n", dwError);
315 SetLastError(dwError);
316 return FALSE;
317 }
318
319 return TRUE;
320 }
321
322
323 /**********************************************************************
324 * CloseServiceHandle
325 *
326 * @implemented
327 */
328 BOOL STDCALL
329 CloseServiceHandle(SC_HANDLE hSCObject)
330 {
331 DWORD dwError;
332
333 TRACE("CloseServiceHandle() called\n");
334
335 HandleBind();
336
337 /* Call to services.exe using RPC */
338 dwError = RCloseServiceHandle(BindingHandle,
339 (LPSC_RPC_HANDLE)&hSCObject);
340 if (dwError)
341 {
342 ERR("RCloseServiceHandle() failed (Error %lu)\n", dwError);
343 SetLastError(dwError);
344 return FALSE;
345 }
346
347 TRACE("CloseServiceHandle() done\n");
348
349 return TRUE;
350 }
351
352
353 /**********************************************************************
354 * ControlService
355 *
356 * @implemented
357 */
358 BOOL STDCALL
359 ControlService(SC_HANDLE hService,
360 DWORD dwControl,
361 LPSERVICE_STATUS lpServiceStatus)
362 {
363 DWORD dwError;
364
365 TRACE("ControlService(%x, %x, %p)\n",
366 hService, dwControl, lpServiceStatus);
367
368 HandleBind();
369
370 /* Call to services.exe using RPC */
371 dwError = RControlService(BindingHandle,
372 (SC_RPC_HANDLE)hService,
373 dwControl,
374 lpServiceStatus);
375 if (dwError != ERROR_SUCCESS)
376 {
377 ERR("RControlService() failed (Error %lu)\n", dwError);
378 SetLastError(dwError);
379 return FALSE;
380 }
381
382 TRACE("ControlService() done\n");
383
384 return TRUE;
385 }
386
387
388 /**********************************************************************
389 * ControlServiceEx
390 *
391 * @unimplemented
392 */
393 BOOL STDCALL
394 ControlServiceEx(IN SC_HANDLE hService,
395 IN DWORD dwControl,
396 IN DWORD dwInfoLevel,
397 IN OUT PVOID pControlParams)
398 {
399 FIXME("ControlServiceEx(0x%p, 0x%x, 0x%x, 0x%p) UNIMPLEMENTED!\n",
400 hService, dwControl, dwInfoLevel, pControlParams);
401 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
402 return FALSE;
403 }
404
405
406
407 /**********************************************************************
408 * CreateServiceA
409 *
410 * @implemented
411 */
412 SC_HANDLE STDCALL
413 CreateServiceA(SC_HANDLE hSCManager,
414 LPCSTR lpServiceName,
415 LPCSTR lpDisplayName,
416 DWORD dwDesiredAccess,
417 DWORD dwServiceType,
418 DWORD dwStartType,
419 DWORD dwErrorControl,
420 LPCSTR lpBinaryPathName,
421 LPCSTR lpLoadOrderGroup,
422 LPDWORD lpdwTagId,
423 LPCSTR lpDependencies,
424 LPCSTR lpServiceStartName,
425 LPCSTR lpPassword)
426 {
427 SC_HANDLE RetVal = NULL;
428 LPWSTR lpServiceNameW = NULL;
429 LPWSTR lpDisplayNameW = NULL;
430 LPWSTR lpBinaryPathNameW = NULL;
431 LPWSTR lpLoadOrderGroupW = NULL;
432 LPWSTR lpDependenciesW = NULL;
433 LPWSTR lpServiceStartNameW = NULL;
434 LPWSTR lpPasswordW = NULL;
435 DWORD dwDependenciesLength = 0;
436 DWORD dwLength;
437 int len;
438 LPSTR lpStr;
439
440 if (lpServiceName)
441 {
442 len = MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, NULL, 0);
443 lpServiceNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
444 if (!lpServiceNameW)
445 {
446 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
447 goto cleanup;
448 }
449 MultiByteToWideChar(CP_ACP, 0, lpServiceName, -1, lpServiceNameW, len);
450 }
451
452 if (lpDisplayName)
453 {
454 len = MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, NULL, 0);
455 lpDisplayNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
456 if (!lpDisplayNameW)
457 {
458 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
459 goto cleanup;
460 }
461 MultiByteToWideChar(CP_ACP, 0, lpDisplayName, -1, lpDisplayNameW, len);
462 }
463
464 if (lpBinaryPathName)
465 {
466 len = MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, NULL, 0);
467 lpBinaryPathNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
468 if (!lpBinaryPathNameW)
469 {
470 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
471 goto cleanup;
472 }
473 MultiByteToWideChar(CP_ACP, 0, lpBinaryPathName, -1, lpBinaryPathNameW, len);
474 }
475
476 if (lpLoadOrderGroup)
477 {
478 len = MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, NULL, 0);
479 lpLoadOrderGroupW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
480 if (!lpLoadOrderGroupW)
481 {
482 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
483 goto cleanup;
484 }
485 MultiByteToWideChar(CP_ACP, 0, lpLoadOrderGroup, -1, lpLoadOrderGroupW, len);
486 }
487
488 if (lpDependencies)
489 {
490 lpStr = (LPSTR)lpDependencies;
491 while (*lpStr)
492 {
493 dwLength = strlen(lpStr) + 1;
494 dwDependenciesLength += dwLength;
495 lpStr = lpStr + dwLength;
496 }
497 dwDependenciesLength++;
498
499 lpDependenciesW = HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength * sizeof(WCHAR));
500 if (!lpDependenciesW)
501 {
502 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
503 goto cleanup;
504 }
505 MultiByteToWideChar(CP_ACP, 0, lpDependencies, dwDependenciesLength, lpDependenciesW, dwDependenciesLength);
506 }
507
508 if (lpServiceStartName)
509 {
510 len = MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, NULL, 0);
511 lpServiceStartNameW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
512 if (!lpServiceStartNameW)
513 {
514 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
515 goto cleanup;
516 }
517 MultiByteToWideChar(CP_ACP, 0, lpServiceStartName, -1, lpServiceStartNameW, len);
518 }
519
520 if (lpPassword)
521 {
522 len = MultiByteToWideChar(CP_ACP, 0, lpPassword, -1, NULL, 0);
523 lpPasswordW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
524 if (!lpPasswordW)
525 {
526 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
527 goto cleanup;
528 }
529 MultiByteToWideChar(CP_ACP, 0, lpPassword, -1, lpPasswordW, len);
530 }
531
532 RetVal = CreateServiceW(hSCManager,
533 lpServiceNameW,
534 lpDisplayNameW,
535 dwDesiredAccess,
536 dwServiceType,
537 dwStartType,
538 dwErrorControl,
539 lpBinaryPathNameW,
540 lpLoadOrderGroupW,
541 lpdwTagId,
542 lpDependenciesW,
543 lpServiceStartNameW,
544 lpPasswordW);
545
546 cleanup:
547 if (lpServiceNameW !=NULL)
548 HeapFree(GetProcessHeap(), 0, lpServiceNameW);
549
550 if (lpDisplayNameW != NULL)
551 HeapFree(GetProcessHeap(), 0, lpDisplayNameW);
552
553 if (lpBinaryPathNameW != NULL)
554 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW);
555
556 if (lpLoadOrderGroupW != NULL)
557 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW);
558
559 if (lpDependenciesW != NULL)
560 HeapFree(GetProcessHeap(), 0, lpDependenciesW);
561
562 if (lpServiceStartNameW != NULL)
563 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW);
564
565 if (lpPasswordW != NULL)
566 HeapFree(GetProcessHeap(), 0, lpPasswordW);
567
568 return RetVal;
569 }
570
571
572 /**********************************************************************
573 * CreateServiceW
574 *
575 * @implemented
576 */
577 SC_HANDLE STDCALL
578 CreateServiceW(SC_HANDLE hSCManager,
579 LPCWSTR lpServiceName,
580 LPCWSTR lpDisplayName,
581 DWORD dwDesiredAccess,
582 DWORD dwServiceType,
583 DWORD dwStartType,
584 DWORD dwErrorControl,
585 LPCWSTR lpBinaryPathName,
586 LPCWSTR lpLoadOrderGroup,
587 LPDWORD lpdwTagId,
588 LPCWSTR lpDependencies,
589 LPCWSTR lpServiceStartName,
590 LPCWSTR lpPassword)
591 {
592 SC_HANDLE hService = NULL;
593 DWORD dwDependenciesLength = 0;
594 DWORD dwError;
595 DWORD dwLength;
596 LPWSTR lpStr;
597
598 TRACE("CreateServiceW() called\n");
599
600 /* Calculate the Dependencies length*/
601 if (lpDependencies != NULL)
602 {
603 lpStr = (LPWSTR)lpDependencies;
604 while (*lpStr)
605 {
606 dwLength = wcslen(lpStr) + 1;
607 dwDependenciesLength += dwLength;
608 lpStr = lpStr + dwLength;
609 }
610 dwDependenciesLength++;
611
612 dwDependenciesLength *= sizeof(WCHAR);
613 }
614
615 /* FIXME: Encrypt the password */
616
617 HandleBind();
618
619 /* Call to services.exe using RPC */
620 dwError = RCreateServiceW(BindingHandle,
621 (SC_RPC_HANDLE)hSCManager,
622 (LPWSTR)lpServiceName,
623 (LPWSTR)lpDisplayName,
624 dwDesiredAccess,
625 dwServiceType,
626 dwStartType,
627 dwErrorControl,
628 (LPWSTR)lpBinaryPathName,
629 (LPWSTR)lpLoadOrderGroup,
630 lpdwTagId,
631 (LPBYTE)lpDependencies,
632 dwDependenciesLength,
633 (LPWSTR)lpServiceStartName,
634 NULL, /* FIXME: lpPassword */
635 0, /* FIXME: dwPasswordLength */
636 (SC_RPC_HANDLE *)&hService);
637 if (dwError != ERROR_SUCCESS)
638 {
639 ERR("RCreateServiceW() failed (Error %lu)\n", dwError);
640 SetLastError(dwError);
641 return NULL;
642 }
643
644 return hService;
645 }
646
647
648 /**********************************************************************
649 * DeleteService
650 *
651 * @implemented
652 */
653 BOOL STDCALL
654 DeleteService(SC_HANDLE hService)
655 {
656 DWORD dwError;
657
658 TRACE("DeleteService(%x)\n", hService);
659
660 HandleBind();
661
662 /* Call to services.exe using RPC */
663 dwError = RDeleteService(BindingHandle,
664 (SC_RPC_HANDLE)hService);
665 if (dwError != ERROR_SUCCESS)
666 {
667 ERR("RDeleteService() failed (Error %lu)\n", dwError);
668 SetLastError(dwError);
669 return FALSE;
670 }
671
672 return TRUE;
673 }
674
675
676 /**********************************************************************
677 * EnumDependentServicesA
678 *
679 * @implemented
680 */
681 BOOL STDCALL
682 EnumDependentServicesA(SC_HANDLE hService,
683 DWORD dwServiceState,
684 LPENUM_SERVICE_STATUSA lpServices,
685 DWORD cbBufSize,
686 LPDWORD pcbBytesNeeded,
687 LPDWORD lpServicesReturned)
688 {
689 LPENUM_SERVICE_STATUSA lpStatusPtr;
690 DWORD dwError = ERROR_SUCCESS;
691 DWORD dwCount;
692
693 TRACE("EnumServicesStatusA() called\n");
694
695 HandleBind();
696
697 dwError = REnumDependentServicesA(BindingHandle,
698 (SC_RPC_HANDLE)hService,
699 dwServiceState,
700 (LPBYTE)lpServices,
701 cbBufSize,
702 pcbBytesNeeded,
703 lpServicesReturned);
704
705 lpStatusPtr = (LPENUM_SERVICE_STATUSA)lpServices;
706 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
707 {
708 if (lpStatusPtr->lpServiceName)
709 lpStatusPtr->lpServiceName =
710 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
711
712 if (lpStatusPtr->lpDisplayName)
713 lpStatusPtr->lpDisplayName =
714 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
715
716 lpStatusPtr++;
717 }
718
719 if (dwError != ERROR_SUCCESS)
720 {
721 ERR("REnumDependentServicesA() failed (Error %lu)\n", dwError);
722 SetLastError(dwError);
723 return FALSE;
724 }
725
726 TRACE("EnumDependentServicesA() done\n");
727
728 return TRUE;
729 }
730
731
732 /**********************************************************************
733 * EnumDependentServicesW
734 *
735 * @implemented
736 */
737 BOOL STDCALL
738 EnumDependentServicesW(SC_HANDLE hService,
739 DWORD dwServiceState,
740 LPENUM_SERVICE_STATUSW lpServices,
741 DWORD cbBufSize,
742 LPDWORD pcbBytesNeeded,
743 LPDWORD lpServicesReturned)
744 {
745 LPENUM_SERVICE_STATUSW lpStatusPtr;
746 DWORD dwError = ERROR_SUCCESS;
747 DWORD dwCount;
748
749 TRACE("EnumServicesStatusW() called\n");
750
751 HandleBind();
752
753 dwError = REnumDependentServicesW(BindingHandle,
754 (SC_RPC_HANDLE)hService,
755 dwServiceState,
756 (LPBYTE)lpServices,
757 cbBufSize,
758 pcbBytesNeeded,
759 lpServicesReturned);
760
761 lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpServices;
762 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
763 {
764 if (lpStatusPtr->lpServiceName)
765 lpStatusPtr->lpServiceName =
766 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
767
768 if (lpStatusPtr->lpDisplayName)
769 lpStatusPtr->lpDisplayName =
770 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
771
772 lpStatusPtr++;
773 }
774
775 if (dwError != ERROR_SUCCESS)
776 {
777 ERR("REnumDependentServicesW() failed (Error %lu)\n", dwError);
778 SetLastError(dwError);
779 return FALSE;
780 }
781
782 TRACE("EnumDependentServicesW() done\n");
783
784 return TRUE;
785 }
786
787
788 /**********************************************************************
789 * EnumServiceGroupW
790 *
791 * @unimplemented
792 */
793 BOOL
794 STDCALL
795 EnumServiceGroupW(
796 SC_HANDLE hSCManager,
797 DWORD dwServiceType,
798 DWORD dwServiceState,
799 LPENUM_SERVICE_STATUSW lpServices,
800 DWORD cbBufSize,
801 LPDWORD pcbBytesNeeded,
802 LPDWORD lpServicesReturned,
803 LPDWORD lpResumeHandle,
804 LPCWSTR lpGroup)
805 {
806 FIXME("EnumServiceGroupW is unimplemented\n");
807 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
808 return FALSE;
809 }
810
811
812 /**********************************************************************
813 * EnumServicesStatusA
814 *
815 * @implemented
816 */
817 BOOL STDCALL
818 EnumServicesStatusA(SC_HANDLE hSCManager,
819 DWORD dwServiceType,
820 DWORD dwServiceState,
821 LPENUM_SERVICE_STATUSA lpServices,
822 DWORD cbBufSize,
823 LPDWORD pcbBytesNeeded,
824 LPDWORD lpServicesReturned,
825 LPDWORD lpResumeHandle)
826 {
827 LPENUM_SERVICE_STATUSA lpStatusPtr;
828 DWORD dwError = ERROR_SUCCESS;
829 DWORD dwCount;
830
831 TRACE("EnumServicesStatusA() called\n");
832
833 HandleBind();
834
835 dwError = REnumServicesStatusA(BindingHandle,
836 (SC_RPC_HANDLE)hSCManager,
837 dwServiceType,
838 dwServiceState,
839 (LPBYTE)lpServices,
840 cbBufSize,
841 pcbBytesNeeded,
842 lpServicesReturned,
843 lpResumeHandle);
844
845 lpStatusPtr = (LPENUM_SERVICE_STATUSA)lpServices;
846 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
847 {
848 if (lpStatusPtr->lpServiceName)
849 lpStatusPtr->lpServiceName =
850 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
851
852 if (lpStatusPtr->lpDisplayName)
853 lpStatusPtr->lpDisplayName =
854 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
855
856 lpStatusPtr++;
857 }
858
859 if (dwError != ERROR_SUCCESS)
860 {
861 ERR("REnumServicesStatusA() failed (Error %lu)\n", dwError);
862 SetLastError(dwError);
863 return FALSE;
864 }
865
866 TRACE("EnumServicesStatusA() done\n");
867
868 return TRUE;
869 }
870
871
872 /**********************************************************************
873 * EnumServicesStatusW
874 *
875 * @implemented
876 */
877 BOOL STDCALL
878 EnumServicesStatusW(SC_HANDLE hSCManager,
879 DWORD dwServiceType,
880 DWORD dwServiceState,
881 LPENUM_SERVICE_STATUSW lpServices,
882 DWORD cbBufSize,
883 LPDWORD pcbBytesNeeded,
884 LPDWORD lpServicesReturned,
885 LPDWORD lpResumeHandle)
886 {
887 LPENUM_SERVICE_STATUSW lpStatusPtr;
888 DWORD dwError = ERROR_SUCCESS;
889 DWORD dwCount;
890
891 TRACE("EnumServicesStatusW() called\n");
892
893 HandleBind();
894
895 dwError = REnumServicesStatusW(BindingHandle,
896 (SC_RPC_HANDLE)hSCManager,
897 dwServiceType,
898 dwServiceState,
899 (LPBYTE)lpServices,
900 cbBufSize,
901 pcbBytesNeeded,
902 lpServicesReturned,
903 lpResumeHandle);
904
905 lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpServices;
906 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
907 {
908 if (lpStatusPtr->lpServiceName)
909 lpStatusPtr->lpServiceName =
910 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
911
912 if (lpStatusPtr->lpDisplayName)
913 lpStatusPtr->lpDisplayName =
914 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
915
916 lpStatusPtr++;
917 }
918
919 if (dwError != ERROR_SUCCESS)
920 {
921 ERR("REnumServicesStatusW() failed (Error %lu)\n", dwError);
922 SetLastError(dwError);
923 return FALSE;
924 }
925
926 TRACE("EnumServicesStatusW() done\n");
927
928 return TRUE;
929 }
930
931
932 /**********************************************************************
933 * EnumServicesStatusExA
934 *
935 * @implemented
936 */
937 BOOL STDCALL
938 EnumServicesStatusExA(SC_HANDLE hSCManager,
939 SC_ENUM_TYPE InfoLevel,
940 DWORD dwServiceType,
941 DWORD dwServiceState,
942 LPBYTE lpServices,
943 DWORD cbBufSize,
944 LPDWORD pcbBytesNeeded,
945 LPDWORD lpServicesReturned,
946 LPDWORD lpResumeHandle,
947 LPCSTR pszGroupName)
948 {
949 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtr;
950 DWORD dwError = ERROR_SUCCESS;
951 DWORD dwCount;
952
953 TRACE("EnumServicesStatusExA() called\n");
954
955 HandleBind();
956
957 dwError = REnumServicesStatusExA(BindingHandle,
958 (SC_RPC_HANDLE)hSCManager,
959 InfoLevel,
960 dwServiceType,
961 dwServiceState,
962 (LPBYTE)lpServices,
963 cbBufSize,
964 pcbBytesNeeded,
965 lpServicesReturned,
966 lpResumeHandle,
967 (LPSTR)pszGroupName);
968
969 if (dwError == ERROR_MORE_DATA)
970 {
971 WARN("Required buffer size %ul\n", *pcbBytesNeeded);
972 SetLastError(dwError);
973 return FALSE;
974 }
975 else if (dwError == ERROR_SUCCESS)
976 {
977 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSA)lpServices;
978 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
979 {
980 if (lpStatusPtr->lpServiceName)
981 lpStatusPtr->lpServiceName =
982 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
983
984 if (lpStatusPtr->lpDisplayName)
985 lpStatusPtr->lpDisplayName =
986 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
987
988 lpStatusPtr++;
989 }
990 }
991 else
992 {
993 ERR("REnumServicesStatusExA() failed (Error %lu)\n", dwError);
994 SetLastError(dwError);
995 return FALSE;
996 }
997
998 TRACE("EnumServicesStatusExA() done\n");
999
1000 return TRUE;
1001 }
1002
1003
1004 /**********************************************************************
1005 * EnumServicesStatusExW
1006 *
1007 * @implemented
1008 */
1009 BOOL STDCALL
1010 EnumServicesStatusExW(SC_HANDLE hSCManager,
1011 SC_ENUM_TYPE InfoLevel,
1012 DWORD dwServiceType,
1013 DWORD dwServiceState,
1014 LPBYTE lpServices,
1015 DWORD cbBufSize,
1016 LPDWORD pcbBytesNeeded,
1017 LPDWORD lpServicesReturned,
1018 LPDWORD lpResumeHandle,
1019 LPCWSTR pszGroupName)
1020 {
1021 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
1022 DWORD dwError = ERROR_SUCCESS;
1023 DWORD dwCount;
1024
1025 TRACE("EnumServicesStatusExW() called\n");
1026
1027 HandleBind();
1028
1029 dwError = REnumServicesStatusExW(BindingHandle,
1030 (SC_RPC_HANDLE)hSCManager,
1031 InfoLevel,
1032 dwServiceType,
1033 dwServiceState,
1034 (LPBYTE)lpServices,
1035 cbBufSize,
1036 pcbBytesNeeded,
1037 lpServicesReturned,
1038 lpResumeHandle,
1039 (LPWSTR)pszGroupName);
1040
1041 if (dwError == ERROR_MORE_DATA)
1042 {
1043 WARN("Required buffer size %ul\n", *pcbBytesNeeded);
1044 SetLastError(dwError);
1045 return FALSE;
1046 }
1047 else if (dwError == ERROR_SUCCESS)
1048 {
1049 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices;
1050 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
1051 {
1052 if (lpStatusPtr->lpServiceName)
1053 lpStatusPtr->lpServiceName =
1054 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
1055
1056 if (lpStatusPtr->lpDisplayName)
1057 lpStatusPtr->lpDisplayName =
1058 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
1059
1060 lpStatusPtr++;
1061 }
1062 }
1063 else
1064 {
1065 ERR("REnumServicesStatusExW() failed (Error %lu)\n", dwError);
1066 SetLastError(dwError);
1067 return FALSE;
1068 }
1069
1070 TRACE("EnumServicesStatusExW() done\n");
1071
1072 return TRUE;
1073 }
1074
1075
1076 /**********************************************************************
1077 * GetServiceDisplayNameA
1078 *
1079 * @implemented
1080 */
1081 BOOL STDCALL
1082 GetServiceDisplayNameA(SC_HANDLE hSCManager,
1083 LPCSTR lpServiceName,
1084 LPSTR lpDisplayName,
1085 LPDWORD lpcchBuffer)
1086 {
1087 DWORD dwError;
1088
1089 TRACE("GetServiceDisplayNameA() called\n");
1090
1091 HandleBind();
1092
1093 dwError = RGetServiceDisplayNameA(BindingHandle,
1094 (SC_RPC_HANDLE)hSCManager,
1095 (LPSTR)lpServiceName,
1096 lpDisplayName,
1097 lpcchBuffer);
1098 if (dwError != ERROR_SUCCESS)
1099 {
1100 ERR("RGetServiceDisplayNameA() failed (Error %lu)\n", dwError);
1101 SetLastError(dwError);
1102 return FALSE;
1103 }
1104
1105 (*lpcchBuffer)--;
1106
1107 return TRUE;
1108 }
1109
1110
1111 /**********************************************************************
1112 * GetServiceDisplayNameW
1113 *
1114 * @implemented
1115 */
1116 BOOL STDCALL
1117 GetServiceDisplayNameW(SC_HANDLE hSCManager,
1118 LPCWSTR lpServiceName,
1119 LPWSTR lpDisplayName,
1120 LPDWORD lpcchBuffer)
1121 {
1122 DWORD dwError;
1123
1124 TRACE("GetServiceDisplayNameW() called\n");
1125
1126 HandleBind();
1127
1128 dwError = RGetServiceDisplayNameW(BindingHandle,
1129 (SC_RPC_HANDLE)hSCManager,
1130 (LPWSTR)lpServiceName,
1131 lpDisplayName,
1132 lpcchBuffer);
1133 if (dwError != ERROR_SUCCESS)
1134 {
1135 ERR("RGetServiceDisplayNameW() failed (Error %lu)\n", dwError);
1136 SetLastError(dwError);
1137 return FALSE;
1138 }
1139
1140 (*lpcchBuffer)--;
1141
1142 return TRUE;
1143 }
1144
1145
1146 /**********************************************************************
1147 * GetServiceKeyNameA
1148 *
1149 * @implemented
1150 */
1151 BOOL STDCALL
1152 GetServiceKeyNameA(SC_HANDLE hSCManager,
1153 LPCSTR lpDisplayName,
1154 LPSTR lpServiceName,
1155 LPDWORD lpcchBuffer)
1156 {
1157 DWORD dwError;
1158
1159 TRACE("GetServiceKeyNameA() called\n");
1160
1161 HandleBind();
1162
1163 dwError = RGetServiceKeyNameA(BindingHandle,
1164 (SC_RPC_HANDLE)hSCManager,
1165 (LPSTR)lpDisplayName,
1166 lpServiceName,
1167 lpcchBuffer);
1168 if (dwError != ERROR_SUCCESS)
1169 {
1170 ERR("RGetServiceKeyNameA() failed (Error %lu)\n", dwError);
1171 SetLastError(dwError);
1172 return FALSE;
1173 }
1174
1175 (*lpcchBuffer)--;
1176
1177 return TRUE;
1178 }
1179
1180
1181 /**********************************************************************
1182 * GetServiceKeyNameW
1183 *
1184 * @implemented
1185 */
1186 BOOL STDCALL
1187 GetServiceKeyNameW(SC_HANDLE hSCManager,
1188 LPCWSTR lpDisplayName,
1189 LPWSTR lpServiceName,
1190 LPDWORD lpcchBuffer)
1191 {
1192 DWORD dwError;
1193
1194 TRACE("GetServiceKeyNameW() called\n");
1195
1196 HandleBind();
1197
1198 dwError = RGetServiceKeyNameW(BindingHandle,
1199 (SC_RPC_HANDLE)hSCManager,
1200 (LPWSTR)lpDisplayName,
1201 lpServiceName,
1202 lpcchBuffer);
1203 if (dwError != ERROR_SUCCESS)
1204 {
1205 ERR("RGetServiceKeyNameW() failed (Error %lu)\n", dwError);
1206 SetLastError(dwError);
1207 return FALSE;
1208 }
1209
1210 (*lpcchBuffer)--;
1211
1212 return TRUE;
1213 }
1214
1215
1216 /**********************************************************************
1217 * LockServiceDatabase
1218 *
1219 * @implemented
1220 */
1221 SC_LOCK STDCALL
1222 LockServiceDatabase(SC_HANDLE hSCManager)
1223 {
1224 SC_LOCK hLock;
1225 DWORD dwError;
1226
1227 TRACE("LockServiceDatabase(%x)\n", hSCManager);
1228
1229 HandleBind();
1230
1231 /* Call to services.exe using RPC */
1232 dwError = RLockServiceDatabase(BindingHandle,
1233 (SC_RPC_HANDLE)hSCManager,
1234 (SC_RPC_LOCK *)&hLock);
1235 if (dwError != ERROR_SUCCESS)
1236 {
1237 ERR("RLockServiceDatabase() failed (Error %lu)\n", dwError);
1238 SetLastError(dwError);
1239 return NULL;
1240 }
1241
1242 TRACE("hLock = %p\n", hLock);
1243
1244 return hLock;
1245 }
1246
1247
1248 static VOID
1249 WaitForSCManager(VOID)
1250 {
1251 HANDLE hEvent;
1252
1253 TRACE("WaitForSCManager() called\n");
1254
1255 /* Try to open the existing event */
1256 hEvent = OpenEventW(SYNCHRONIZE,
1257 FALSE,
1258 L"SvcctrlStartEvent_A3752DX");
1259 if (hEvent == NULL)
1260 {
1261 if (GetLastError() != ERROR_FILE_NOT_FOUND)
1262 return;
1263
1264 /* Try to create a new event */
1265 hEvent = CreateEventW(NULL,
1266 TRUE,
1267 FALSE,
1268 L"SvcctrlStartEvent_A3752DX");
1269 if (hEvent == NULL)
1270 {
1271 /* Try to open the existing event again */
1272 hEvent = OpenEventW(SYNCHRONIZE,
1273 FALSE,
1274 L"SvcctrlStartEvent_A3752DX");
1275 if (hEvent == NULL)
1276 return;
1277 }
1278 }
1279
1280 /* Wait for 3 minutes */
1281 WaitForSingleObject(hEvent, 180000);
1282 CloseHandle(hEvent);
1283
1284 TRACE("ScmWaitForSCManager() done\n");
1285 }
1286
1287
1288 /**********************************************************************
1289 * OpenSCManagerA
1290 *
1291 * @implemented
1292 */
1293 SC_HANDLE STDCALL
1294 OpenSCManagerA(LPCSTR lpMachineName,
1295 LPCSTR lpDatabaseName,
1296 DWORD dwDesiredAccess)
1297 {
1298 SC_HANDLE hScm = NULL;
1299 DWORD dwError;
1300
1301 TRACE("OpenSCManagerA(%s, %s, %lx)\n",
1302 lpMachineName, lpDatabaseName, dwDesiredAccess);
1303
1304 WaitForSCManager();
1305
1306 HandleBind();
1307
1308 /* Call to services.exe using RPC */
1309 dwError = ROpenSCManagerA(BindingHandle,
1310 (LPSTR)lpMachineName,
1311 (LPSTR)lpDatabaseName,
1312 dwDesiredAccess,
1313 (SC_RPC_HANDLE *)&hScm);
1314 if (dwError != ERROR_SUCCESS)
1315 {
1316 ERR("ROpenSCManagerA() failed (Error %lu)\n", dwError);
1317 SetLastError(dwError);
1318 return NULL;
1319 }
1320
1321 TRACE("hScm = %p\n", hScm);
1322
1323 return hScm;
1324 }
1325
1326
1327 /**********************************************************************
1328 * OpenSCManagerW
1329 *
1330 * @implemented
1331 */
1332 SC_HANDLE STDCALL
1333 OpenSCManagerW(LPCWSTR lpMachineName,
1334 LPCWSTR lpDatabaseName,
1335 DWORD dwDesiredAccess)
1336 {
1337 SC_HANDLE hScm = NULL;
1338 DWORD dwError;
1339
1340 TRACE("OpenSCManagerW(%S, %S, %lx)\n",
1341 lpMachineName, lpDatabaseName, dwDesiredAccess);
1342
1343 WaitForSCManager();
1344
1345 HandleBind();
1346
1347 /* Call to services.exe using RPC */
1348 dwError = ROpenSCManagerW(BindingHandle,
1349 (LPWSTR)lpMachineName,
1350 (LPWSTR)lpDatabaseName,
1351 dwDesiredAccess,
1352 (SC_RPC_HANDLE *)&hScm);
1353 if (dwError != ERROR_SUCCESS)
1354 {
1355 ERR("ROpenSCManagerW() failed (Error %lu)\n", dwError);
1356 SetLastError(dwError);
1357 return NULL;
1358 }
1359
1360 TRACE("hScm = %p\n", hScm);
1361
1362 return hScm;
1363 }
1364
1365
1366 /**********************************************************************
1367 * OpenServiceA
1368 *
1369 * @implemented
1370 */
1371 SC_HANDLE STDCALL
1372 OpenServiceA(SC_HANDLE hSCManager,
1373 LPCSTR lpServiceName,
1374 DWORD dwDesiredAccess)
1375 {
1376 SC_HANDLE hService = NULL;
1377 DWORD dwError;
1378
1379 TRACE("OpenServiceA(%p, %s, %lx)\n",
1380 hSCManager, lpServiceName, dwDesiredAccess);
1381
1382 HandleBind();
1383
1384 /* Call to services.exe using RPC */
1385 dwError = ROpenServiceA(BindingHandle,
1386 (SC_RPC_HANDLE)hSCManager,
1387 (LPSTR)lpServiceName,
1388 dwDesiredAccess,
1389 (SC_RPC_HANDLE *)&hService);
1390 if (dwError != ERROR_SUCCESS)
1391 {
1392 ERR("ROpenServiceA() failed (Error %lu)\n", dwError);
1393 SetLastError(dwError);
1394 return NULL;
1395 }
1396
1397 TRACE("hService = %p\n", hService);
1398
1399 return hService;
1400 }
1401
1402
1403 /**********************************************************************
1404 * OpenServiceW
1405 *
1406 * @implemented
1407 */
1408 SC_HANDLE STDCALL
1409 OpenServiceW(SC_HANDLE hSCManager,
1410 LPCWSTR lpServiceName,
1411 DWORD dwDesiredAccess)
1412 {
1413 SC_HANDLE hService = NULL;
1414 DWORD dwError;
1415
1416 TRACE("OpenServiceW(%p, %S, %lx)\n",
1417 hSCManager, lpServiceName, dwDesiredAccess);
1418
1419 HandleBind();
1420
1421 /* Call to services.exe using RPC */
1422 dwError = ROpenServiceW(BindingHandle,
1423 (SC_RPC_HANDLE)hSCManager,
1424 (LPWSTR)lpServiceName,
1425 dwDesiredAccess,
1426 (SC_RPC_HANDLE *)&hService);
1427 if (dwError != ERROR_SUCCESS)
1428 {
1429 if (dwError == ERROR_SERVICE_DOES_NOT_EXIST)
1430 WARN("ROpenServiceW() failed (Error %lu)\n", dwError);
1431 else
1432 ERR("ROpenServiceW() failed (Error %lu)\n", dwError);
1433 SetLastError(dwError);
1434 return NULL;
1435 }
1436
1437 TRACE("hService = %p\n", hService);
1438
1439 return hService;
1440 }
1441
1442
1443 /**********************************************************************
1444 * QueryServiceConfigA
1445 *
1446 * @implemented
1447 */
1448 BOOL STDCALL
1449 QueryServiceConfigA(SC_HANDLE hService,
1450 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
1451 DWORD cbBufSize,
1452 LPDWORD pcbBytesNeeded)
1453 {
1454 DWORD dwError;
1455
1456 TRACE("QueryServiceConfigA(%p, %p, %lu, %p)\n",
1457 hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
1458
1459 HandleBind();
1460
1461 /* Call to services.exe using RPC */
1462 dwError = RQueryServiceConfigA(BindingHandle,
1463 (SC_RPC_HANDLE)hService,
1464 lpServiceConfig,
1465 cbBufSize,
1466 pcbBytesNeeded);
1467 if (dwError != ERROR_SUCCESS)
1468 {
1469 ERR("RQueryServiceConfigA() failed (Error %lu)\n", dwError);
1470 SetLastError(dwError);
1471 return FALSE;
1472 }
1473
1474 /* Adjust the pointers */
1475 if (lpServiceConfig->lpBinaryPathName)
1476 lpServiceConfig->lpBinaryPathName =
1477 (LPSTR)((ULONG_PTR)lpServiceConfig +
1478 (ULONG_PTR)lpServiceConfig->lpBinaryPathName);
1479
1480 if (lpServiceConfig->lpLoadOrderGroup)
1481 lpServiceConfig->lpLoadOrderGroup =
1482 (LPSTR)((ULONG_PTR)lpServiceConfig +
1483 (ULONG_PTR)lpServiceConfig->lpLoadOrderGroup);
1484
1485 if (lpServiceConfig->lpDependencies)
1486 lpServiceConfig->lpDependencies =
1487 (LPSTR)((ULONG_PTR)lpServiceConfig +
1488 (ULONG_PTR)lpServiceConfig->lpDependencies);
1489
1490 if (lpServiceConfig->lpServiceStartName)
1491 lpServiceConfig->lpServiceStartName =
1492 (LPSTR)((ULONG_PTR)lpServiceConfig +
1493 (ULONG_PTR)lpServiceConfig->lpServiceStartName);
1494
1495 if (lpServiceConfig->lpDisplayName)
1496 lpServiceConfig->lpDisplayName =
1497 (LPSTR)((ULONG_PTR)lpServiceConfig +
1498 (ULONG_PTR)lpServiceConfig->lpDisplayName);
1499
1500 TRACE("QueryServiceConfigA() done\n");
1501
1502 return TRUE;
1503 }
1504
1505
1506 /**********************************************************************
1507 * QueryServiceConfigW
1508 *
1509 * @implemented
1510 */
1511 BOOL STDCALL
1512 QueryServiceConfigW(SC_HANDLE hService,
1513 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1514 DWORD cbBufSize,
1515 LPDWORD pcbBytesNeeded)
1516 {
1517 DWORD dwError;
1518
1519 TRACE("QueryServiceConfigW(%p, %p, %lu, %p)\n",
1520 hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
1521
1522 HandleBind();
1523
1524 /* Call to services.exe using RPC */
1525 dwError = RQueryServiceConfigW(BindingHandle,
1526 (SC_RPC_HANDLE)hService,
1527 (LPBYTE)lpServiceConfig,
1528 cbBufSize,
1529 pcbBytesNeeded);
1530 if (dwError != ERROR_SUCCESS)
1531 {
1532 if (dwError == ERROR_INSUFFICIENT_BUFFER)
1533 WARN("RQueryServiceConfigW() failed (Error %lu)\n", dwError);
1534 else
1535 ERR("RQueryServiceConfigW() failed (Error %lu)\n", dwError);
1536 SetLastError(dwError);
1537 return FALSE;
1538 }
1539
1540 /* Adjust the pointers */
1541 if (lpServiceConfig->lpBinaryPathName)
1542 lpServiceConfig->lpBinaryPathName =
1543 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1544 (ULONG_PTR)lpServiceConfig->lpBinaryPathName);
1545
1546 if (lpServiceConfig->lpLoadOrderGroup)
1547 lpServiceConfig->lpLoadOrderGroup =
1548 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1549 (ULONG_PTR)lpServiceConfig->lpLoadOrderGroup);
1550
1551 if (lpServiceConfig->lpDependencies)
1552 lpServiceConfig->lpDependencies =
1553 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1554 (ULONG_PTR)lpServiceConfig->lpDependencies);
1555
1556 if (lpServiceConfig->lpServiceStartName)
1557 lpServiceConfig->lpServiceStartName =
1558 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1559 (ULONG_PTR)lpServiceConfig->lpServiceStartName);
1560
1561 if (lpServiceConfig->lpDisplayName)
1562 lpServiceConfig->lpDisplayName =
1563 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1564 (ULONG_PTR)lpServiceConfig->lpDisplayName);
1565
1566 TRACE("QueryServiceConfigW() done\n");
1567
1568 return TRUE;
1569 }
1570
1571
1572 /**********************************************************************
1573 * QueryServiceConfig2A
1574 *
1575 * @implemented
1576 */
1577 BOOL STDCALL
1578 QueryServiceConfig2A(SC_HANDLE hService,
1579 DWORD dwInfoLevel,
1580 LPBYTE lpBuffer,
1581 DWORD cbBufSize,
1582 LPDWORD pcbBytesNeeded)
1583 {
1584 DWORD dwError;
1585
1586 TRACE("QueryServiceConfig2A(%p, %lu, %p, %lu, %p)\n",
1587 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1588
1589 HandleBind();
1590
1591 /* Call to services.exe using RPC */
1592 dwError = RQueryServiceConfig2A(BindingHandle,
1593 (SC_RPC_HANDLE)hService,
1594 dwInfoLevel,
1595 lpBuffer,
1596 cbBufSize,
1597 pcbBytesNeeded);
1598 if (dwError != ERROR_SUCCESS)
1599 {
1600 ERR("RQueryServiceConfig2A() failed (Error %lu)\n", dwError);
1601 SetLastError(dwError);
1602 return FALSE;
1603 }
1604
1605 switch (dwInfoLevel)
1606 {
1607 case SERVICE_CONFIG_DESCRIPTION:
1608 {
1609 LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpBuffer;
1610
1611 if (lpPtr->lpDescription != NULL)
1612 lpPtr->lpDescription =
1613 (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpDescription);
1614 }
1615 break;
1616
1617 case SERVICE_CONFIG_FAILURE_ACTIONS:
1618 {
1619 LPSERVICE_FAILURE_ACTIONSA lpPtr = (LPSERVICE_FAILURE_ACTIONSA)lpBuffer;
1620
1621 if (lpPtr->lpRebootMsg != NULL)
1622 lpPtr->lpRebootMsg =
1623 (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpRebootMsg);
1624
1625 if (lpPtr->lpCommand != NULL)
1626 lpPtr->lpCommand =
1627 (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpCommand);
1628
1629 if (lpPtr->lpsaActions != NULL)
1630 lpPtr->lpsaActions =
1631 (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
1632 }
1633 break;
1634
1635 default:
1636 ERR("Unknown info level 0x%lx\n", dwInfoLevel);
1637 SetLastError(ERROR_INVALID_PARAMETER);
1638 return FALSE;
1639 }
1640
1641 TRACE("QueryServiceConfig2A() done\n");
1642
1643 return TRUE;
1644 }
1645
1646
1647 /**********************************************************************
1648 * QueryServiceConfig2W
1649 *
1650 * @implemented
1651 */
1652 BOOL STDCALL
1653 QueryServiceConfig2W(SC_HANDLE hService,
1654 DWORD dwInfoLevel,
1655 LPBYTE lpBuffer,
1656 DWORD cbBufSize,
1657 LPDWORD pcbBytesNeeded)
1658 {
1659 DWORD dwError;
1660
1661 TRACE("QueryServiceConfig2W(%p, %lu, %p, %lu, %p)\n",
1662 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1663
1664 HandleBind();
1665
1666 /* Call to services.exe using RPC */
1667 dwError = RQueryServiceConfig2W(BindingHandle,
1668 (SC_RPC_HANDLE)hService,
1669 dwInfoLevel,
1670 lpBuffer,
1671 cbBufSize,
1672 pcbBytesNeeded);
1673 if (dwError != ERROR_SUCCESS)
1674 {
1675 ERR("RQueryServiceConfig2W() failed (Error %lu)\n", dwError);
1676 SetLastError(dwError);
1677 return FALSE;
1678 }
1679
1680 switch (dwInfoLevel)
1681 {
1682 case SERVICE_CONFIG_DESCRIPTION:
1683 {
1684 LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpBuffer;
1685
1686 if (lpPtr->lpDescription != NULL)
1687 lpPtr->lpDescription =
1688 (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpDescription);
1689 }
1690 break;
1691
1692 case SERVICE_CONFIG_FAILURE_ACTIONS:
1693 {
1694 LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer;
1695
1696 if (lpPtr->lpRebootMsg != NULL)
1697 lpPtr->lpRebootMsg =
1698 (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpRebootMsg);
1699
1700 if (lpPtr->lpCommand != NULL)
1701 lpPtr->lpCommand =
1702 (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpCommand);
1703
1704 if (lpPtr->lpsaActions != NULL)
1705 lpPtr->lpsaActions =
1706 (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
1707 }
1708 break;
1709
1710 default:
1711 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
1712 SetLastError(ERROR_INVALID_PARAMETER);
1713 return FALSE;
1714 }
1715
1716 TRACE("QueryServiceConfig2W() done\n");
1717
1718 return TRUE;
1719 }
1720
1721
1722 /**********************************************************************
1723 * QueryServiceLockStatusA
1724 *
1725 * @implemented
1726 */
1727 BOOL STDCALL
1728 QueryServiceLockStatusA(SC_HANDLE hSCManager,
1729 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1730 DWORD cbBufSize,
1731 LPDWORD pcbBytesNeeded)
1732 {
1733 DWORD dwError;
1734
1735 TRACE("QueryServiceLockStatusA() called\n");
1736
1737 HandleBind();
1738
1739 /* Call to services.exe using RPC */
1740 dwError = RQueryServiceLockStatusA(BindingHandle,
1741 (SC_RPC_HANDLE)hSCManager,
1742 lpLockStatus,
1743 cbBufSize,
1744 pcbBytesNeeded);
1745 if (dwError != ERROR_SUCCESS)
1746 {
1747 ERR("RQueryServiceLockStatusA() failed (Error %lu)\n", dwError);
1748 SetLastError(dwError);
1749 return FALSE;
1750 }
1751
1752 if (lpLockStatus->lpLockOwner != NULL)
1753 {
1754 lpLockStatus->lpLockOwner =
1755 (LPSTR)((UINT_PTR)lpLockStatus + (UINT_PTR)lpLockStatus->lpLockOwner);
1756 }
1757
1758 TRACE("QueryServiceLockStatusA() done\n");
1759
1760 return TRUE;
1761 }
1762
1763
1764 /**********************************************************************
1765 * QueryServiceLockStatusW
1766 *
1767 * @implemented
1768 */
1769 BOOL STDCALL
1770 QueryServiceLockStatusW(SC_HANDLE hSCManager,
1771 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1772 DWORD cbBufSize,
1773 LPDWORD pcbBytesNeeded)
1774 {
1775 DWORD dwError;
1776
1777 TRACE("QueryServiceLockStatusW() called\n");
1778
1779 HandleBind();
1780
1781 /* Call to services.exe using RPC */
1782 dwError = RQueryServiceLockStatusW(BindingHandle,
1783 (SC_RPC_HANDLE)hSCManager,
1784 lpLockStatus,
1785 cbBufSize,
1786 pcbBytesNeeded);
1787 if (dwError != ERROR_SUCCESS)
1788 {
1789 ERR("RQueryServiceLockStatusW() failed (Error %lu)\n", dwError);
1790 SetLastError(dwError);
1791 return FALSE;
1792 }
1793
1794 if (lpLockStatus->lpLockOwner != NULL)
1795 {
1796 lpLockStatus->lpLockOwner =
1797 (LPWSTR)((UINT_PTR)lpLockStatus + (UINT_PTR)lpLockStatus->lpLockOwner);
1798 }
1799
1800 TRACE("QueryServiceLockStatusW() done\n");
1801
1802 return TRUE;
1803 }
1804
1805
1806 /**********************************************************************
1807 * QueryServiceObjectSecurity
1808 *
1809 * @implemented
1810 */
1811 BOOL STDCALL
1812 QueryServiceObjectSecurity(SC_HANDLE hService,
1813 SECURITY_INFORMATION dwSecurityInformation,
1814 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
1815 DWORD cbBufSize,
1816 LPDWORD pcbBytesNeeded)
1817 {
1818 DWORD dwError;
1819
1820 TRACE("QueryServiceObjectSecurity(%p, %lu, %p)\n",
1821 hService, dwSecurityInformation, lpSecurityDescriptor);
1822
1823 HandleBind();
1824
1825 /* Call to services.exe using RPC */
1826 dwError = RQueryServiceObjectSecurity(BindingHandle,
1827 (SC_RPC_HANDLE)hService,
1828 dwSecurityInformation,
1829 (LPBYTE)lpSecurityDescriptor,
1830 cbBufSize,
1831 pcbBytesNeeded);
1832 if (dwError != ERROR_SUCCESS)
1833 {
1834 ERR("QueryServiceObjectSecurity() failed (Error %lu)\n", dwError);
1835 SetLastError(dwError);
1836 return FALSE;
1837 }
1838
1839 return TRUE;
1840 }
1841
1842 /**********************************************************************
1843 * SetServiceObjectSecurity
1844 *
1845 * @implemented
1846 */
1847 BOOL STDCALL
1848 SetServiceObjectSecurity(SC_HANDLE hService,
1849 SECURITY_INFORMATION dwSecurityInformation,
1850 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
1851 {
1852 PSECURITY_DESCRIPTOR SelfRelativeSD = NULL;
1853 ULONG Length;
1854 NTSTATUS Status;
1855 DWORD dwError;
1856
1857 Length = 0;
1858 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
1859 SelfRelativeSD,
1860 &Length);
1861 if (Status != STATUS_BUFFER_TOO_SMALL)
1862 {
1863 SetLastError(ERROR_INVALID_PARAMETER);
1864 return FALSE;
1865 }
1866
1867 SelfRelativeSD = HeapAlloc(GetProcessHeap(), 0, Length);
1868 if (SelfRelativeSD == NULL)
1869 {
1870 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1871 return FALSE;
1872 }
1873
1874 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
1875 SelfRelativeSD,
1876 &Length);
1877 if (!NT_SUCCESS(Status))
1878 {
1879 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
1880 SetLastError(RtlNtStatusToDosError(Status));
1881 return FALSE;
1882 }
1883
1884 HandleBind();
1885
1886 /* Call to services.exe using RPC */
1887 dwError = RSetServiceObjectSecurity(BindingHandle,
1888 (SC_RPC_HANDLE)hService,
1889 dwSecurityInformation,
1890 (LPBYTE)SelfRelativeSD,
1891 Length);
1892
1893 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
1894
1895 if (dwError != ERROR_SUCCESS)
1896 {
1897 ERR("RServiceObjectSecurity() failed (Error %lu)\n", dwError);
1898 SetLastError(dwError);
1899 return FALSE;
1900 }
1901
1902 return TRUE;
1903 }
1904
1905
1906 /**********************************************************************
1907 * QueryServiceStatus
1908 *
1909 * @implemented
1910 */
1911 BOOL STDCALL
1912 QueryServiceStatus(SC_HANDLE hService,
1913 LPSERVICE_STATUS lpServiceStatus)
1914 {
1915 DWORD dwError;
1916
1917 TRACE("QueryServiceStatus(%p, %p)\n",
1918 hService, lpServiceStatus);
1919
1920 HandleBind();
1921
1922 /* Call to services.exe using RPC */
1923 dwError = RQueryServiceStatus(BindingHandle,
1924 (SC_RPC_HANDLE)hService,
1925 lpServiceStatus);
1926 if (dwError != ERROR_SUCCESS)
1927 {
1928 ERR("RQueryServiceStatus() failed (Error %lu)\n", dwError);
1929 SetLastError(dwError);
1930 return FALSE;
1931 }
1932
1933 return TRUE;
1934 }
1935
1936
1937 /**********************************************************************
1938 * QueryServiceStatusEx
1939 *
1940 * @implemented
1941 */
1942 BOOL STDCALL
1943 QueryServiceStatusEx(SC_HANDLE hService,
1944 SC_STATUS_TYPE InfoLevel,
1945 LPBYTE lpBuffer,
1946 DWORD cbBufSize,
1947 LPDWORD pcbBytesNeeded)
1948 {
1949 DWORD dwError;
1950
1951 TRACE("QueryServiceStatusEx() called\n");
1952
1953 HandleBind();
1954
1955 /* Call to services.exe using RPC */
1956 dwError = RQueryServiceStatusEx(BindingHandle,
1957 (SC_RPC_HANDLE)hService,
1958 InfoLevel,
1959 lpBuffer,
1960 cbBufSize,
1961 pcbBytesNeeded);
1962 if (dwError != ERROR_SUCCESS)
1963 {
1964 ERR("RQueryServiceStatusEx() failed (Error %lu)\n", dwError);
1965 SetLastError(dwError);
1966 return FALSE;
1967 }
1968
1969 return TRUE;
1970 }
1971
1972
1973 /**********************************************************************
1974 * StartServiceA
1975 *
1976 * @implemented
1977 */
1978 BOOL STDCALL
1979 StartServiceA(SC_HANDLE hService,
1980 DWORD dwNumServiceArgs,
1981 LPCSTR *lpServiceArgVectors)
1982 {
1983 DWORD dwError;
1984
1985 dwError = RStartServiceA(BindingHandle,
1986 (SC_RPC_HANDLE)hService,
1987 dwNumServiceArgs,
1988 (LPSTRING_PTRSA)lpServiceArgVectors);
1989
1990
1991 if (dwError != ERROR_SUCCESS)
1992 {
1993 ERR("RStartServiceA() failed (Error %lu)\n", dwError);
1994 SetLastError(dwError);
1995 return FALSE;
1996 }
1997
1998 return TRUE;
1999 }
2000
2001
2002 /**********************************************************************
2003 * StartServiceW
2004 *
2005 * @implemented
2006 */
2007 BOOL STDCALL
2008 StartServiceW(SC_HANDLE hService,
2009 DWORD dwNumServiceArgs,
2010 LPCWSTR *lpServiceArgVectors)
2011 {
2012 DWORD dwError;
2013
2014 dwError = RStartServiceW(BindingHandle,
2015 (SC_RPC_HANDLE)hService,
2016 dwNumServiceArgs,
2017 (LPSTRING_PTRSW)lpServiceArgVectors);
2018
2019 if (dwError != ERROR_SUCCESS)
2020 {
2021 ERR("RStartServiceW() failed (Error %lu)\n", dwError);
2022 SetLastError(dwError);
2023 return FALSE;
2024 }
2025
2026 return TRUE;
2027 }
2028
2029
2030 /**********************************************************************
2031 * UnlockServiceDatabase
2032 *
2033 * @implemented
2034 */
2035 BOOL STDCALL
2036 UnlockServiceDatabase(SC_LOCK ScLock)
2037 {
2038 DWORD dwError;
2039
2040 TRACE("UnlockServiceDatabase(%x)\n", ScLock);
2041
2042 HandleBind();
2043
2044 /* Call to services.exe using RPC */
2045 dwError = RUnlockServiceDatabase(BindingHandle,
2046 (SC_RPC_LOCK)ScLock);
2047 if (dwError != ERROR_SUCCESS)
2048 {
2049 ERR("RUnlockServiceDatabase() failed (Error %lu)\n", dwError);
2050 SetLastError(dwError);
2051 return FALSE;
2052 }
2053
2054 return TRUE;
2055 }
2056
2057
2058 /**********************************************************************
2059 * NotifyBootConfigStatus
2060 *
2061 * @implemented
2062 */
2063 BOOL STDCALL
2064 NotifyBootConfigStatus(BOOL BootAcceptable)
2065 {
2066 DWORD dwError;
2067
2068 TRACE("NotifyBootConfigStatus()\n");
2069
2070 HandleBind();
2071
2072 /* Call to services.exe using RPC */
2073 dwError = RNotifyBootConfigStatus(BindingHandle,
2074 NULL,
2075 BootAcceptable);
2076 if (dwError != ERROR_SUCCESS)
2077 {
2078 ERR("NotifyBootConfigStatus() failed (Error %lu)\n", dwError);
2079 SetLastError(dwError);
2080 return FALSE;
2081 }
2082
2083 return TRUE;
2084 }
2085
2086 /* EOF */