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