ae519b77c455eddafa228dd60e6dc89acaeb442a
[reactos.git] / reactos / lib / advapi32 / service / scm.c
1 /* $Id: scm.c,v 1.19 2003/08/07 04:03:22 royce Exp $
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 */