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