- fix typo in CreateServiceA
[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
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, -1, 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
613 /* FIXME: Encrypt the password */
614
615 HandleBind();
616
617 /* Call to services.exe using RPC */
618 dwError = RCreateServiceW(BindingHandle,
619 (SC_RPC_HANDLE)hSCManager,
620 (LPWSTR)lpServiceName,
621 (LPWSTR)lpDisplayName,
622 dwDesiredAccess,
623 dwServiceType,
624 dwStartType,
625 dwErrorControl,
626 (LPWSTR)lpBinaryPathName,
627 (LPWSTR)lpLoadOrderGroup,
628 lpdwTagId,
629 (LPBYTE)lpDependencies,
630 dwDependenciesLength,
631 (LPWSTR)lpServiceStartName,
632 NULL, /* FIXME: lpPassword */
633 0, /* FIXME: dwPasswordLength */
634 (SC_RPC_HANDLE *)&hService);
635 if (dwError != ERROR_SUCCESS)
636 {
637 ERR("RCreateServiceW() failed (Error %lu)\n", dwError);
638 SetLastError(dwError);
639 return NULL;
640 }
641
642 return hService;
643 }
644
645
646 /**********************************************************************
647 * DeleteService
648 *
649 * @implemented
650 */
651 BOOL STDCALL
652 DeleteService(SC_HANDLE hService)
653 {
654 DWORD dwError;
655
656 TRACE("DeleteService(%x)\n", hService);
657
658 HandleBind();
659
660 /* Call to services.exe using RPC */
661 dwError = RDeleteService(BindingHandle,
662 (SC_RPC_HANDLE)hService);
663 if (dwError != ERROR_SUCCESS)
664 {
665 ERR("RDeleteService() failed (Error %lu)\n", dwError);
666 SetLastError(dwError);
667 return FALSE;
668 }
669
670 return TRUE;
671 }
672
673
674 /**********************************************************************
675 * EnumDependentServicesA
676 *
677 * @implemented
678 */
679 BOOL STDCALL
680 EnumDependentServicesA(SC_HANDLE hService,
681 DWORD dwServiceState,
682 LPENUM_SERVICE_STATUSA lpServices,
683 DWORD cbBufSize,
684 LPDWORD pcbBytesNeeded,
685 LPDWORD lpServicesReturned)
686 {
687 LPENUM_SERVICE_STATUSA lpStatusPtr;
688 DWORD dwError = ERROR_SUCCESS;
689 DWORD dwCount;
690
691 TRACE("EnumServicesStatusA() called\n");
692
693 HandleBind();
694
695 dwError = REnumDependentServicesA(BindingHandle,
696 (SC_RPC_HANDLE)hService,
697 dwServiceState,
698 (LPBYTE)lpServices,
699 cbBufSize,
700 pcbBytesNeeded,
701 lpServicesReturned);
702
703 lpStatusPtr = (LPENUM_SERVICE_STATUSA)lpServices;
704 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
705 {
706 if (lpStatusPtr->lpServiceName)
707 lpStatusPtr->lpServiceName =
708 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
709
710 if (lpStatusPtr->lpDisplayName)
711 lpStatusPtr->lpDisplayName =
712 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
713
714 lpStatusPtr++;
715 }
716
717 if (dwError != ERROR_SUCCESS)
718 {
719 ERR("REnumDependentServicesA() failed (Error %lu)\n", dwError);
720 SetLastError(dwError);
721 return FALSE;
722 }
723
724 TRACE("EnumDependentServicesA() done\n");
725
726 return TRUE;
727 }
728
729
730 /**********************************************************************
731 * EnumDependentServicesW
732 *
733 * @implemented
734 */
735 BOOL STDCALL
736 EnumDependentServicesW(SC_HANDLE hService,
737 DWORD dwServiceState,
738 LPENUM_SERVICE_STATUSW lpServices,
739 DWORD cbBufSize,
740 LPDWORD pcbBytesNeeded,
741 LPDWORD lpServicesReturned)
742 {
743 LPENUM_SERVICE_STATUSW lpStatusPtr;
744 DWORD dwError = ERROR_SUCCESS;
745 DWORD dwCount;
746
747 TRACE("EnumServicesStatusW() called\n");
748
749 HandleBind();
750
751 dwError = REnumDependentServicesW(BindingHandle,
752 (SC_RPC_HANDLE)hService,
753 dwServiceState,
754 (LPBYTE)lpServices,
755 cbBufSize,
756 pcbBytesNeeded,
757 lpServicesReturned);
758
759 lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpServices;
760 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
761 {
762 if (lpStatusPtr->lpServiceName)
763 lpStatusPtr->lpServiceName =
764 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
765
766 if (lpStatusPtr->lpDisplayName)
767 lpStatusPtr->lpDisplayName =
768 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
769
770 lpStatusPtr++;
771 }
772
773 if (dwError != ERROR_SUCCESS)
774 {
775 ERR("REnumDependentServicesW() failed (Error %lu)\n", dwError);
776 SetLastError(dwError);
777 return FALSE;
778 }
779
780 TRACE("EnumDependentServicesW() done\n");
781
782 return TRUE;
783 }
784
785
786 /**********************************************************************
787 * EnumServiceGroupW
788 *
789 * @unimplemented
790 */
791 BOOL
792 STDCALL
793 EnumServiceGroupW(
794 SC_HANDLE hSCManager,
795 DWORD dwServiceType,
796 DWORD dwServiceState,
797 LPENUM_SERVICE_STATUSW lpServices,
798 DWORD cbBufSize,
799 LPDWORD pcbBytesNeeded,
800 LPDWORD lpServicesReturned,
801 LPDWORD lpResumeHandle,
802 LPCWSTR lpGroup)
803 {
804 FIXME("EnumServiceGroupW is unimplemented\n");
805 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
806 return FALSE;
807 }
808
809
810 /**********************************************************************
811 * EnumServicesStatusA
812 *
813 * @implemented
814 */
815 BOOL STDCALL
816 EnumServicesStatusA(SC_HANDLE hSCManager,
817 DWORD dwServiceType,
818 DWORD dwServiceState,
819 LPENUM_SERVICE_STATUSA lpServices,
820 DWORD cbBufSize,
821 LPDWORD pcbBytesNeeded,
822 LPDWORD lpServicesReturned,
823 LPDWORD lpResumeHandle)
824 {
825 LPENUM_SERVICE_STATUSA lpStatusPtr;
826 DWORD dwError = ERROR_SUCCESS;
827 DWORD dwCount;
828
829 TRACE("EnumServicesStatusA() called\n");
830
831 HandleBind();
832
833 dwError = REnumServicesStatusA(BindingHandle,
834 (SC_RPC_HANDLE)hSCManager,
835 dwServiceType,
836 dwServiceState,
837 (LPBYTE)lpServices,
838 cbBufSize,
839 pcbBytesNeeded,
840 lpServicesReturned,
841 lpResumeHandle);
842
843 lpStatusPtr = (LPENUM_SERVICE_STATUSA)lpServices;
844 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
845 {
846 if (lpStatusPtr->lpServiceName)
847 lpStatusPtr->lpServiceName =
848 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
849
850 if (lpStatusPtr->lpDisplayName)
851 lpStatusPtr->lpDisplayName =
852 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
853
854 lpStatusPtr++;
855 }
856
857 if (dwError != ERROR_SUCCESS)
858 {
859 ERR("REnumServicesStatusA() failed (Error %lu)\n", dwError);
860 SetLastError(dwError);
861 return FALSE;
862 }
863
864 TRACE("EnumServicesStatusA() done\n");
865
866 return TRUE;
867 }
868
869
870 /**********************************************************************
871 * EnumServicesStatusW
872 *
873 * @implemented
874 */
875 BOOL STDCALL
876 EnumServicesStatusW(SC_HANDLE hSCManager,
877 DWORD dwServiceType,
878 DWORD dwServiceState,
879 LPENUM_SERVICE_STATUSW lpServices,
880 DWORD cbBufSize,
881 LPDWORD pcbBytesNeeded,
882 LPDWORD lpServicesReturned,
883 LPDWORD lpResumeHandle)
884 {
885 LPENUM_SERVICE_STATUSW lpStatusPtr;
886 DWORD dwError = ERROR_SUCCESS;
887 DWORD dwCount;
888
889 TRACE("EnumServicesStatusW() called\n");
890
891 HandleBind();
892
893 dwError = REnumServicesStatusW(BindingHandle,
894 (SC_RPC_HANDLE)hSCManager,
895 dwServiceType,
896 dwServiceState,
897 (LPBYTE)lpServices,
898 cbBufSize,
899 pcbBytesNeeded,
900 lpServicesReturned,
901 lpResumeHandle);
902
903 lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpServices;
904 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
905 {
906 if (lpStatusPtr->lpServiceName)
907 lpStatusPtr->lpServiceName =
908 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
909
910 if (lpStatusPtr->lpDisplayName)
911 lpStatusPtr->lpDisplayName =
912 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
913
914 lpStatusPtr++;
915 }
916
917 if (dwError != ERROR_SUCCESS)
918 {
919 ERR("REnumServicesStatusW() failed (Error %lu)\n", dwError);
920 SetLastError(dwError);
921 return FALSE;
922 }
923
924 TRACE("EnumServicesStatusW() done\n");
925
926 return TRUE;
927 }
928
929
930 /**********************************************************************
931 * EnumServicesStatusExA
932 *
933 * @implemented
934 */
935 BOOL STDCALL
936 EnumServicesStatusExA(SC_HANDLE hSCManager,
937 SC_ENUM_TYPE InfoLevel,
938 DWORD dwServiceType,
939 DWORD dwServiceState,
940 LPBYTE lpServices,
941 DWORD cbBufSize,
942 LPDWORD pcbBytesNeeded,
943 LPDWORD lpServicesReturned,
944 LPDWORD lpResumeHandle,
945 LPCSTR pszGroupName)
946 {
947 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtr;
948 DWORD dwError = ERROR_SUCCESS;
949 DWORD dwCount;
950
951 TRACE("EnumServicesStatusExA() called\n");
952
953 HandleBind();
954
955 dwError = REnumServicesStatusExA(BindingHandle,
956 (SC_RPC_HANDLE)hSCManager,
957 InfoLevel,
958 dwServiceType,
959 dwServiceState,
960 (LPBYTE)lpServices,
961 cbBufSize,
962 pcbBytesNeeded,
963 lpServicesReturned,
964 lpResumeHandle,
965 (LPSTR)pszGroupName);
966
967 if (dwError == ERROR_MORE_DATA)
968 {
969 WARN("Required buffer size %ul\n", *pcbBytesNeeded);
970 SetLastError(dwError);
971 return FALSE;
972 }
973 else if (dwError == ERROR_SUCCESS)
974 {
975 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSA)lpServices;
976 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
977 {
978 if (lpStatusPtr->lpServiceName)
979 lpStatusPtr->lpServiceName =
980 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
981
982 if (lpStatusPtr->lpDisplayName)
983 lpStatusPtr->lpDisplayName =
984 (LPSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
985
986 lpStatusPtr++;
987 }
988 }
989 else
990 {
991 ERR("REnumServicesStatusExA() failed (Error %lu)\n", dwError);
992 SetLastError(dwError);
993 return FALSE;
994 }
995
996 TRACE("EnumServicesStatusExA() done\n");
997
998 return TRUE;
999 }
1000
1001
1002 /**********************************************************************
1003 * EnumServicesStatusExW
1004 *
1005 * @implemented
1006 */
1007 BOOL STDCALL
1008 EnumServicesStatusExW(SC_HANDLE hSCManager,
1009 SC_ENUM_TYPE InfoLevel,
1010 DWORD dwServiceType,
1011 DWORD dwServiceState,
1012 LPBYTE lpServices,
1013 DWORD cbBufSize,
1014 LPDWORD pcbBytesNeeded,
1015 LPDWORD lpServicesReturned,
1016 LPDWORD lpResumeHandle,
1017 LPCWSTR pszGroupName)
1018 {
1019 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
1020 DWORD dwError = ERROR_SUCCESS;
1021 DWORD dwCount;
1022
1023 TRACE("EnumServicesStatusExW() called\n");
1024
1025 HandleBind();
1026
1027 dwError = REnumServicesStatusExW(BindingHandle,
1028 (SC_RPC_HANDLE)hSCManager,
1029 InfoLevel,
1030 dwServiceType,
1031 dwServiceState,
1032 (LPBYTE)lpServices,
1033 cbBufSize,
1034 pcbBytesNeeded,
1035 lpServicesReturned,
1036 lpResumeHandle,
1037 (LPWSTR)pszGroupName);
1038
1039 if (dwError == ERROR_MORE_DATA)
1040 {
1041 WARN("Required buffer size %ul\n", *pcbBytesNeeded);
1042 SetLastError(dwError);
1043 return FALSE;
1044 }
1045 else if (dwError == ERROR_SUCCESS)
1046 {
1047 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices;
1048 for (dwCount = 0; dwCount < *lpServicesReturned; dwCount++)
1049 {
1050 if (lpStatusPtr->lpServiceName)
1051 lpStatusPtr->lpServiceName =
1052 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpServiceName);
1053
1054 if (lpStatusPtr->lpDisplayName)
1055 lpStatusPtr->lpDisplayName =
1056 (LPWSTR)((ULONG_PTR)lpServices + (ULONG_PTR)lpStatusPtr->lpDisplayName);
1057
1058 lpStatusPtr++;
1059 }
1060 }
1061 else
1062 {
1063 ERR("REnumServicesStatusExW() failed (Error %lu)\n", dwError);
1064 SetLastError(dwError);
1065 return FALSE;
1066 }
1067
1068 TRACE("EnumServicesStatusExW() done\n");
1069
1070 return TRUE;
1071 }
1072
1073
1074 /**********************************************************************
1075 * GetServiceDisplayNameA
1076 *
1077 * @implemented
1078 */
1079 BOOL STDCALL
1080 GetServiceDisplayNameA(SC_HANDLE hSCManager,
1081 LPCSTR lpServiceName,
1082 LPSTR lpDisplayName,
1083 LPDWORD lpcchBuffer)
1084 {
1085 DWORD dwError;
1086
1087 TRACE("GetServiceDisplayNameA() called\n");
1088
1089 HandleBind();
1090
1091 dwError = RGetServiceDisplayNameA(BindingHandle,
1092 (SC_RPC_HANDLE)hSCManager,
1093 (LPSTR)lpServiceName,
1094 lpDisplayName,
1095 lpcchBuffer);
1096 if (dwError != ERROR_SUCCESS)
1097 {
1098 ERR("RGetServiceDisplayNameA() failed (Error %lu)\n", dwError);
1099 SetLastError(dwError);
1100 return FALSE;
1101 }
1102
1103 (*lpcchBuffer)--;
1104
1105 return TRUE;
1106 }
1107
1108
1109 /**********************************************************************
1110 * GetServiceDisplayNameW
1111 *
1112 * @implemented
1113 */
1114 BOOL STDCALL
1115 GetServiceDisplayNameW(SC_HANDLE hSCManager,
1116 LPCWSTR lpServiceName,
1117 LPWSTR lpDisplayName,
1118 LPDWORD lpcchBuffer)
1119 {
1120 DWORD dwError;
1121
1122 TRACE("GetServiceDisplayNameW() called\n");
1123
1124 HandleBind();
1125
1126 dwError = RGetServiceDisplayNameW(BindingHandle,
1127 (SC_RPC_HANDLE)hSCManager,
1128 (LPWSTR)lpServiceName,
1129 lpDisplayName,
1130 lpcchBuffer);
1131 if (dwError != ERROR_SUCCESS)
1132 {
1133 ERR("RGetServiceDisplayNameW() failed (Error %lu)\n", dwError);
1134 SetLastError(dwError);
1135 return FALSE;
1136 }
1137
1138 (*lpcchBuffer)--;
1139
1140 return TRUE;
1141 }
1142
1143
1144 /**********************************************************************
1145 * GetServiceKeyNameA
1146 *
1147 * @implemented
1148 */
1149 BOOL STDCALL
1150 GetServiceKeyNameA(SC_HANDLE hSCManager,
1151 LPCSTR lpDisplayName,
1152 LPSTR lpServiceName,
1153 LPDWORD lpcchBuffer)
1154 {
1155 DWORD dwError;
1156
1157 TRACE("GetServiceKeyNameA() called\n");
1158
1159 HandleBind();
1160
1161 dwError = RGetServiceKeyNameA(BindingHandle,
1162 (SC_RPC_HANDLE)hSCManager,
1163 (LPSTR)lpDisplayName,
1164 lpServiceName,
1165 lpcchBuffer);
1166 if (dwError != ERROR_SUCCESS)
1167 {
1168 ERR("RGetServiceKeyNameA() failed (Error %lu)\n", dwError);
1169 SetLastError(dwError);
1170 return FALSE;
1171 }
1172
1173 (*lpcchBuffer)--;
1174
1175 return TRUE;
1176 }
1177
1178
1179 /**********************************************************************
1180 * GetServiceKeyNameW
1181 *
1182 * @implemented
1183 */
1184 BOOL STDCALL
1185 GetServiceKeyNameW(SC_HANDLE hSCManager,
1186 LPCWSTR lpDisplayName,
1187 LPWSTR lpServiceName,
1188 LPDWORD lpcchBuffer)
1189 {
1190 DWORD dwError;
1191
1192 TRACE("GetServiceKeyNameW() called\n");
1193
1194 HandleBind();
1195
1196 dwError = RGetServiceKeyNameW(BindingHandle,
1197 (SC_RPC_HANDLE)hSCManager,
1198 (LPWSTR)lpDisplayName,
1199 lpServiceName,
1200 lpcchBuffer);
1201 if (dwError != ERROR_SUCCESS)
1202 {
1203 ERR("RGetServiceKeyNameW() failed (Error %lu)\n", dwError);
1204 SetLastError(dwError);
1205 return FALSE;
1206 }
1207
1208 (*lpcchBuffer)--;
1209
1210 return TRUE;
1211 }
1212
1213
1214 /**********************************************************************
1215 * LockServiceDatabase
1216 *
1217 * @implemented
1218 */
1219 SC_LOCK STDCALL
1220 LockServiceDatabase(SC_HANDLE hSCManager)
1221 {
1222 SC_LOCK hLock;
1223 DWORD dwError;
1224
1225 TRACE("LockServiceDatabase(%x)\n", hSCManager);
1226
1227 HandleBind();
1228
1229 /* Call to services.exe using RPC */
1230 dwError = RLockServiceDatabase(BindingHandle,
1231 (SC_RPC_HANDLE)hSCManager,
1232 (SC_RPC_LOCK *)&hLock);
1233 if (dwError != ERROR_SUCCESS)
1234 {
1235 ERR("RLockServiceDatabase() failed (Error %lu)\n", dwError);
1236 SetLastError(dwError);
1237 return NULL;
1238 }
1239
1240 TRACE("hLock = %p\n", hLock);
1241
1242 return hLock;
1243 }
1244
1245
1246 static VOID
1247 WaitForSCManager(VOID)
1248 {
1249 HANDLE hEvent;
1250
1251 TRACE("WaitForSCManager() called\n");
1252
1253 /* Try to open the existing event */
1254 hEvent = OpenEventW(SYNCHRONIZE,
1255 FALSE,
1256 L"SvcctrlStartEvent_A3752DX");
1257 if (hEvent == NULL)
1258 {
1259 if (GetLastError() != ERROR_FILE_NOT_FOUND)
1260 return;
1261
1262 /* Try to create a new event */
1263 hEvent = CreateEventW(NULL,
1264 TRUE,
1265 FALSE,
1266 L"SvcctrlStartEvent_A3752DX");
1267 if (hEvent == NULL)
1268 {
1269 /* Try to open the existing event again */
1270 hEvent = OpenEventW(SYNCHRONIZE,
1271 FALSE,
1272 L"SvcctrlStartEvent_A3752DX");
1273 if (hEvent == NULL)
1274 return;
1275 }
1276 }
1277
1278 /* Wait for 3 minutes */
1279 WaitForSingleObject(hEvent, 180000);
1280 CloseHandle(hEvent);
1281
1282 TRACE("ScmWaitForSCManager() done\n");
1283 }
1284
1285
1286 /**********************************************************************
1287 * OpenSCManagerA
1288 *
1289 * @implemented
1290 */
1291 SC_HANDLE STDCALL
1292 OpenSCManagerA(LPCSTR lpMachineName,
1293 LPCSTR lpDatabaseName,
1294 DWORD dwDesiredAccess)
1295 {
1296 SC_HANDLE hScm = NULL;
1297 DWORD dwError;
1298
1299 TRACE("OpenSCManagerA(%s, %s, %lx)\n",
1300 lpMachineName, lpDatabaseName, dwDesiredAccess);
1301
1302 WaitForSCManager();
1303
1304 HandleBind();
1305
1306 /* Call to services.exe using RPC */
1307 dwError = ROpenSCManagerA(BindingHandle,
1308 (LPSTR)lpMachineName,
1309 (LPSTR)lpDatabaseName,
1310 dwDesiredAccess,
1311 (SC_RPC_HANDLE *)&hScm);
1312 if (dwError != ERROR_SUCCESS)
1313 {
1314 ERR("ROpenSCManagerA() failed (Error %lu)\n", dwError);
1315 SetLastError(dwError);
1316 return NULL;
1317 }
1318
1319 TRACE("hScm = %p\n", hScm);
1320
1321 return hScm;
1322 }
1323
1324
1325 /**********************************************************************
1326 * OpenSCManagerW
1327 *
1328 * @implemented
1329 */
1330 SC_HANDLE STDCALL
1331 OpenSCManagerW(LPCWSTR lpMachineName,
1332 LPCWSTR lpDatabaseName,
1333 DWORD dwDesiredAccess)
1334 {
1335 SC_HANDLE hScm = NULL;
1336 DWORD dwError;
1337
1338 TRACE("OpenSCManagerW(%S, %S, %lx)\n",
1339 lpMachineName, lpDatabaseName, dwDesiredAccess);
1340
1341 WaitForSCManager();
1342
1343 HandleBind();
1344
1345 /* Call to services.exe using RPC */
1346 dwError = ROpenSCManagerW(BindingHandle,
1347 (LPWSTR)lpMachineName,
1348 (LPWSTR)lpDatabaseName,
1349 dwDesiredAccess,
1350 (SC_RPC_HANDLE *)&hScm);
1351 if (dwError != ERROR_SUCCESS)
1352 {
1353 ERR("ROpenSCManagerW() failed (Error %lu)\n", dwError);
1354 SetLastError(dwError);
1355 return NULL;
1356 }
1357
1358 TRACE("hScm = %p\n", hScm);
1359
1360 return hScm;
1361 }
1362
1363
1364 /**********************************************************************
1365 * OpenServiceA
1366 *
1367 * @implemented
1368 */
1369 SC_HANDLE STDCALL
1370 OpenServiceA(SC_HANDLE hSCManager,
1371 LPCSTR lpServiceName,
1372 DWORD dwDesiredAccess)
1373 {
1374 SC_HANDLE hService = NULL;
1375 DWORD dwError;
1376
1377 TRACE("OpenServiceA(%p, %s, %lx)\n",
1378 hSCManager, lpServiceName, dwDesiredAccess);
1379
1380 HandleBind();
1381
1382 /* Call to services.exe using RPC */
1383 dwError = ROpenServiceA(BindingHandle,
1384 (SC_RPC_HANDLE)hSCManager,
1385 (LPSTR)lpServiceName,
1386 dwDesiredAccess,
1387 (SC_RPC_HANDLE *)&hService);
1388 if (dwError != ERROR_SUCCESS)
1389 {
1390 ERR("ROpenServiceA() failed (Error %lu)\n", dwError);
1391 SetLastError(dwError);
1392 return NULL;
1393 }
1394
1395 TRACE("hService = %p\n", hService);
1396
1397 return hService;
1398 }
1399
1400
1401 /**********************************************************************
1402 * OpenServiceW
1403 *
1404 * @implemented
1405 */
1406 SC_HANDLE STDCALL
1407 OpenServiceW(SC_HANDLE hSCManager,
1408 LPCWSTR lpServiceName,
1409 DWORD dwDesiredAccess)
1410 {
1411 SC_HANDLE hService = NULL;
1412 DWORD dwError;
1413
1414 TRACE("OpenServiceW(%p, %S, %lx)\n",
1415 hSCManager, lpServiceName, dwDesiredAccess);
1416
1417 HandleBind();
1418
1419 /* Call to services.exe using RPC */
1420 dwError = ROpenServiceW(BindingHandle,
1421 (SC_RPC_HANDLE)hSCManager,
1422 (LPWSTR)lpServiceName,
1423 dwDesiredAccess,
1424 (SC_RPC_HANDLE *)&hService);
1425 if (dwError != ERROR_SUCCESS)
1426 {
1427 if (dwError == ERROR_SERVICE_DOES_NOT_EXIST)
1428 WARN("ROpenServiceW() failed (Error %lu)\n", dwError);
1429 else
1430 ERR("ROpenServiceW() failed (Error %lu)\n", dwError);
1431 SetLastError(dwError);
1432 return NULL;
1433 }
1434
1435 TRACE("hService = %p\n", hService);
1436
1437 return hService;
1438 }
1439
1440
1441 /**********************************************************************
1442 * QueryServiceConfigA
1443 *
1444 * @implemented
1445 */
1446 BOOL STDCALL
1447 QueryServiceConfigA(SC_HANDLE hService,
1448 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
1449 DWORD cbBufSize,
1450 LPDWORD pcbBytesNeeded)
1451 {
1452 DWORD dwError;
1453
1454 TRACE("QueryServiceConfigA(%p, %p, %lu, %p)\n",
1455 hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
1456
1457 HandleBind();
1458
1459 /* Call to services.exe using RPC */
1460 dwError = RQueryServiceConfigA(BindingHandle,
1461 (SC_RPC_HANDLE)hService,
1462 lpServiceConfig,
1463 cbBufSize,
1464 pcbBytesNeeded);
1465 if (dwError != ERROR_SUCCESS)
1466 {
1467 ERR("RQueryServiceConfigA() failed (Error %lu)\n", dwError);
1468 SetLastError(dwError);
1469 return FALSE;
1470 }
1471
1472 /* Adjust the pointers */
1473 if (lpServiceConfig->lpBinaryPathName)
1474 lpServiceConfig->lpBinaryPathName =
1475 (LPSTR)((ULONG_PTR)lpServiceConfig +
1476 (ULONG_PTR)lpServiceConfig->lpBinaryPathName);
1477
1478 if (lpServiceConfig->lpLoadOrderGroup)
1479 lpServiceConfig->lpLoadOrderGroup =
1480 (LPSTR)((ULONG_PTR)lpServiceConfig +
1481 (ULONG_PTR)lpServiceConfig->lpLoadOrderGroup);
1482
1483 if (lpServiceConfig->lpDependencies)
1484 lpServiceConfig->lpDependencies =
1485 (LPSTR)((ULONG_PTR)lpServiceConfig +
1486 (ULONG_PTR)lpServiceConfig->lpDependencies);
1487
1488 if (lpServiceConfig->lpServiceStartName)
1489 lpServiceConfig->lpServiceStartName =
1490 (LPSTR)((ULONG_PTR)lpServiceConfig +
1491 (ULONG_PTR)lpServiceConfig->lpServiceStartName);
1492
1493 if (lpServiceConfig->lpDisplayName)
1494 lpServiceConfig->lpDisplayName =
1495 (LPSTR)((ULONG_PTR)lpServiceConfig +
1496 (ULONG_PTR)lpServiceConfig->lpDisplayName);
1497
1498 TRACE("QueryServiceConfigA() done\n");
1499
1500 return TRUE;
1501 }
1502
1503
1504 /**********************************************************************
1505 * QueryServiceConfigW
1506 *
1507 * @implemented
1508 */
1509 BOOL STDCALL
1510 QueryServiceConfigW(SC_HANDLE hService,
1511 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
1512 DWORD cbBufSize,
1513 LPDWORD pcbBytesNeeded)
1514 {
1515 DWORD dwError;
1516
1517 TRACE("QueryServiceConfigW(%p, %p, %lu, %p)\n",
1518 hService, lpServiceConfig, cbBufSize, pcbBytesNeeded);
1519
1520 HandleBind();
1521
1522 /* Call to services.exe using RPC */
1523 dwError = RQueryServiceConfigW(BindingHandle,
1524 (SC_RPC_HANDLE)hService,
1525 (LPBYTE)lpServiceConfig,
1526 cbBufSize,
1527 pcbBytesNeeded);
1528 if (dwError != ERROR_SUCCESS)
1529 {
1530 if (dwError == ERROR_INSUFFICIENT_BUFFER)
1531 WARN("RQueryServiceConfigW() failed (Error %lu)\n", dwError);
1532 else
1533 ERR("RQueryServiceConfigW() failed (Error %lu)\n", dwError);
1534 SetLastError(dwError);
1535 return FALSE;
1536 }
1537
1538 /* Adjust the pointers */
1539 if (lpServiceConfig->lpBinaryPathName)
1540 lpServiceConfig->lpBinaryPathName =
1541 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1542 (ULONG_PTR)lpServiceConfig->lpBinaryPathName);
1543
1544 if (lpServiceConfig->lpLoadOrderGroup)
1545 lpServiceConfig->lpLoadOrderGroup =
1546 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1547 (ULONG_PTR)lpServiceConfig->lpLoadOrderGroup);
1548
1549 if (lpServiceConfig->lpDependencies)
1550 lpServiceConfig->lpDependencies =
1551 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1552 (ULONG_PTR)lpServiceConfig->lpDependencies);
1553
1554 if (lpServiceConfig->lpServiceStartName)
1555 lpServiceConfig->lpServiceStartName =
1556 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1557 (ULONG_PTR)lpServiceConfig->lpServiceStartName);
1558
1559 if (lpServiceConfig->lpDisplayName)
1560 lpServiceConfig->lpDisplayName =
1561 (LPWSTR)((ULONG_PTR)lpServiceConfig +
1562 (ULONG_PTR)lpServiceConfig->lpDisplayName);
1563
1564 TRACE("QueryServiceConfigW() done\n");
1565
1566 return TRUE;
1567 }
1568
1569
1570 /**********************************************************************
1571 * QueryServiceConfig2A
1572 *
1573 * @implemented
1574 */
1575 BOOL STDCALL
1576 QueryServiceConfig2A(SC_HANDLE hService,
1577 DWORD dwInfoLevel,
1578 LPBYTE lpBuffer,
1579 DWORD cbBufSize,
1580 LPDWORD pcbBytesNeeded)
1581 {
1582 DWORD dwError;
1583
1584 TRACE("QueryServiceConfig2A(%p, %lu, %p, %lu, %p)\n",
1585 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1586
1587 HandleBind();
1588
1589 /* Call to services.exe using RPC */
1590 dwError = RQueryServiceConfig2A(BindingHandle,
1591 (SC_RPC_HANDLE)hService,
1592 dwInfoLevel,
1593 lpBuffer,
1594 cbBufSize,
1595 pcbBytesNeeded);
1596 if (dwError != ERROR_SUCCESS)
1597 {
1598 ERR("RQueryServiceConfig2A() failed (Error %lu)\n", dwError);
1599 SetLastError(dwError);
1600 return FALSE;
1601 }
1602
1603 switch (dwInfoLevel)
1604 {
1605 case SERVICE_CONFIG_DESCRIPTION:
1606 {
1607 LPSERVICE_DESCRIPTIONA lpPtr = (LPSERVICE_DESCRIPTIONA)lpBuffer;
1608
1609 if (lpPtr->lpDescription != NULL)
1610 lpPtr->lpDescription =
1611 (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpDescription);
1612 }
1613 break;
1614
1615 case SERVICE_CONFIG_FAILURE_ACTIONS:
1616 {
1617 LPSERVICE_FAILURE_ACTIONSA lpPtr = (LPSERVICE_FAILURE_ACTIONSA)lpBuffer;
1618
1619 if (lpPtr->lpRebootMsg != NULL)
1620 lpPtr->lpRebootMsg =
1621 (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpRebootMsg);
1622
1623 if (lpPtr->lpCommand != NULL)
1624 lpPtr->lpCommand =
1625 (LPSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpCommand);
1626
1627 if (lpPtr->lpsaActions != NULL)
1628 lpPtr->lpsaActions =
1629 (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
1630 }
1631 break;
1632
1633 default:
1634 ERR("Unknown info level 0x%lx\n", dwInfoLevel);
1635 SetLastError(ERROR_INVALID_PARAMETER);
1636 return FALSE;
1637 }
1638
1639 TRACE("QueryServiceConfig2A() done\n");
1640
1641 return TRUE;
1642 }
1643
1644
1645 /**********************************************************************
1646 * QueryServiceConfig2W
1647 *
1648 * @implemented
1649 */
1650 BOOL STDCALL
1651 QueryServiceConfig2W(SC_HANDLE hService,
1652 DWORD dwInfoLevel,
1653 LPBYTE lpBuffer,
1654 DWORD cbBufSize,
1655 LPDWORD pcbBytesNeeded)
1656 {
1657 DWORD dwError;
1658
1659 TRACE("QueryServiceConfig2W(%p, %lu, %p, %lu, %p)\n",
1660 hService, dwInfoLevel, lpBuffer, cbBufSize, pcbBytesNeeded);
1661
1662 HandleBind();
1663
1664 /* Call to services.exe using RPC */
1665 dwError = RQueryServiceConfig2W(BindingHandle,
1666 (SC_RPC_HANDLE)hService,
1667 dwInfoLevel,
1668 lpBuffer,
1669 cbBufSize,
1670 pcbBytesNeeded);
1671 if (dwError != ERROR_SUCCESS)
1672 {
1673 ERR("RQueryServiceConfig2W() failed (Error %lu)\n", dwError);
1674 SetLastError(dwError);
1675 return FALSE;
1676 }
1677
1678 switch (dwInfoLevel)
1679 {
1680 case SERVICE_CONFIG_DESCRIPTION:
1681 {
1682 LPSERVICE_DESCRIPTIONW lpPtr = (LPSERVICE_DESCRIPTIONW)lpBuffer;
1683
1684 if (lpPtr->lpDescription != NULL)
1685 lpPtr->lpDescription =
1686 (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpDescription);
1687 }
1688 break;
1689
1690 case SERVICE_CONFIG_FAILURE_ACTIONS:
1691 {
1692 LPSERVICE_FAILURE_ACTIONSW lpPtr = (LPSERVICE_FAILURE_ACTIONSW)lpBuffer;
1693
1694 if (lpPtr->lpRebootMsg != NULL)
1695 lpPtr->lpRebootMsg =
1696 (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpRebootMsg);
1697
1698 if (lpPtr->lpCommand != NULL)
1699 lpPtr->lpCommand =
1700 (LPWSTR)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpCommand);
1701
1702 if (lpPtr->lpsaActions != NULL)
1703 lpPtr->lpsaActions =
1704 (SC_ACTION*)((UINT_PTR)lpPtr + (UINT_PTR)lpPtr->lpsaActions);
1705 }
1706 break;
1707
1708 default:
1709 WARN("Unknown info level 0x%lx\n", dwInfoLevel);
1710 SetLastError(ERROR_INVALID_PARAMETER);
1711 return FALSE;
1712 }
1713
1714 TRACE("QueryServiceConfig2W() done\n");
1715
1716 return TRUE;
1717 }
1718
1719
1720 /**********************************************************************
1721 * QueryServiceLockStatusA
1722 *
1723 * @implemented
1724 */
1725 BOOL STDCALL
1726 QueryServiceLockStatusA(SC_HANDLE hSCManager,
1727 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
1728 DWORD cbBufSize,
1729 LPDWORD pcbBytesNeeded)
1730 {
1731 DWORD dwError;
1732
1733 TRACE("QueryServiceLockStatusA() called\n");
1734
1735 HandleBind();
1736
1737 /* Call to services.exe using RPC */
1738 dwError = RQueryServiceLockStatusA(BindingHandle,
1739 (SC_RPC_HANDLE)hSCManager,
1740 lpLockStatus,
1741 cbBufSize,
1742 pcbBytesNeeded);
1743 if (dwError != ERROR_SUCCESS)
1744 {
1745 ERR("RQueryServiceLockStatusA() failed (Error %lu)\n", dwError);
1746 SetLastError(dwError);
1747 return FALSE;
1748 }
1749
1750 if (lpLockStatus->lpLockOwner != NULL)
1751 {
1752 lpLockStatus->lpLockOwner =
1753 (LPSTR)((UINT_PTR)lpLockStatus + (UINT_PTR)lpLockStatus->lpLockOwner);
1754 }
1755
1756 TRACE("QueryServiceLockStatusA() done\n");
1757
1758 return TRUE;
1759 }
1760
1761
1762 /**********************************************************************
1763 * QueryServiceLockStatusW
1764 *
1765 * @implemented
1766 */
1767 BOOL STDCALL
1768 QueryServiceLockStatusW(SC_HANDLE hSCManager,
1769 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
1770 DWORD cbBufSize,
1771 LPDWORD pcbBytesNeeded)
1772 {
1773 DWORD dwError;
1774
1775 TRACE("QueryServiceLockStatusW() called\n");
1776
1777 HandleBind();
1778
1779 /* Call to services.exe using RPC */
1780 dwError = RQueryServiceLockStatusW(BindingHandle,
1781 (SC_RPC_HANDLE)hSCManager,
1782 lpLockStatus,
1783 cbBufSize,
1784 pcbBytesNeeded);
1785 if (dwError != ERROR_SUCCESS)
1786 {
1787 ERR("RQueryServiceLockStatusW() failed (Error %lu)\n", dwError);
1788 SetLastError(dwError);
1789 return FALSE;
1790 }
1791
1792 if (lpLockStatus->lpLockOwner != NULL)
1793 {
1794 lpLockStatus->lpLockOwner =
1795 (LPWSTR)((UINT_PTR)lpLockStatus + (UINT_PTR)lpLockStatus->lpLockOwner);
1796 }
1797
1798 TRACE("QueryServiceLockStatusW() done\n");
1799
1800 return TRUE;
1801 }
1802
1803
1804 /**********************************************************************
1805 * QueryServiceObjectSecurity
1806 *
1807 * @implemented
1808 */
1809 BOOL STDCALL
1810 QueryServiceObjectSecurity(SC_HANDLE hService,
1811 SECURITY_INFORMATION dwSecurityInformation,
1812 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
1813 DWORD cbBufSize,
1814 LPDWORD pcbBytesNeeded)
1815 {
1816 DWORD dwError;
1817
1818 TRACE("QueryServiceObjectSecurity(%p, %lu, %p)\n",
1819 hService, dwSecurityInformation, lpSecurityDescriptor);
1820
1821 HandleBind();
1822
1823 /* Call to services.exe using RPC */
1824 dwError = RQueryServiceObjectSecurity(BindingHandle,
1825 (SC_RPC_HANDLE)hService,
1826 dwSecurityInformation,
1827 (LPBYTE)lpSecurityDescriptor,
1828 cbBufSize,
1829 pcbBytesNeeded);
1830 if (dwError != ERROR_SUCCESS)
1831 {
1832 ERR("QueryServiceObjectSecurity() failed (Error %lu)\n", dwError);
1833 SetLastError(dwError);
1834 return FALSE;
1835 }
1836
1837 return TRUE;
1838 }
1839
1840 /**********************************************************************
1841 * SetServiceObjectSecurity
1842 *
1843 * @implemented
1844 */
1845 BOOL STDCALL
1846 SetServiceObjectSecurity(SC_HANDLE hService,
1847 SECURITY_INFORMATION dwSecurityInformation,
1848 PSECURITY_DESCRIPTOR lpSecurityDescriptor)
1849 {
1850 PSECURITY_DESCRIPTOR SelfRelativeSD = NULL;
1851 ULONG Length;
1852 NTSTATUS Status;
1853 DWORD dwError;
1854
1855 Length = 0;
1856 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
1857 SelfRelativeSD,
1858 &Length);
1859 if (Status != STATUS_BUFFER_TOO_SMALL)
1860 {
1861 SetLastError(ERROR_INVALID_PARAMETER);
1862 return FALSE;
1863 }
1864
1865 SelfRelativeSD = HeapAlloc(GetProcessHeap(), 0, Length);
1866 if (SelfRelativeSD == NULL)
1867 {
1868 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
1869 return FALSE;
1870 }
1871
1872 Status = RtlMakeSelfRelativeSD(lpSecurityDescriptor,
1873 SelfRelativeSD,
1874 &Length);
1875 if (!NT_SUCCESS(Status))
1876 {
1877 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
1878 SetLastError(RtlNtStatusToDosError(Status));
1879 return FALSE;
1880 }
1881
1882 HandleBind();
1883
1884 /* Call to services.exe using RPC */
1885 dwError = RSetServiceObjectSecurity(BindingHandle,
1886 (SC_RPC_HANDLE)hService,
1887 dwSecurityInformation,
1888 (LPBYTE)SelfRelativeSD,
1889 Length);
1890
1891 HeapFree(GetProcessHeap(), 0, SelfRelativeSD);
1892
1893 if (dwError != ERROR_SUCCESS)
1894 {
1895 ERR("RServiceObjectSecurity() failed (Error %lu)\n", dwError);
1896 SetLastError(dwError);
1897 return FALSE;
1898 }
1899
1900 return TRUE;
1901 }
1902
1903
1904 /**********************************************************************
1905 * QueryServiceStatus
1906 *
1907 * @implemented
1908 */
1909 BOOL STDCALL
1910 QueryServiceStatus(SC_HANDLE hService,
1911 LPSERVICE_STATUS lpServiceStatus)
1912 {
1913 DWORD dwError;
1914
1915 TRACE("QueryServiceStatus(%p, %p)\n",
1916 hService, lpServiceStatus);
1917
1918 HandleBind();
1919
1920 /* Call to services.exe using RPC */
1921 dwError = RQueryServiceStatus(BindingHandle,
1922 (SC_RPC_HANDLE)hService,
1923 lpServiceStatus);
1924 if (dwError != ERROR_SUCCESS)
1925 {
1926 ERR("RQueryServiceStatus() failed (Error %lu)\n", dwError);
1927 SetLastError(dwError);
1928 return FALSE;
1929 }
1930
1931 return TRUE;
1932 }
1933
1934
1935 /**********************************************************************
1936 * QueryServiceStatusEx
1937 *
1938 * @implemented
1939 */
1940 BOOL STDCALL
1941 QueryServiceStatusEx(SC_HANDLE hService,
1942 SC_STATUS_TYPE InfoLevel,
1943 LPBYTE lpBuffer,
1944 DWORD cbBufSize,
1945 LPDWORD pcbBytesNeeded)
1946 {
1947 DWORD dwError;
1948
1949 TRACE("QueryServiceStatusEx() called\n");
1950
1951 HandleBind();
1952
1953 /* Call to services.exe using RPC */
1954 dwError = RQueryServiceStatusEx(BindingHandle,
1955 (SC_RPC_HANDLE)hService,
1956 InfoLevel,
1957 lpBuffer,
1958 cbBufSize,
1959 pcbBytesNeeded);
1960 if (dwError != ERROR_SUCCESS)
1961 {
1962 ERR("RQueryServiceStatusEx() failed (Error %lu)\n", dwError);
1963 SetLastError(dwError);
1964 return FALSE;
1965 }
1966
1967 return TRUE;
1968 }
1969
1970
1971 /**********************************************************************
1972 * StartServiceA
1973 *
1974 * @implemented
1975 */
1976 BOOL STDCALL
1977 StartServiceA(SC_HANDLE hService,
1978 DWORD dwNumServiceArgs,
1979 LPCSTR *lpServiceArgVectors)
1980 {
1981 DWORD dwError;
1982
1983 dwError = RStartServiceA(BindingHandle,
1984 (SC_RPC_HANDLE)hService,
1985 dwNumServiceArgs,
1986 (LPSTRING_PTRSA)lpServiceArgVectors);
1987
1988
1989 if (dwError != ERROR_SUCCESS)
1990 {
1991 ERR("RStartServiceA() failed (Error %lu)\n", dwError);
1992 SetLastError(dwError);
1993 return FALSE;
1994 }
1995
1996 return TRUE;
1997 }
1998
1999
2000 /**********************************************************************
2001 * StartServiceW
2002 *
2003 * @implemented
2004 */
2005 BOOL STDCALL
2006 StartServiceW(SC_HANDLE hService,
2007 DWORD dwNumServiceArgs,
2008 LPCWSTR *lpServiceArgVectors)
2009 {
2010 DWORD dwError;
2011
2012 dwError = RStartServiceW(BindingHandle,
2013 (SC_RPC_HANDLE)hService,
2014 dwNumServiceArgs,
2015 (LPSTRING_PTRSW)lpServiceArgVectors);
2016
2017 if (dwError != ERROR_SUCCESS)
2018 {
2019 ERR("RStartServiceW() failed (Error %lu)\n", dwError);
2020 SetLastError(dwError);
2021 return FALSE;
2022 }
2023
2024 return TRUE;
2025 }
2026
2027
2028 /**********************************************************************
2029 * UnlockServiceDatabase
2030 *
2031 * @implemented
2032 */
2033 BOOL STDCALL
2034 UnlockServiceDatabase(SC_LOCK ScLock)
2035 {
2036 DWORD dwError;
2037
2038 TRACE("UnlockServiceDatabase(%x)\n", ScLock);
2039
2040 HandleBind();
2041
2042 /* Call to services.exe using RPC */
2043 dwError = RUnlockServiceDatabase(BindingHandle,
2044 (SC_RPC_LOCK)ScLock);
2045 if (dwError != ERROR_SUCCESS)
2046 {
2047 ERR("RUnlockServiceDatabase() failed (Error %lu)\n", dwError);
2048 SetLastError(dwError);
2049 return FALSE;
2050 }
2051
2052 return TRUE;
2053 }
2054
2055
2056 /**********************************************************************
2057 * NotifyBootConfigStatus
2058 *
2059 * @implemented
2060 */
2061 BOOL STDCALL
2062 NotifyBootConfigStatus(BOOL BootAcceptable)
2063 {
2064 DWORD dwError;
2065
2066 TRACE("NotifyBootConfigStatus()\n");
2067
2068 HandleBind();
2069
2070 /* Call to services.exe using RPC */
2071 dwError = RNotifyBootConfigStatus(BindingHandle,
2072 NULL,
2073 BootAcceptable);
2074 if (dwError != ERROR_SUCCESS)
2075 {
2076 ERR("NotifyBootConfigStatus() failed (Error %lu)\n", dwError);
2077 SetLastError(dwError);
2078 return FALSE;
2079 }
2080
2081 return TRUE;
2082 }
2083
2084 /* EOF */