Use RPC for making calls to the Service Control Manager.
[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.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 * ChangeServiceConfigA
82 *
83 * @unimplemented
84 */
85 BOOL
86 STDCALL
87 ChangeServiceConfigA(
88 SC_HANDLE hService,
89 DWORD dwServiceType,
90 DWORD dwStartType,
91 DWORD dwErrorControl,
92 LPCSTR lpBinaryPathName,
93 LPCSTR lpLoadOrderGroup,
94 LPDWORD lpdwTagId,
95 LPCSTR lpDependencies,
96 LPCSTR lpServiceStartName,
97 LPCSTR lpPassword,
98 LPCSTR lpDisplayName)
99 {
100 DPRINT1("ChangeServiceConfigA is unimplemented\n");
101 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
102 return FALSE;
103 }
104
105
106 /**********************************************************************
107 * ChangeServiceConfigW
108 *
109 * @unimplemented
110 */
111 BOOL
112 STDCALL
113 ChangeServiceConfigW(
114 SC_HANDLE hService,
115 DWORD dwServiceType,
116 DWORD dwStartType,
117 DWORD dwErrorControl,
118 LPCWSTR lpBinaryPathName,
119 LPCWSTR lpLoadOrderGroup,
120 LPDWORD lpdwTagId,
121 LPCWSTR lpDependencies,
122 LPCWSTR lpServiceStartName,
123 LPCWSTR lpPassword,
124 LPCWSTR lpDisplayName)
125 {
126 DPRINT1("ChangeServiceConfigW is unimplemented\n");
127 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
128 return FALSE;
129 }
130
131
132 /**********************************************************************
133 * CloseServiceHandle
134 *
135 * @implemented
136 */
137 BOOL STDCALL
138 CloseServiceHandle(SC_HANDLE hSCObject)
139 {
140 DWORD dwError;
141
142 DPRINT1("CloseServiceHandle() called\n");
143
144 HandleBind();
145
146 /* Call to services.exe using RPC */
147 dwError = ScmrCloseServiceHandle(BindingHandle,
148 (unsigned int)hSCObject);
149 DPRINT1("dwError %lu\n", dwError);
150
151 if (dwError)
152 {
153 SetLastError(dwError);
154 return FALSE;
155 }
156
157 return TRUE;
158 }
159
160
161 /**********************************************************************
162 * ControlService
163 *
164 * @unimplemented
165 */
166 BOOL STDCALL
167 ControlService(SC_HANDLE hService,
168 DWORD dwControl,
169 LPSERVICE_STATUS lpServiceStatus)
170 {
171 #if 0
172 DWORD dwError;
173
174 DPRINT1("ControlService(%x, %x, %p)\n",
175 hService, dwControl, lpServiceStatus);
176
177 HandleBind();
178
179 /* Call to services.exe using RPC */
180 dwError = ScmrControlService(BindingHandle,
181 (unsigned int)hService,
182 dwControl,
183 lpServiceStatus);
184 if (dwError != ERROR_SUCCESS)
185 {
186 SetLastError(dwError);
187 return FALSE;
188 }
189
190 return TRUE;
191 #endif
192
193 DPRINT1("ControlService is unimplemented\n");
194 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
195 return FALSE;
196 }
197
198
199 /**********************************************************************
200 * CreateServiceA
201 *
202 * @unimplemented
203 */
204 SC_HANDLE
205 STDCALL
206 CreateServiceA(
207 SC_HANDLE hSCManager,
208 LPCSTR lpServiceName,
209 LPCSTR lpDisplayName,
210 DWORD dwDesiredAccess,
211 DWORD dwServiceType,
212 DWORD dwStartType,
213 DWORD dwErrorControl,
214 LPCSTR lpBinaryPathName,
215 LPCSTR lpLoadOrderGroup,
216 LPDWORD lpdwTagId,
217 LPCSTR lpDependencies,
218 LPCSTR lpServiceStartName,
219 LPCSTR lpPassword)
220 {
221 DPRINT1("CreateServiceA is unimplemented, but returning INVALID_HANDLE_VALUE instead of NULL\n");
222 return INVALID_HANDLE_VALUE;
223 }
224
225
226 /**********************************************************************
227 * CreateServiceW
228 *
229 * @unimplemented
230 */
231 SC_HANDLE
232 STDCALL
233 CreateServiceW(
234 SC_HANDLE hSCManager,
235 LPCWSTR lpServiceName,
236 LPCWSTR lpDisplayName,
237 DWORD dwDesiredAccess,
238 DWORD dwServiceType,
239 DWORD dwStartType,
240 DWORD dwErrorControl,
241 LPCWSTR lpBinaryPathName,
242 LPCWSTR lpLoadOrderGroup,
243 LPDWORD lpdwTagId,
244 LPCWSTR lpDependencies,
245 LPCWSTR lpServiceStartName,
246 LPCWSTR lpPassword)
247 {
248 DPRINT1("CreateServiceW is unimplemented, but returning INVALID_HANDLE_VALUE instead of NULL\n");
249 return INVALID_HANDLE_VALUE;
250 }
251
252
253 /**********************************************************************
254 * DeleteService
255 *
256 * @unimplemented
257 */
258 BOOL STDCALL
259 DeleteService(SC_HANDLE hService)
260 {
261 DWORD dwError;
262
263 DPRINT1("DeleteService(%x)\n", hService);
264
265 HandleBind();
266
267 /* Call to services.exe using RPC */
268 dwError = ScmrDeleteService(BindingHandle,
269 (unsigned int)hService);
270 if (dwError != ERROR_SUCCESS)
271 {
272 SetLastError(dwError);
273 return FALSE;
274 }
275
276 return TRUE;
277 }
278
279
280 /**********************************************************************
281 * EnumDependentServicesA
282 *
283 * @unimplemented
284 */
285 BOOL
286 STDCALL
287 EnumDependentServicesA(
288 SC_HANDLE hService,
289 DWORD dwServiceState,
290 LPENUM_SERVICE_STATUSA lpServices,
291 DWORD cbBufSize,
292 LPDWORD pcbBytesNeeded,
293 LPDWORD lpServicesReturned)
294 {
295 DPRINT1("EnumDependentServicesA is unimplemented\n");
296 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
297 return FALSE;
298 }
299
300
301 /**********************************************************************
302 * EnumDependentServicesW
303 *
304 * @unimplemented
305 */
306 BOOL
307 STDCALL
308 EnumDependentServicesW(
309 SC_HANDLE hService,
310 DWORD dwServiceState,
311 LPENUM_SERVICE_STATUSW lpServices,
312 DWORD cbBufSize,
313 LPDWORD pcbBytesNeeded,
314 LPDWORD lpServicesReturned)
315 {
316 DPRINT1("EnumDependentServicesW is unimplemented\n");
317 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
318 return FALSE;
319 }
320
321
322 /**********************************************************************
323 * EnumServiceGroupW
324 *
325 * @unimplemented
326 */
327 BOOL
328 STDCALL
329 EnumServiceGroupW (
330 DWORD Unknown0,
331 DWORD Unknown1,
332 DWORD Unknown2,
333 DWORD Unknown3,
334 DWORD Unknown4,
335 DWORD Unknown5,
336 DWORD Unknown6,
337 DWORD Unknown7,
338 DWORD Unknown8)
339 {
340 DPRINT1("EnumServiceGroupW is unimplemented\n");
341 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
342 return FALSE;
343 }
344
345
346 /**********************************************************************
347 * EnumServicesStatusA
348 *
349 * @unimplemented
350 */
351 BOOL
352 STDCALL
353 EnumServicesStatusA (
354 SC_HANDLE hSCManager,
355 DWORD dwServiceType,
356 DWORD dwServiceState,
357 LPENUM_SERVICE_STATUSA lpServices,
358 DWORD cbBufSize,
359 LPDWORD pcbBytesNeeded,
360 LPDWORD lpServicesReturned,
361 LPDWORD lpResumeHandle)
362 {
363 DPRINT1("EnumServicesStatusA is unimplemented\n");
364 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
365 return FALSE;
366 }
367
368
369 /**********************************************************************
370 * EnumServicesStatusExA
371 *
372 * @unimplemented
373 */
374 BOOL
375 STDCALL
376 EnumServicesStatusExA(SC_HANDLE hSCManager,
377 SC_ENUM_TYPE InfoLevel,
378 DWORD dwServiceType,
379 DWORD dwServiceState,
380 LPBYTE lpServices,
381 DWORD cbBufSize,
382 LPDWORD pcbBytesNeeded,
383 LPDWORD lpServicesReturned,
384 LPDWORD lpResumeHandle,
385 LPCSTR pszGroupName)
386 {
387 DPRINT1("EnumServicesStatusExA is unimplemented\n");
388 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
389 return FALSE;
390 }
391
392
393 /**********************************************************************
394 * EnumServicesStatusExW
395 *
396 * @unimplemented
397 */
398 BOOL
399 STDCALL
400 EnumServicesStatusExW(SC_HANDLE hSCManager,
401 SC_ENUM_TYPE InfoLevel,
402 DWORD dwServiceType,
403 DWORD dwServiceState,
404 LPBYTE lpServices,
405 DWORD cbBufSize,
406 LPDWORD pcbBytesNeeded,
407 LPDWORD lpServicesReturned,
408 LPDWORD lpResumeHandle,
409 LPCWSTR pszGroupName)
410 {
411 DPRINT1("EnumServicesStatusExW is unimplemented\n");
412 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
413 return FALSE;
414 }
415
416
417 /**********************************************************************
418 * EnumServicesStatusW
419 *
420 * @unimplemented
421 */
422 BOOL
423 STDCALL
424 EnumServicesStatusW(
425 SC_HANDLE hSCManager,
426 DWORD dwServiceType,
427 DWORD dwServiceState,
428 LPENUM_SERVICE_STATUSW lpServices,
429 DWORD cbBufSize,
430 LPDWORD pcbBytesNeeded,
431 LPDWORD lpServicesReturned,
432 LPDWORD lpResumeHandle)
433 {
434 DPRINT1("EnumServicesStatusW is unimplemented\n");
435 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
436 return FALSE;
437 }
438
439
440 /**********************************************************************
441 * GetServiceDisplayNameA
442 *
443 * @unimplemented
444 */
445 BOOL
446 STDCALL
447 GetServiceDisplayNameA(
448 SC_HANDLE hSCManager,
449 LPCSTR lpServiceName,
450 LPSTR lpDisplayName,
451 LPDWORD lpcchBuffer)
452 {
453 DPRINT1("GetServiceDisplayNameA is unimplemented\n");
454 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
455 return FALSE;
456 }
457
458
459 /**********************************************************************
460 * GetServiceDisplayNameW
461 *
462 * @unimplemented
463 */
464 BOOL
465 STDCALL
466 GetServiceDisplayNameW(
467 SC_HANDLE hSCManager,
468 LPCWSTR lpServiceName,
469 LPWSTR lpDisplayName,
470 LPDWORD lpcchBuffer)
471 {
472 DPRINT1("GetServiceDisplayNameW is unimplemented\n");
473 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
474 return FALSE;
475 }
476
477
478 /**********************************************************************
479 * GetServiceKeyNameA
480 *
481 * @unimplemented
482 */
483 BOOL
484 STDCALL
485 GetServiceKeyNameA(
486 SC_HANDLE hSCManager,
487 LPCSTR lpDisplayName,
488 LPSTR lpServiceName,
489 LPDWORD lpcchBuffer)
490 {
491 DPRINT1("GetServiceKeyNameA is unimplemented\n");
492 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
493 return FALSE;
494 }
495
496
497 /**********************************************************************
498 * GetServiceKeyNameW
499 *
500 * @unimplemented
501 */
502 BOOL
503 STDCALL
504 GetServiceKeyNameW(
505 SC_HANDLE hSCManager,
506 LPCWSTR lpDisplayName,
507 LPWSTR lpServiceName,
508 LPDWORD lpcchBuffer)
509 {
510 DPRINT1("GetServiceKeyNameW is unimplemented\n");
511 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
512 return FALSE;
513 }
514
515
516 /**********************************************************************
517 * LockServiceDatabase
518 *
519 * @unimplemented
520 */
521 SC_LOCK
522 STDCALL
523 LockServiceDatabase(SC_HANDLE hSCManager)
524 {
525 DPRINT1("LockServiceDatabase is unimplemented\n");
526 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
527 return NULL;
528 }
529
530
531 static VOID
532 WaitForSCManager(VOID)
533 {
534 HANDLE hEvent;
535
536 DPRINT1("WaitForSCManager() called\n");
537
538 /* Try to open the existing event */
539 hEvent = OpenEventW(SYNCHRONIZE,
540 FALSE,
541 L"SvcctrlStartEvent_A3725DX");
542 if (hEvent == NULL)
543 {
544 if (GetLastError() != ERROR_FILE_NOT_FOUND)
545 return;
546
547 /* Try to create a new event */
548 hEvent = CreateEventW(NULL,
549 TRUE,
550 FALSE,
551 L"SvcctrlStartEvent_A3725DX");
552 if (hEvent == NULL)
553 {
554 /* Try to open the existing event again */
555 hEvent = OpenEventW(SYNCHRONIZE,
556 FALSE,
557 L"SvcctrlStartEvent_A3725DX");
558 if (hEvent == NULL)
559 return;
560 }
561 }
562
563 /* Wait for 3 minutes */
564 WaitForSingleObject(hEvent, 180000);
565 CloseHandle(hEvent);
566
567 DPRINT1("ScmWaitForSCManager() done\n");
568 }
569
570
571 /**********************************************************************
572 * OpenSCManagerA
573 *
574 * @implemented
575 */
576 SC_HANDLE STDCALL
577 OpenSCManagerA(LPCSTR lpMachineName,
578 LPCSTR lpDatabaseName,
579 DWORD dwDesiredAccess)
580 {
581 SC_HANDLE hScm = NULL;
582 DWORD dwError;
583
584 DPRINT1("OpenSCManagerA(%s, %s, %lx)\n",
585 lpMachineName, lpDatabaseName, dwDesiredAccess);
586
587 WaitForSCManager();
588
589 HandleBind();
590
591 /* Call to services.exe using RPC */
592 dwError = ScmrOpenSCManagerA(BindingHandle,
593 (LPSTR)lpMachineName,
594 (LPSTR)lpDatabaseName,
595 dwDesiredAccess,
596 (unsigned int*)&hScm);
597 DPRINT1("hScm = %p\n", hScm);
598 if (dwError)
599 {
600 SetLastError(dwError);
601 return NULL;
602 }
603
604 return hScm;
605 }
606
607
608 /**********************************************************************
609 * OpenSCManagerW
610 *
611 * @unimplemented
612 */
613 SC_HANDLE STDCALL
614 OpenSCManagerW(LPCWSTR lpMachineName,
615 LPCWSTR lpDatabaseName,
616 DWORD dwDesiredAccess)
617 {
618 SC_HANDLE hScm = NULL;
619 DWORD dwError;
620
621 DPRINT1("OpenSCManagerW(%S, %S, %lx)\n",
622 lpMachineName, lpDatabaseName, dwDesiredAccess);
623
624 WaitForSCManager();
625
626 HandleBind();
627
628 /* Call to services.exe using RPC */
629 dwError = ScmrOpenSCManagerW(BindingHandle,
630 (LPWSTR)lpMachineName,
631 (LPWSTR)lpDatabaseName,
632 dwDesiredAccess,
633 (unsigned int*)&hScm);
634 if (dwError != ERROR_SUCCESS)
635 {
636 DPRINT1("ScmrOpenSCManagerW() failed (Error %lu)\n", dwError);
637 SetLastError(dwError);
638 return NULL;
639 }
640
641 DPRINT1("hScm = %p\n", hScm);
642
643 return hScm;
644 }
645
646
647 /**********************************************************************
648 * OpenServiceA
649 *
650 * @implemented
651 */
652 SC_HANDLE STDCALL
653 OpenServiceA(SC_HANDLE hSCManager,
654 LPCSTR lpServiceName,
655 DWORD dwDesiredAccess)
656 {
657 SC_HANDLE hService = NULL;
658 DWORD dwError;
659
660 DPRINT1("OpenServiceA(%p, %s, %lx)\n",
661 hSCManager, lpServiceName, dwDesiredAccess);
662
663 HandleBind();
664
665 /* Call to services.exe using RPC */
666 dwError = ScmrOpenServiceA(BindingHandle,
667 (unsigned int)hSCManager,
668 (LPSTR)lpServiceName,
669 dwDesiredAccess,
670 (unsigned int*)&hService);
671 if (dwError != ERROR_SUCCESS)
672 {
673 DPRINT1("ScmrOpenServiceA() failed (Error %lu)\n", dwError);
674 SetLastError(dwError);
675 return NULL;
676 }
677
678 DPRINT1("hService = %p\n", hService);
679
680 return hService;
681 }
682
683
684 /**********************************************************************
685 * OpenServiceW
686 *
687 * @implemented
688 */
689 SC_HANDLE STDCALL
690 OpenServiceW(SC_HANDLE hSCManager,
691 LPCWSTR lpServiceName,
692 DWORD dwDesiredAccess)
693 {
694 SC_HANDLE hService = NULL;
695 DWORD dwError;
696
697 DPRINT1("OpenServiceW(%p, %S, %lx)\n",
698 hSCManager, lpServiceName, dwDesiredAccess);
699
700 HandleBind();
701
702 /* Call to services.exe using RPC */
703 dwError = ScmrOpenServiceW(BindingHandle,
704 (unsigned int)hSCManager,
705 (LPWSTR)lpServiceName,
706 dwDesiredAccess,
707 (unsigned int*)&hService);
708 if (dwError != ERROR_SUCCESS)
709 {
710 DPRINT1("ScmrOpenServiceW() failed (Error %lu)\n", dwError);
711 SetLastError(dwError);
712 return NULL;
713 }
714
715 DPRINT1("hService = %p\n", hService);
716
717 return hService;
718 }
719
720
721 /**********************************************************************
722 * QueryServiceConfigA
723 *
724 * @unimplemented
725 */
726 BOOL
727 STDCALL
728 QueryServiceConfigA(
729 SC_HANDLE hService,
730 LPQUERY_SERVICE_CONFIGA lpServiceConfig,
731 DWORD cbBufSize,
732 LPDWORD pcbBytesNeeded)
733 {
734 DPRINT1("QueryServiceConfigA is unimplemented\n");
735 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
736 return FALSE;
737 }
738
739
740 /**********************************************************************
741 * QueryServiceConfigW
742 *
743 * @unimplemented
744 */
745 BOOL
746 STDCALL
747 QueryServiceConfigW(
748 SC_HANDLE hService,
749 LPQUERY_SERVICE_CONFIGW lpServiceConfig,
750 DWORD cbBufSize,
751 LPDWORD pcbBytesNeeded)
752 {
753 DPRINT1("QueryServiceConfigW is unimplemented\n");
754 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
755 return FALSE;
756 }
757
758
759 /**********************************************************************
760 * QueryServiceLockStatusA
761 *
762 * @unimplemented
763 */
764 BOOL
765 STDCALL
766 QueryServiceLockStatusA(
767 SC_HANDLE hSCManager,
768 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus,
769 DWORD cbBufSize,
770 LPDWORD pcbBytesNeeded)
771 {
772 DPRINT1("QueryServiceLockStatusA is unimplemented\n");
773 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
774 return FALSE;
775 }
776
777
778 /**********************************************************************
779 * QueryServiceLockStatusW
780 *
781 * @unimplemented
782 */
783 BOOL
784 STDCALL
785 QueryServiceLockStatusW(
786 SC_HANDLE hSCManager,
787 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus,
788 DWORD cbBufSize,
789 LPDWORD pcbBytesNeeded)
790 {
791 DPRINT1("QueryServiceLockStatusW is unimplemented\n");
792 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
793 return FALSE;
794 }
795
796
797 /**********************************************************************
798 * QueryServiceObjectSecurity
799 *
800 * @unimplemented
801 */
802 BOOL
803 STDCALL
804 QueryServiceObjectSecurity(
805 SC_HANDLE hService,
806 SECURITY_INFORMATION dwSecurityInformation,
807 PSECURITY_DESCRIPTOR lpSecurityDescriptor,
808 DWORD cbBufSize,
809 LPDWORD pcbBytesNeeded)
810 {
811 DPRINT1("QueryServiceObjectSecurity is unimplemented\n");
812 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
813 return FALSE;
814 }
815
816
817 /**********************************************************************
818 * QueryServiceStatus
819 *
820 * @unimplemented
821 */
822 BOOL
823 STDCALL
824 QueryServiceStatus(
825 SC_HANDLE hService,
826 LPSERVICE_STATUS lpServiceStatus)
827 {
828 DPRINT1("QueryServiceStatus is unimplemented\n");
829 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
830 return FALSE;
831 }
832
833
834 /**********************************************************************
835 * QueryServiceStatusEx
836 *
837 * @unimplemented
838 */
839 BOOL
840 STDCALL
841 QueryServiceStatusEx(SC_HANDLE hService,
842 SC_STATUS_TYPE InfoLevel,
843 LPBYTE lpBuffer,
844 DWORD cbBufSize,
845 LPDWORD pcbBytesNeeded)
846 {
847 DPRINT1("QueryServiceStatusEx is unimplemented\n");
848 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
849 return FALSE;
850 }
851
852
853 /**********************************************************************
854 * StartServiceA
855 *
856 * @unimplemented
857 */
858 BOOL
859 STDCALL
860 StartServiceA(
861 SC_HANDLE hService,
862 DWORD dwNumServiceArgs,
863 LPCSTR *lpServiceArgVectors)
864 {
865 DPRINT1("StartServiceA is unimplemented\n");
866 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
867 return FALSE;
868 }
869
870
871
872
873 /**********************************************************************
874 * StartServiceW
875 *
876 * @unimplemented
877 */
878 BOOL
879 STDCALL
880 StartServiceW(
881 SC_HANDLE hService,
882 DWORD dwNumServiceArgs,
883 LPCWSTR *lpServiceArgVectors)
884 {
885 DPRINT1("StartServiceW is unimplemented\n");
886 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
887 return FALSE;
888 }
889
890
891 /**********************************************************************
892 * UnlockServiceDatabase
893 *
894 * @unimplemented
895 */
896 BOOL
897 STDCALL
898 UnlockServiceDatabase(SC_LOCK ScLock)
899 {
900 DPRINT1("UnlockServiceDatabase is unimplemented\n");
901 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
902 return FALSE;
903 }
904
905
906 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
907 {
908 return GlobalAlloc(GPTR,len);
909 }
910
911 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
912 {
913 GlobalFree(ptr);
914 }
915
916 /* EOF */