update for HEAD-2003091401
[reactos.git] / lib / advapi32 / service / scm.c
1 /* $Id$
2  * 
3  * COPYRIGHT:       See COPYING in the top level directory
4  * PROJECT:         ReactOS system libraries
5  * FILE:            lib/advapi32/service/scm.c
6  * PURPOSE:         Service control manager functions
7  * PROGRAMMER:      Emanuele Aliberti
8  * UPDATE HISTORY:
9  *  19990413 EA created
10  *  19990515 EA
11  */
12
13 /* INCLUDES ******************************************************************/
14
15 #define NTOS_MODE_USER
16 #include <ntos.h>
17 #include <windows.h>
18 #include <wchar.h>
19 #include <tchar.h>
20
21 #define DBG
22 #include <debug.h>
23
24 /* FUNCTIONS *****************************************************************/
25
26 /**********************************************************************
27  *  ChangeServiceConfigA
28  *
29  * @unimplemented
30  */
31 BOOL
32 STDCALL
33 ChangeServiceConfigA(
34     SC_HANDLE   hService,
35     DWORD       dwServiceType,
36     DWORD       dwStartType,
37     DWORD       dwErrorControl,
38     LPCSTR      lpBinaryPathName,
39     LPCSTR      lpLoadOrderGroup,
40     LPDWORD     lpdwTagId,
41     LPCSTR      lpDependencies,
42     LPCSTR      lpServiceStartName,
43     LPCSTR      lpPassword,
44     LPCSTR      lpDisplayName)
45 {
46     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
47     return FALSE;
48 }
49
50
51 /**********************************************************************
52  *  ChangeServiceConfigW
53  *
54  * @unimplemented
55  */
56 BOOL
57 STDCALL
58 ChangeServiceConfigW(
59     SC_HANDLE   hService,
60     DWORD       dwServiceType,
61     DWORD       dwStartType,
62     DWORD       dwErrorControl,
63     LPCWSTR     lpBinaryPathName,
64     LPCWSTR     lpLoadOrderGroup,
65     LPDWORD     lpdwTagId,
66     LPCWSTR     lpDependencies,
67     LPCWSTR     lpServiceStartName,
68     LPCWSTR     lpPassword,
69     LPCWSTR     lpDisplayName)
70 {
71     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
72     return FALSE;
73 }
74
75
76 /**********************************************************************
77  *  CloseServiceHandle
78  *
79  * @implemented
80  */
81 BOOL 
82 STDCALL
83 CloseServiceHandle(SC_HANDLE hSCObject)
84 {
85     HANDLE hPipe;
86     DPRINT("CloseServiceHandle() - called.\n");
87 //    SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
88
89     if (!CloseHandle(hPipe)) {
90         SetLastError(ERROR_INVALID_HANDLE);
91         return FALSE;
92     }
93     return TRUE;
94 }
95
96
97 /**********************************************************************
98  *  ControlService
99  *
100  * @unimplemented
101  */
102 BOOL
103 STDCALL
104 ControlService(SC_HANDLE        hService,
105                DWORD            dwControl,
106                LPSERVICE_STATUS lpServiceStatus)
107 {
108     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
109     return FALSE;
110 }
111
112
113 /**********************************************************************
114  *  CreateServiceA
115  *
116  * @unimplemented
117  */
118 SC_HANDLE
119 STDCALL
120 CreateServiceA(
121     SC_HANDLE   hSCManager,
122     LPCSTR      lpServiceName,
123     LPCSTR      lpDisplayName,
124     DWORD       dwDesiredAccess,
125     DWORD       dwServiceType,
126     DWORD       dwStartType,
127     DWORD       dwErrorControl,
128     LPCSTR      lpBinaryPathName,
129     LPCSTR      lpLoadOrderGroup,
130     LPDWORD     lpdwTagId,
131     LPCSTR      lpDependencies,
132     LPCSTR      lpServiceStartName,
133     LPCSTR      lpPassword)
134 {
135     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
136     return NULL;
137 }
138
139
140 /**********************************************************************
141  *  CreateServiceW
142  *
143  * @unimplemented
144  */
145 SC_HANDLE
146 STDCALL
147 CreateServiceW(
148     SC_HANDLE   hSCManager,
149     LPCWSTR     lpServiceName,
150     LPCWSTR     lpDisplayName,
151     DWORD       dwDesiredAccess,
152     DWORD       dwServiceType,
153     DWORD       dwStartType,
154     DWORD       dwErrorControl,
155     LPCWSTR     lpBinaryPathName,
156     LPCWSTR     lpLoadOrderGroup,
157     LPDWORD     lpdwTagId,
158     LPCWSTR     lpDependencies,
159     LPCWSTR     lpServiceStartName,
160     LPCWSTR     lpPassword)
161 {
162     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
163     return NULL;
164 }
165
166
167 /**********************************************************************
168  *  DeleteService
169  *
170  * @unimplemented
171  */
172 BOOL
173 STDCALL
174 DeleteService(SC_HANDLE hService)
175 {
176     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
177     return FALSE;
178 }
179
180
181 /**********************************************************************
182  *  EnumDependentServicesA
183  *
184  * @unimplemented
185  */
186 BOOL
187 STDCALL
188 EnumDependentServicesA(
189     SC_HANDLE       hService,
190     DWORD           dwServiceState,
191     LPENUM_SERVICE_STATUSA  lpServices,
192     DWORD           cbBufSize,
193     LPDWORD         pcbBytesNeeded,
194     LPDWORD         lpServicesReturned)
195 {
196     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
197     return FALSE;
198 }
199
200
201 /**********************************************************************
202  *  EnumDependentServicesW
203  *
204  * @unimplemented
205  */
206 BOOL
207 STDCALL
208 EnumDependentServicesW(
209     SC_HANDLE       hService,
210     DWORD           dwServiceState,
211     LPENUM_SERVICE_STATUSW  lpServices,
212     DWORD           cbBufSize,
213     LPDWORD         pcbBytesNeeded,
214     LPDWORD         lpServicesReturned)
215 {
216     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
217     return FALSE;
218 }
219
220
221 /**********************************************************************
222  *  EnumServiceGroupW
223  *
224  * @unimplemented
225  */
226 BOOL
227 STDCALL
228 EnumServiceGroupW (
229     DWORD   Unknown0,
230     DWORD   Unknown1,
231     DWORD   Unknown2,
232     DWORD   Unknown3,
233     DWORD   Unknown4,
234     DWORD   Unknown5,
235     DWORD   Unknown6,
236     DWORD   Unknown7,
237     DWORD   Unknown8)
238 {
239     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
240     return FALSE;
241 }
242
243
244 /**********************************************************************
245  *  EnumServicesStatusA
246  *
247  * @unimplemented
248  */
249 BOOL
250 STDCALL
251 EnumServicesStatusA (
252     SC_HANDLE               hSCManager,
253     DWORD                   dwServiceType,
254     DWORD                   dwServiceState,
255     LPENUM_SERVICE_STATUSA  lpServices,
256     DWORD                   cbBufSize,
257     LPDWORD                 pcbBytesNeeded,
258     LPDWORD                 lpServicesReturned,
259     LPDWORD                 lpResumeHandle)
260 {
261     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
262     return FALSE;
263 }
264
265
266 /**********************************************************************
267  *  EnumServicesStatusExA
268  *
269  * @unimplemented
270  */
271 BOOL
272 STDCALL
273 EnumServicesStatusExA(SC_HANDLE  hSCManager,
274   SC_ENUM_TYPE  InfoLevel,
275   DWORD  dwServiceType,
276   DWORD  dwServiceState,
277   LPBYTE  lpServices,
278   DWORD  cbBufSize,
279   LPDWORD  pcbBytesNeeded,
280   LPDWORD  lpServicesReturned,
281   LPDWORD  lpResumeHandle,
282   LPCSTR  pszGroupName)
283 {
284     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
285     return FALSE;
286 }
287
288
289 /**********************************************************************
290  *  EnumServicesStatusExW
291  *
292  * @unimplemented
293  */
294 BOOL
295 STDCALL
296 EnumServicesStatusExW(SC_HANDLE  hSCManager,
297   SC_ENUM_TYPE  InfoLevel,
298   DWORD  dwServiceType,
299   DWORD  dwServiceState,
300   LPBYTE  lpServices,
301   DWORD  cbBufSize,
302   LPDWORD  pcbBytesNeeded,
303   LPDWORD  lpServicesReturned,
304   LPDWORD  lpResumeHandle,
305   LPCWSTR  pszGroupName)
306 {
307     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
308     return FALSE;
309 }
310
311
312 /**********************************************************************
313  *  EnumServicesStatusW
314  *
315  * @unimplemented
316  */
317 BOOL
318 STDCALL
319 EnumServicesStatusW(
320     SC_HANDLE               hSCManager,
321     DWORD                   dwServiceType,
322     DWORD                   dwServiceState,
323     LPENUM_SERVICE_STATUSW  lpServices,
324     DWORD                   cbBufSize,
325     LPDWORD                 pcbBytesNeeded,
326     LPDWORD                 lpServicesReturned,
327     LPDWORD                 lpResumeHandle)
328 {
329     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
330     return FALSE;
331 }
332
333
334 /**********************************************************************
335  *  GetServiceDisplayNameA
336  *
337  * @unimplemented
338  */
339 BOOL
340 STDCALL
341 GetServiceDisplayNameA(
342     SC_HANDLE   hSCManager,
343     LPCSTR      lpServiceName,
344     LPSTR       lpDisplayName,
345     LPDWORD     lpcchBuffer)
346 {
347     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
348     return FALSE;
349 }
350
351
352 /**********************************************************************
353  *  GetServiceDisplayNameW
354  *
355  * @unimplemented
356  */
357 BOOL
358 STDCALL
359 GetServiceDisplayNameW(
360     SC_HANDLE   hSCManager,
361     LPCWSTR     lpServiceName,
362     LPWSTR      lpDisplayName,
363     LPDWORD     lpcchBuffer)
364 {
365     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
366     return FALSE;
367 }
368
369
370 /**********************************************************************
371  *  GetServiceKeyNameA
372  *
373  * @unimplemented
374  */
375 BOOL
376 STDCALL
377 GetServiceKeyNameA(
378     SC_HANDLE   hSCManager,
379     LPCSTR      lpDisplayName,
380     LPSTR       lpServiceName,
381     LPDWORD     lpcchBuffer)
382 {
383     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
384     return FALSE;
385 }
386
387
388 /**********************************************************************
389  *  GetServiceKeyNameW
390  *
391  * @unimplemented
392  */
393 BOOL
394 STDCALL
395 GetServiceKeyNameW(
396     SC_HANDLE   hSCManager,
397     LPCWSTR     lpDisplayName,
398     LPWSTR      lpServiceName,
399     LPDWORD     lpcchBuffer)
400 {
401     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
402     return FALSE;
403 }
404
405 /**********************************************************************
406  *  LockServiceDatabase
407  *
408  * @unimplemented
409  */
410 SC_LOCK
411 STDCALL
412 LockServiceDatabase(SC_HANDLE   hSCManager)
413 {
414     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
415     return NULL;
416 }
417
418
419 /**********************************************************************
420  *  OpenSCManagerA
421  *
422  * @unplemented
423  */
424 SC_HANDLE STDCALL
425 OpenSCManagerA(LPCSTR lpMachineName,
426            LPCSTR lpDatabaseName,
427            DWORD dwDesiredAccess)
428 {
429   SC_HANDLE Handle;
430   UNICODE_STRING MachineNameW;
431   UNICODE_STRING DatabaseNameW;
432   ANSI_STRING MachineNameA;
433   ANSI_STRING DatabaseNameA;
434
435   DPRINT("OpenSCManagerA(%x, %x, %d)\n", lpMachineName, lpDatabaseName, dwDesiredAccess);
436
437   RtlInitAnsiString(&MachineNameA, (LPSTR)lpMachineName);
438   RtlAnsiStringToUnicodeString(&MachineNameW, &MachineNameA, TRUE);
439   RtlInitAnsiString(&DatabaseNameA, (LPSTR)lpDatabaseName);
440   RtlAnsiStringToUnicodeString(&DatabaseNameW, &DatabaseNameA, TRUE);
441
442   Handle = OpenSCManagerW(lpMachineName ? MachineNameW.Buffer : NULL,
443               lpDatabaseName ? DatabaseNameW.Buffer : NULL,
444               dwDesiredAccess);
445
446   RtlFreeHeap(GetProcessHeap(), 0, MachineNameW.Buffer);
447   RtlFreeHeap(GetProcessHeap(), 0, DatabaseNameW.Buffer);
448   return Handle;
449 }
450
451
452 /**********************************************************************
453  *  OpenSCManagerW
454  *
455  * @unimplemented
456  */
457 SC_HANDLE STDCALL OpenSCManagerW(LPCWSTR lpMachineName,
458                                  LPCWSTR lpDatabaseName,
459                                  DWORD dwDesiredAccess)
460 {
461   HANDLE hPipe;
462   DWORD dwMode;
463   DWORD dwWait;
464   BOOL fSuccess;
465   HANDLE hStartEvent;
466   LPWSTR lpszPipeName = L"\\\\.\\pipe\\Ntsvcs";
467
468   DPRINT("OpenSCManagerW(%x, %x, %d)\n", lpMachineName, lpDatabaseName, dwDesiredAccess);
469
470   if (lpMachineName == NULL || wcslen(lpMachineName) == 0)
471     {
472       if (lpDatabaseName != NULL && wcscmp(lpDatabaseName, SERVICES_ACTIVE_DATABASEW) != 0)
473         {
474           DPRINT("OpenSCManagerW() - Invalid parameters.\n");
475           return NULL; 
476         }
477
478       DPRINT("OpenSCManagerW() - OpenEvent(\"SvcctrlStartEvent_A3725DX\")\n");
479
480       // Only connect to scm when event "SvcctrlStartEvent_A3725DX" is signaled
481       hStartEvent = OpenEventW(SYNCHRONIZE, FALSE, L"SvcctrlStartEvent_A3725DX");
482       if (hStartEvent == NULL)
483         {
484           SetLastError(ERROR_DATABASE_DOES_NOT_EXIST);
485           DPRINT("OpenSCManagerW() - Failed to Open Event \"SvcctrlStartEvent_A3725DX\".\n");
486           return NULL;
487         }
488
489       DPRINT("OpenSCManagerW() - Waiting forever on event handle: %x\n", hStartEvent);
490
491 #if 1
492       dwWait = WaitForSingleObject(hStartEvent, INFINITE);
493       if (dwWait == WAIT_FAILED)
494         {
495           DPRINT("OpenSCManagerW() - Wait For Start Event failed.\n");
496           SetLastError(ERROR_ACCESS_DENIED);
497           return NULL;
498         }
499 #else
500         {
501           DWORD Count;
502
503           /* wait for event creation (by SCM) for max. 20 seconds */
504           for (Count = 0; Count < 20; Count++)
505             {
506               dwWait = WaitForSingleObject(hStartEvent, 1000);
507               if (dwWait == WAIT_FAILED)
508                 {
509                   DPRINT("OpenSCManagerW() - Wait For Start Event failed.\n");
510                   Sleep(1000);
511                 }
512               else
513                 {
514                   break;
515                 }
516             }
517
518           if (dwWait == WAIT_FAILED)
519             {
520               DbgPrint("WL: Failed to wait on event \"SvcctrlStartEvent_A3725DX\"\n");
521             }
522
523         }
524 #endif
525
526       DPRINT("OpenSCManagerW() - Closing handle to event...\n");
527       
528       CloseHandle(hStartEvent);
529       
530       // Try to open a named pipe; wait for it, if necessary
531       while (1)
532       {
533         DWORD dwLastError;
534         DPRINT("OpenSCManagerW() - attempting to open named pipe to SCM.\n");
535         hPipe = CreateFileW(lpszPipeName,     // pipe name
536             dwDesiredAccess,
537             0,                // no sharing
538             NULL,             // no security attributes
539             OPEN_EXISTING,    // opens existing pipe
540             0,                // default attributes
541             NULL);            // no template file
542         
543         DPRINT("OpenSCManagerW() - handle to named pipe: %x\n", hPipe);
544         // Break if the pipe handle is valid
545         if (hPipe != INVALID_HANDLE_VALUE)
546           {
547             break;
548           }
549         
550         // Exit if an error other than ERROR_PIPE_BUSY occurs
551         dwLastError = GetLastError();
552         if (dwLastError != ERROR_PIPE_BUSY)
553           {
554             DPRINT("OpenSCManagerW() - returning at 4, dwLastError %d\n", dwLastError);
555             return NULL;
556           }
557         
558         // All pipe instances are busy, so wait for 20 seconds
559         if (!WaitNamedPipeW(lpszPipeName, 20000))
560           {
561             DPRINT("OpenSCManagerW() - Failed on WaitNamedPipeW(...).\n");
562             return NULL;
563           }
564       }
565     
566       // The pipe connected; change to message-read mode
567       dwMode = PIPE_READMODE_MESSAGE;
568       fSuccess = SetNamedPipeHandleState(
569           hPipe,    // pipe handle
570           &dwMode,  // new pipe mode
571           NULL,     // don't set maximum bytes
572           NULL);    // don't set maximum time
573       if (!fSuccess)
574         {
575           CloseHandle(hPipe);
576           DPRINT("OpenSCManagerW() - Failed on SetNamedPipeHandleState(...).\n");
577           return NULL;
578         }
579 #if 0
580       // Send a message to the pipe server
581       lpvMessage = (argc > 1) ? argv[1] : "default message";
582       
583       fSuccess = WriteFile(
584           hPipe,                  // pipe handle
585           lpvMessage,             // message
586           strlen(lpvMessage) + 1, // message length
587           &cbWritten,             // bytes written
588           NULL);                  // not overlapped
589       if (!fSuccess)
590         {
591           CloseHandle(hPipe);
592           DPRINT("OpenSCManagerW() - Failed to write to pipe.\n");
593           return NULL;
594         }
595       
596       do
597         {
598           DPRINT("OpenSCManagerW() - in I/O loop to SCM...\n");
599           // Read from the pipe
600           fSuccess = ReadFile(
601               hPipe,    // pipe handle
602               chBuf,    // buffer to receive reply
603               512,      // size of buffer
604               &cbRead,  // number of bytes read
605               NULL);    // not overlapped
606           
607           if (!fSuccess && GetLastError() != ERROR_MORE_DATA)
608             {
609               break;
610             }
611           
612           // Reply from the pipe is written to STDOUT.
613           if (!WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), chBuf, cbRead, &cbWritten, NULL))
614             {
615               break;
616             }
617         } while(!fSuccess);  // repeat loop if ERROR_MORE_DATA
618       
619       DPRINT("OpenSCManagerW() - I/O loop completed.\n");
620       //CloseHandle(hPipe);
621 #endif
622       DPRINT("OpenSCManagerW() - success, returning handle to pipe %x\n", hPipe);
623       return hPipe;
624     }
625   else
626     {
627       /* FIXME: Connect to remote SCM */
628       DPRINT("OpenSCManagerW() - FIXME: Connect to remote SCM not implemented.\n");
629       return NULL;
630     }
631 }
632
633
634 /**********************************************************************
635  *  OpenServiceA
636  *
637  * @unimplemented
638  */
639 SC_HANDLE STDCALL
640 OpenServiceA(SC_HANDLE hSCManager,
641          LPCSTR  lpServiceName,
642          DWORD dwDesiredAccess)
643 {
644   SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
645   return NULL;
646 }
647
648
649 /**********************************************************************
650  *  OpenServiceW
651  *
652  * @unimplemented
653  */
654 SC_HANDLE
655 STDCALL
656 OpenServiceW(
657     SC_HANDLE   hSCManager,
658     LPCWSTR     lpServiceName,
659     DWORD       dwDesiredAccess
660     )
661 {
662     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
663     return NULL;
664 }
665
666
667 /**********************************************************************
668  *  QueryServiceConfigA
669  *
670  * @unimplemented
671  */
672 BOOL
673 STDCALL
674 QueryServiceConfigA(
675     SC_HANDLE       hService,
676     LPQUERY_SERVICE_CONFIGA lpServiceConfig,
677     DWORD           cbBufSize,
678     LPDWORD         pcbBytesNeeded)
679 {
680     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
681     return FALSE;
682 }
683
684
685 /**********************************************************************
686  *  QueryServiceConfigW
687  *
688  * @unimplemented
689  */
690 BOOL
691 STDCALL
692 QueryServiceConfigW(
693     SC_HANDLE       hService,
694     LPQUERY_SERVICE_CONFIGW lpServiceConfig,
695     DWORD                   cbBufSize,
696     LPDWORD                 pcbBytesNeeded)
697 {
698     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
699     return FALSE;
700 }
701
702
703 /**********************************************************************
704  *  QueryServiceLockStatusA
705  *
706  * @unimplemented
707  */
708 BOOL
709 STDCALL
710 QueryServiceLockStatusA(
711     SC_HANDLE           hSCManager,
712     LPQUERY_SERVICE_LOCK_STATUSA    lpLockStatus,
713     DWORD               cbBufSize,
714     LPDWORD             pcbBytesNeeded)
715 {
716     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
717     return FALSE;
718 }
719
720
721 /**********************************************************************
722  *  QueryServiceLockStatusW
723  *
724  * @unimplemented
725  */
726 BOOL
727 STDCALL
728 QueryServiceLockStatusW(
729     SC_HANDLE           hSCManager,
730     LPQUERY_SERVICE_LOCK_STATUSW    lpLockStatus,
731     DWORD               cbBufSize,
732     LPDWORD             pcbBytesNeeded)
733 {
734     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
735     return FALSE;
736 }
737
738
739 /**********************************************************************
740  *  QueryServiceObjectSecurity
741  *
742  * @unimplemented
743  */
744 BOOL
745 STDCALL
746 QueryServiceObjectSecurity(
747     SC_HANDLE       hService,
748     SECURITY_INFORMATION    dwSecurityInformation,
749     PSECURITY_DESCRIPTOR    lpSecurityDescriptor,
750     DWORD           cbBufSize,
751     LPDWORD         pcbBytesNeeded)
752 {
753     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
754     return FALSE;
755 }
756
757
758 /**********************************************************************
759  *  QueryServiceStatus
760  *
761  * @unimplemented
762  */
763 BOOL
764 STDCALL
765 QueryServiceStatus(
766     SC_HANDLE       hService,
767     LPSERVICE_STATUS    lpServiceStatus)
768 {
769     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
770     return FALSE;
771 }
772
773
774 /**********************************************************************
775  *  QueryServiceStatusEx
776  *
777  * @unimplemented
778  */
779 BOOL
780 STDCALL
781 QueryServiceStatusEx(SC_HANDLE  hService,
782   SC_STATUS_TYPE  InfoLevel,
783   LPBYTE  lpBuffer,
784   DWORD  cbBufSize,
785   LPDWORD  pcbBytesNeeded)
786 {
787     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
788     return FALSE;
789 }
790
791
792 /**********************************************************************
793  *  StartServiceA
794  *
795  * @unimplemented
796  */
797 BOOL
798 STDCALL
799 StartServiceA(
800     SC_HANDLE   hService,
801     DWORD       dwNumServiceArgs,
802     LPCSTR      *lpServiceArgVectors)
803 {
804     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
805     return FALSE;
806 }
807
808
809
810
811 /**********************************************************************
812  *  StartServiceW
813  *
814  * @unimplemented
815  */
816 BOOL
817 STDCALL
818 StartServiceW(
819     SC_HANDLE   hService,
820     DWORD       dwNumServiceArgs,
821     LPCWSTR     *lpServiceArgVectors)
822 {
823     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
824     return FALSE;
825 }
826
827
828 /**********************************************************************
829  *  UnlockServiceDatabase
830  *
831  * @unimplemented
832  */
833 BOOL
834 STDCALL
835 UnlockServiceDatabase(SC_LOCK   ScLock)
836 {
837     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
838     return FALSE;
839 }
840
841
842 /* EOF */