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