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