- Implement ScmStartServiceA and revert the last modification of StartServiceA.
[reactos.git] / reactos / base / system / services / rpcserver.c
1 /*
2
3 */
4
5 /* INCLUDES ****************************************************************/
6
7 #include "services.h"
8 #include "svcctl_s.h"
9
10 #define NDEBUG
11 #include <debug.h>
12
13
14 /* GLOBALS *****************************************************************/
15
16 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
17 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
18
19 typedef struct _SCMGR_HANDLE
20 {
21 DWORD Tag;
22 DWORD RefCount;
23 DWORD DesiredAccess;
24 } SCMGR_HANDLE;
25
26
27 typedef struct _MANAGER_HANDLE
28 {
29 SCMGR_HANDLE Handle;
30
31 /* FIXME: Insert more data here */
32
33 WCHAR DatabaseName[1];
34 } MANAGER_HANDLE, *PMANAGER_HANDLE;
35
36
37 typedef struct _SERVICE_HANDLE
38 {
39 SCMGR_HANDLE Handle;
40
41 DWORD DesiredAccess;
42 PSERVICE ServiceEntry;
43
44 /* FIXME: Insert more data here */
45
46 } SERVICE_HANDLE, *PSERVICE_HANDLE;
47
48
49 #define SC_MANAGER_READ \
50 (STANDARD_RIGHTS_READ | \
51 SC_MANAGER_QUERY_LOCK_STATUS | \
52 SC_MANAGER_ENUMERATE_SERVICE)
53
54 #define SC_MANAGER_WRITE \
55 (STANDARD_RIGHTS_WRITE | \
56 SC_MANAGER_MODIFY_BOOT_CONFIG | \
57 SC_MANAGER_CREATE_SERVICE)
58
59 #define SC_MANAGER_EXECUTE \
60 (STANDARD_RIGHTS_EXECUTE | \
61 SC_MANAGER_LOCK | \
62 SC_MANAGER_ENUMERATE_SERVICE | \
63 SC_MANAGER_CONNECT | \
64 SC_MANAGER_CREATE_SERVICE)
65
66
67 #define SERVICE_READ \
68 (STANDARD_RIGHTS_READ | \
69 SERVICE_INTERROGATE | \
70 SERVICE_ENUMERATE_DEPENDENTS | \
71 SERVICE_QUERY_STATUS | \
72 SERVICE_QUERY_CONFIG)
73
74 #define SERVICE_WRITE \
75 (STANDARD_RIGHTS_WRITE | \
76 SERVICE_CHANGE_CONFIG)
77
78 #define SERVICE_EXECUTE \
79 (STANDARD_RIGHTS_EXECUTE | \
80 SERVICE_USER_DEFINED_CONTROL | \
81 SERVICE_PAUSE_CONTINUE | \
82 SERVICE_STOP | \
83 SERVICE_START)
84
85
86 /* VARIABLES ***************************************************************/
87
88 static GENERIC_MAPPING
89 ScmManagerMapping = {SC_MANAGER_READ,
90 SC_MANAGER_WRITE,
91 SC_MANAGER_EXECUTE,
92 SC_MANAGER_ALL_ACCESS};
93
94 static GENERIC_MAPPING
95 ScmServiceMapping = {SERVICE_READ,
96 SERVICE_WRITE,
97 SERVICE_EXECUTE,
98 SC_MANAGER_ALL_ACCESS};
99
100
101 /* FUNCTIONS ***************************************************************/
102
103 VOID
104 ScmStartRpcServer(VOID)
105 {
106 RPC_STATUS Status;
107
108 DPRINT("ScmStartRpcServer() called");
109
110 Status = RpcServerUseProtseqEpW(L"ncacn_np",
111 10,
112 L"\\pipe\\ntsvcs",
113 NULL);
114 if (Status != RPC_S_OK)
115 {
116 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status);
117 return;
118 }
119
120 Status = RpcServerRegisterIf(svcctl_ServerIfHandle,
121 NULL,
122 NULL);
123 if (Status != RPC_S_OK)
124 {
125 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status);
126 return;
127 }
128
129 Status = RpcServerListen(1, 20, TRUE);
130 if (Status != RPC_S_OK)
131 {
132 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status);
133 return;
134 }
135
136 DPRINT("ScmStartRpcServer() done");
137 }
138
139
140 static DWORD
141 ScmCreateManagerHandle(LPWSTR lpDatabaseName,
142 SC_HANDLE *Handle)
143 {
144 PMANAGER_HANDLE Ptr;
145
146 if (lpDatabaseName == NULL)
147 lpDatabaseName = SERVICES_ACTIVE_DATABASEW;
148
149 Ptr = HeapAlloc(GetProcessHeap(),
150 HEAP_ZERO_MEMORY,
151 sizeof(MANAGER_HANDLE) + wcslen(lpDatabaseName) * sizeof(WCHAR));
152 if (Ptr == NULL)
153 return ERROR_NOT_ENOUGH_MEMORY;
154
155 Ptr->Handle.Tag = MANAGER_TAG;
156 Ptr->Handle.RefCount = 1;
157
158 /* FIXME: initialize more data here */
159
160 wcscpy(Ptr->DatabaseName, lpDatabaseName);
161
162 *Handle = (SC_HANDLE)Ptr;
163
164 return ERROR_SUCCESS;
165 }
166
167
168 static DWORD
169 ScmCreateServiceHandle(PSERVICE lpServiceEntry,
170 SC_HANDLE *Handle)
171 {
172 PSERVICE_HANDLE Ptr;
173
174 Ptr = HeapAlloc(GetProcessHeap(),
175 HEAP_ZERO_MEMORY,
176 sizeof(SERVICE_HANDLE));
177 if (Ptr == NULL)
178 return ERROR_NOT_ENOUGH_MEMORY;
179
180 Ptr->Handle.Tag = SERVICE_TAG;
181 Ptr->Handle.RefCount = 1;
182
183 /* FIXME: initialize more data here */
184 Ptr->ServiceEntry = lpServiceEntry;
185
186 *Handle = (SC_HANDLE)Ptr;
187
188 return ERROR_SUCCESS;
189 }
190
191
192 static DWORD
193 ScmCheckAccess(SC_HANDLE Handle,
194 DWORD dwDesiredAccess)
195 {
196 PMANAGER_HANDLE hMgr;
197
198 hMgr = (PMANAGER_HANDLE)Handle;
199 if (hMgr->Handle.Tag == MANAGER_TAG)
200 {
201 RtlMapGenericMask(&dwDesiredAccess,
202 &ScmManagerMapping);
203
204 hMgr->Handle.DesiredAccess = dwDesiredAccess;
205
206 return ERROR_SUCCESS;
207 }
208 else if (hMgr->Handle.Tag == SERVICE_TAG)
209 {
210 RtlMapGenericMask(&dwDesiredAccess,
211 &ScmServiceMapping);
212
213 hMgr->Handle.DesiredAccess = dwDesiredAccess;
214
215 return ERROR_SUCCESS;
216 }
217
218 return ERROR_INVALID_HANDLE;
219 }
220
221
222 DWORD
223 ScmAssignNewTag(PSERVICE lpService)
224 {
225 /* FIXME */
226 DPRINT("Assigning new tag to service %S\n", lpService->lpServiceName);
227 lpService->dwTag = 0;
228 return ERROR_SUCCESS;
229 }
230
231
232 /* Function 0 */
233 unsigned long
234 ScmrCloseServiceHandle(handle_t BindingHandle,
235 unsigned int hScObject)
236 {
237 PMANAGER_HANDLE hManager;
238
239 DPRINT("ScmrCloseServiceHandle() called\n");
240
241 DPRINT("hScObject = %X\n", hScObject);
242
243 if (hScObject == 0)
244 return ERROR_INVALID_HANDLE;
245
246 hManager = (PMANAGER_HANDLE)hScObject;
247 if (hManager->Handle.Tag == MANAGER_TAG)
248 {
249 DPRINT("Found manager handle\n");
250
251 hManager->Handle.RefCount--;
252 if (hManager->Handle.RefCount == 0)
253 {
254 /* FIXME: add cleanup code */
255
256 HeapFree(GetProcessHeap(), 0, hManager);
257 }
258
259 DPRINT("ScmrCloseServiceHandle() done\n");
260 return ERROR_SUCCESS;
261 }
262 else if (hManager->Handle.Tag == SERVICE_TAG)
263 {
264 DPRINT("Found service handle\n");
265
266 hManager->Handle.RefCount--;
267 if (hManager->Handle.RefCount == 0)
268 {
269 /* FIXME: add cleanup code */
270
271 HeapFree(GetProcessHeap(), 0, hManager);
272 }
273
274 DPRINT("ScmrCloseServiceHandle() done\n");
275 return ERROR_SUCCESS;
276 }
277
278 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag);
279
280 return ERROR_INVALID_HANDLE;
281 }
282
283
284 /* Function 1 */
285 unsigned long
286 ScmrControlService(handle_t BindingHandle,
287 unsigned int hService,
288 unsigned long dwControl,
289 LPSERVICE_STATUS lpServiceStatus)
290 {
291 PSERVICE_HANDLE hSvc;
292 PSERVICE lpService;
293 ACCESS_MASK DesiredAccess;
294 DWORD dwError = ERROR_SUCCESS;
295
296 DPRINT("ScmrControlService() called\n");
297
298 if (ScmShutdown)
299 return ERROR_SHUTDOWN_IN_PROGRESS;
300
301 /* Check the service handle */
302 hSvc = (PSERVICE_HANDLE)hService;
303 if (hSvc->Handle.Tag != SERVICE_TAG)
304 {
305 DPRINT1("Invalid handle tag!\n");
306 return ERROR_INVALID_HANDLE;
307 }
308
309 /* Check access rights */
310 switch (dwControl)
311 {
312 case SERVICE_CONTROL_STOP:
313 DesiredAccess = SERVICE_STOP;
314 break;
315
316 case SERVICE_CONTROL_PAUSE:
317 case SERVICE_CONTROL_CONTINUE:
318 DesiredAccess = SERVICE_PAUSE_CONTINUE;
319 break;
320
321 case SERVICE_INTERROGATE:
322 DesiredAccess = SERVICE_INTERROGATE;
323 break;
324
325 default:
326 if (dwControl >= 128 && dwControl <= 255)
327 DesiredAccess = SERVICE_USER_DEFINED_CONTROL;
328 else
329 DesiredAccess = SERVICE_QUERY_CONFIG |
330 SERVICE_CHANGE_CONFIG |
331 SERVICE_QUERY_STATUS |
332 SERVICE_START |
333 SERVICE_PAUSE_CONTINUE;
334 break;
335 }
336
337 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
338 DesiredAccess))
339 return ERROR_ACCESS_DENIED;
340
341 /* Check the service entry point */
342 lpService = hSvc->ServiceEntry;
343 if (lpService == NULL)
344 {
345 DPRINT1("lpService == NULL!\n");
346 return ERROR_INVALID_HANDLE;
347 }
348
349 if (lpService->Status.dwServiceType & SERVICE_DRIVER)
350 {
351 /* Send control code to the driver */
352 dwError = ScmControlDriver(lpService,
353 dwControl,
354 lpServiceStatus);
355 }
356 else
357 {
358 /* FIXME: Send control code to the service */
359 #if 0
360 dwError = ScmControlService(lpService,
361 dwControl,
362 lpServiceStatus);
363 #endif
364 dwError = ERROR_INVALID_SERVICE_CONTROL;
365 }
366
367 /* Return service status information */
368 RtlCopyMemory(lpServiceStatus,
369 &lpService->Status,
370 sizeof(SERVICE_STATUS));
371
372 return dwError;
373 }
374
375
376 /* Function 2 */
377 unsigned long
378 ScmrDeleteService(handle_t BindingHandle,
379 unsigned int hService)
380 {
381 PSERVICE_HANDLE hSvc;
382 PSERVICE lpService;
383 DWORD dwError;
384
385 DPRINT("ScmrDeleteService() called\n");
386
387 if (ScmShutdown)
388 return ERROR_SHUTDOWN_IN_PROGRESS;
389
390 hSvc = (PSERVICE_HANDLE)hService;
391 if (hSvc->Handle.Tag != SERVICE_TAG)
392 return ERROR_INVALID_HANDLE;
393
394 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
395 STANDARD_RIGHTS_REQUIRED))
396 return ERROR_ACCESS_DENIED;
397
398 lpService = hSvc->ServiceEntry;
399 if (lpService == NULL)
400 {
401 DPRINT1("lpService == NULL!\n");
402 return ERROR_INVALID_HANDLE;
403 }
404
405 /* FIXME: Acquire service database lock exclusively */
406
407 if (lpService->bDeleted)
408 {
409 DPRINT1("The service has already been marked for delete!\n");
410 return ERROR_SERVICE_MARKED_FOR_DELETE;
411 }
412
413 /* Mark service for delete */
414 lpService->bDeleted = TRUE;
415
416 dwError = ScmMarkServiceForDelete(lpService);
417
418 /* FIXME: Release service database lock */
419
420 DPRINT("ScmrDeleteService() done\n");
421
422 return dwError;
423 }
424
425
426 /* Function 3 */
427 unsigned long
428 ScmrLockServiceDatabase(handle_t BindingHandle,
429 unsigned int hSCManager,
430 unsigned int *hLock)
431 {
432 PMANAGER_HANDLE hMgr;
433
434 DPRINT("ScmrLockServiceDatabase() called\n");
435
436 *hLock = 0;
437
438 hMgr = (PMANAGER_HANDLE)hSCManager;
439 if (hMgr->Handle.Tag != MANAGER_TAG)
440 return ERROR_INVALID_HANDLE;
441
442 if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess,
443 SC_MANAGER_LOCK))
444 return ERROR_ACCESS_DENIED;
445
446 // return ScmLockDatabase(0, hMgr->0xC, hLock);
447
448 /* FIXME: Lock the database */
449 *hLock = 0x12345678; /* Dummy! */
450
451 return ERROR_SUCCESS;
452 }
453
454
455 /* Function 4 */
456 unsigned long
457 ScmrQueryServiceObjectSecurity(handle_t BindingHandle,
458 unsigned int hService,
459 unsigned long dwSecurityInformation,
460 unsigned char *lpSecurityDescriptor,
461 unsigned long dwSecuityDescriptorSize,
462 unsigned long *pcbBytesNeeded)
463 {
464 #if 0
465 PSERVICE_HANDLE hSvc;
466 PSERVICE lpService;
467 ULONG DesiredAccess = 0;
468 NTSTATUS Status;
469 DWORD dwBytesNeeded;
470 DWORD dwError;
471
472 DPRINT("ScmrQueryServiceObjectSecurity() called\n");
473
474 hSvc = (PSERVICE_HANDLE)hService;
475 if (hSvc->Handle.Tag != SERVICE_TAG)
476 {
477 DPRINT1("Invalid handle tag!\n");
478 return ERROR_INVALID_HANDLE;
479 }
480
481 if (dwSecurityInformation & (DACL_SECURITY_INFORMATION ||
482 GROUP_SECURITY_INFORMATION ||
483 OWNER_SECURITY_INFORMATION))
484 DesiredAccess |= READ_CONTROL;
485
486 if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
487 DesiredAccess |= ACCESS_SYSTEM_SECURITY;
488
489 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
490 DesiredAccess))
491 {
492 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
493 return ERROR_ACCESS_DENIED;
494 }
495
496 lpService = hSvc->ServiceEntry;
497 if (lpService == NULL)
498 {
499 DPRINT1("lpService == NULL!\n");
500 return ERROR_INVALID_HANDLE;
501 }
502
503 /* FIXME: Lock the service list */
504
505 Status = RtlQuerySecurityObject(lpService->lpSecurityDescriptor,
506 dwSecurityInformation,
507 (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
508 dwSecuityDescriptorSize,
509 &dwBytesNeeded);
510
511 /* FIXME: Unlock the service list */
512
513 if (NT_SUCCESS(Status))
514 {
515 *pcbBytesNeeded = dwBytesNeeded;
516 dwError = STATUS_SUCCESS;
517 }
518 else if (Status == STATUS_BUFFER_TOO_SMALL)
519 {
520 *pcbBytesNeeded = dwBytesNeeded;
521 dwError = ERROR_INSUFFICIENT_BUFFER;
522 }
523 else if (Status == STATUS_BAD_DESCRIPTOR_FORMAT)
524 {
525 dwError = ERROR_GEN_FAILURE;
526 }
527 else
528 {
529 dwError = RtlNtStatusToDosError(Status);
530 }
531
532 return dwError;
533 #endif
534 DPRINT1("ScmrQueryServiceObjectSecurity() is unimplemented\n");
535 return ERROR_CALL_NOT_IMPLEMENTED;
536 }
537
538
539 /* Function 5 */
540 unsigned long
541 ScmrSetServiceObjectSecurity(handle_t BindingHandle,
542 unsigned int hService,
543 unsigned long dwSecurityInformation,
544 unsigned char *lpSecurityDescriptor,
545 unsigned long dwSecuityDescriptorSize)
546 {
547 #if 0
548 PSERVICE_HANDLE hSvc;
549 PSERVICE lpService;
550 ULONG DesiredAccess = 0;
551 HANDLE hToken = NULL;
552 HKEY hServiceKey;
553 NTSTATUS Status;
554 DWORD dwError;
555
556 DPRINT1("ScmrSetServiceObjectSecurity() called\n");
557
558 hSvc = (PSERVICE_HANDLE)hService;
559 if (hSvc->Handle.Tag != SERVICE_TAG)
560 {
561 DPRINT1("Invalid handle tag!\n");
562 return ERROR_INVALID_HANDLE;
563 }
564
565 if (dwSecurityInformation == 0 ||
566 dwSecurityInformation & ~0xF)
567 return 0x57;
568
569 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR)lpSecurityDescriptor))
570 return 0x57;
571
572 if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
573 DesiredAccess |= ACCESS_SYSTEM_SECURITY;
574
575 if (dwSecurityInformation & DACL_SECURITY_INFORMATION)
576 DesiredAccess |= 0x40000;
577
578 if (dwSecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
579 DesiredAccess |= 0x80000;
580
581 if ((dwSecurityInformation & OWNER_SECURITY_INFORMATION) &&
582 (((PSECURITY_DESCRIPTOR)lpSecurityDescriptor)->Owner == NULL))
583 return 0x57;
584
585 if ((dwSecurityInformation & GROUP_SECURITY_INFORMATION) &&
586 (((PSECURITY_DESCRIPTOR)lpSecurityDescriptor)->Group == NULL))
587 return 0x57;
588
589 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
590 DesiredAccess))
591 {
592 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
593 return ERROR_ACCESS_DENIED;
594 }
595
596 lpService = hSvc->ServiceEntry;
597 if (lpService == NULL)
598 {
599 DPRINT1("lpService == NULL!\n");
600 return ERROR_INVALID_HANDLE;
601 }
602
603 if (lpService->bDeleted)
604 return 0x430;
605
606 // RpcImpersonateClient(NULL);
607
608 Status = NtOpenThreadToken(NtCurrentThread(),
609 8,
610 1,
611 &hToken);
612 if (!NT_SUCCESS(Status))
613 return RtlNtStatusToDosError(Status);
614
615 // RpcRevertToSelf();
616
617 /* FIXME: Lock service database */
618
619 Status = RtlSetSecurityObject(dwSecurityInformation,
620 (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
621 &lpService->lpSecurityDescriptor,
622 &ScmServiceMapping,
623 hToken);
624 if (!NT_SUCCESS(Status))
625 {
626 dwError = RtlNtStatusToDosError(Status);
627 goto Done;
628 }
629
630 dwError = ScmOpenServiceKey(lpService->lpServiceName,
631 0x20006,
632 &hServiceKey);
633 if (dwError != ERROR_SUCCESS)
634 goto Done;
635
636 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
637 // lpService->lpSecurityDescriptor);
638
639 RegFlushKey(hServiceKey);
640 RegCloseKey(hServiceKey);
641
642 Done:;
643
644 if (hToken != NULL)
645 NtClose(hToken);
646
647 /* FIXME: Unlock service database */
648
649 DPRINT1("ScmrSetServiceObjectSecurity() done (Error %lu)\n", dwError);
650
651 return dwError;
652 #endif
653
654 DPRINT1("ScmrSetServiceObjectSecurity() is unimplemented\n");
655 return ERROR_CALL_NOT_IMPLEMENTED;
656 }
657
658
659 /* Function 6 */
660 unsigned long
661 ScmrQueryServiceStatus(handle_t BindingHandle,
662 unsigned int hService,
663 LPSERVICE_STATUS lpServiceStatus)
664 {
665 PSERVICE_HANDLE hSvc;
666 PSERVICE lpService;
667
668 DPRINT("ScmrQueryServiceStatus() called\n");
669
670 if (ScmShutdown)
671 return ERROR_SHUTDOWN_IN_PROGRESS;
672
673 hSvc = (PSERVICE_HANDLE)hService;
674 if (hSvc->Handle.Tag != SERVICE_TAG)
675 {
676 DPRINT1("Invalid handle tag!\n");
677 return ERROR_INVALID_HANDLE;
678 }
679
680 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
681 SERVICE_QUERY_STATUS))
682 {
683 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
684 return ERROR_ACCESS_DENIED;
685 }
686
687 lpService = hSvc->ServiceEntry;
688 if (lpService == NULL)
689 {
690 DPRINT1("lpService == NULL!\n");
691 return ERROR_INVALID_HANDLE;
692 }
693
694 /* Return service status information */
695 RtlCopyMemory(lpServiceStatus,
696 &lpService->Status,
697 sizeof(SERVICE_STATUS));
698
699 return ERROR_SUCCESS;
700 }
701
702
703 /* Function 7 */
704 unsigned long
705 ScmrSetServiceStatus(handle_t BindingHandle,
706 unsigned long hServiceStatus) /* FIXME */
707 {
708 DPRINT1("ScmrSetServiceStatus() is unimplemented\n");
709 /* FIXME */
710 return ERROR_CALL_NOT_IMPLEMENTED;
711 }
712
713
714 /* Function 8 */
715 unsigned long
716 ScmrUnlockServiceDatabase(handle_t BindingHandle,
717 unsigned int hLock)
718 {
719 DPRINT1("ScmrUnlockServiceDatabase() called\n");
720 /* FIXME */
721 return ERROR_SUCCESS;
722 }
723
724
725 /* Function 9 */
726 unsigned long
727 ScmrNotifyBootConfigStatus(handle_t BindingHandle,
728 unsigned long BootAcceptable)
729 {
730 DPRINT1("ScmrNotifyBootConfigStatus() called\n");
731 /* FIXME */
732 return ERROR_CALL_NOT_IMPLEMENTED;
733 }
734
735
736 /* Function 10 */
737 unsigned long
738 ScmrSetServiceBitsW(handle_t BindingHandle,
739 unsigned long hServiceStatus,
740 unsigned long dwServiceBits,
741 unsigned long bSetBitsOn,
742 unsigned long bUpdateImmediately,
743 wchar_t *lpString)
744 {
745 DPRINT1("ScmrSetServiceBitsW() called\n");
746 /* FIXME */
747 return ERROR_CALL_NOT_IMPLEMENTED;
748 }
749
750
751 /* Function 11 */
752 unsigned long
753 ScmrChangeServiceConfigW(handle_t BiningHandle,
754 unsigned int hService,
755 unsigned long dwServiceType,
756 unsigned long dwStartType,
757 unsigned long dwErrorControl,
758 wchar_t *lpBinaryPathName,
759 wchar_t *lpLoadOrderGroup,
760 unsigned long *lpdwTagId, /* in, out, unique */
761 wchar_t *lpDependencies,
762 unsigned long dwDependenciesLength,
763 wchar_t *lpServiceStartName,
764 wchar_t *lpPassword,
765 unsigned long dwPasswordLength,
766 wchar_t *lpDisplayName)
767 {
768 DWORD dwError = ERROR_SUCCESS;
769 PSERVICE_HANDLE hSvc;
770 PSERVICE lpService = NULL;
771 HKEY hServiceKey = NULL;
772
773 DPRINT("ScmrChangeServiceConfigW() called\n");
774 DPRINT("dwServiceType = %lu\n", dwServiceType);
775 DPRINT("dwStartType = %lu\n", dwStartType);
776 DPRINT("dwErrorControl = %lu\n", dwErrorControl);
777 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
778 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
779 DPRINT("lpDisplayName = %S\n", lpDisplayName);
780
781 if (ScmShutdown)
782 return ERROR_SHUTDOWN_IN_PROGRESS;
783
784 hSvc = (PSERVICE_HANDLE)hService;
785 if (hSvc->Handle.Tag != SERVICE_TAG)
786 {
787 DPRINT1("Invalid handle tag!\n");
788 return ERROR_INVALID_HANDLE;
789 }
790
791 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
792 SERVICE_CHANGE_CONFIG))
793 {
794 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
795 return ERROR_ACCESS_DENIED;
796 }
797
798 lpService = hSvc->ServiceEntry;
799 if (lpService == NULL)
800 {
801 DPRINT1("lpService == NULL!\n");
802 return ERROR_INVALID_HANDLE;
803 }
804
805 /* FIXME: Lock database exclusively */
806
807 if (lpService->bDeleted)
808 {
809 /* FIXME: Unlock database */
810 DPRINT1("The service has already been marked for delete!\n");
811 return ERROR_SERVICE_MARKED_FOR_DELETE;
812 }
813
814 /* Open the service key */
815 dwError = ScmOpenServiceKey(lpService->szServiceName,
816 KEY_SET_VALUE,
817 &hServiceKey);
818 if (dwError != ERROR_SUCCESS)
819 goto done;
820
821 /* Write service data to the registry */
822 /* Set the display name */
823 if (lpDisplayName != NULL && *lpDisplayName != 0)
824 {
825 RegSetValueExW(hServiceKey,
826 L"DisplayName",
827 0,
828 REG_SZ,
829 (LPBYTE)lpDisplayName,
830 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
831 /* FIXME: update lpService->lpDisplayName */
832 }
833
834 if (dwServiceType != SERVICE_NO_CHANGE)
835 {
836 /* Set the service type */
837 dwError = RegSetValueExW(hServiceKey,
838 L"Type",
839 0,
840 REG_DWORD,
841 (LPBYTE)&dwServiceType,
842 sizeof(DWORD));
843 if (dwError != ERROR_SUCCESS)
844 goto done;
845
846 lpService->Status.dwServiceType = dwServiceType;
847 }
848
849 if (dwStartType != SERVICE_NO_CHANGE)
850 {
851 /* Set the start value */
852 dwError = RegSetValueExW(hServiceKey,
853 L"Start",
854 0,
855 REG_DWORD,
856 (LPBYTE)&dwStartType,
857 sizeof(DWORD));
858 if (dwError != ERROR_SUCCESS)
859 goto done;
860
861 lpService->dwStartType = dwStartType;
862 }
863
864 if (dwErrorControl != SERVICE_NO_CHANGE)
865 {
866 /* Set the error control value */
867 dwError = RegSetValueExW(hServiceKey,
868 L"ErrorControl",
869 0,
870 REG_DWORD,
871 (LPBYTE)&dwErrorControl,
872 sizeof(DWORD));
873 if (dwError != ERROR_SUCCESS)
874 goto done;
875
876 lpService->dwErrorControl = dwErrorControl;
877 }
878
879 #if 0
880 /* FIXME: set the new ImagePath value */
881
882 /* Set the image path */
883 if (dwServiceType & SERVICE_WIN32)
884 {
885 if (lpBinaryPathName != NULL && *lpBinaryPathName != 0)
886 {
887 dwError = RegSetValueExW(hServiceKey,
888 L"ImagePath",
889 0,
890 REG_EXPAND_SZ,
891 (LPBYTE)lpBinaryPathName,
892 (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
893 if (dwError != ERROR_SUCCESS)
894 goto done;
895 }
896 }
897 else if (dwServiceType & SERVICE_DRIVER)
898 {
899 if (lpImagePath != NULL && *lpImagePath != 0)
900 {
901 dwError = RegSetValueExW(hServiceKey,
902 L"ImagePath",
903 0,
904 REG_EXPAND_SZ,
905 (LPBYTE)lpImagePath,
906 (wcslen(lpImagePath) + 1) *sizeof(WCHAR));
907 if (dwError != ERROR_SUCCESS)
908 goto done;
909 }
910 }
911 #endif
912
913 /* Set the group name */
914 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
915 {
916 dwError = RegSetValueExW(hServiceKey,
917 L"Group",
918 0,
919 REG_SZ,
920 (LPBYTE)lpLoadOrderGroup,
921 (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
922 if (dwError != ERROR_SUCCESS)
923 goto done;
924 /* FIXME: update lpService->lpServiceGroup */
925 }
926
927 if (lpdwTagId != NULL)
928 {
929 dwError = ScmAssignNewTag(lpService);
930 if (dwError != ERROR_SUCCESS)
931 goto done;
932
933 dwError = RegSetValueExW(hServiceKey,
934 L"Tag",
935 0,
936 REG_DWORD,
937 (LPBYTE)&lpService->dwTag,
938 sizeof(DWORD));
939 if (dwError != ERROR_SUCCESS)
940 goto done;
941
942 *lpdwTagId = lpService->dwTag;
943 }
944
945 /* Write dependencies */
946 if (lpDependencies != NULL && *lpDependencies != 0)
947 {
948 dwError = ScmWriteDependencies(hServiceKey,
949 lpDependencies,
950 dwDependenciesLength);
951 if (dwError != ERROR_SUCCESS)
952 goto done;
953 }
954
955 if (lpPassword != NULL)
956 {
957 /* FIXME: Write password */
958 }
959
960 /* FIXME: Unlock database */
961
962 done:
963 if (hServiceKey != NULL)
964 RegCloseKey(hServiceKey);
965
966 DPRINT("ScmrChangeServiceConfigW() done (Error %lu)\n", dwError);
967
968 return dwError;
969 }
970
971
972 /* Function 12 */
973 unsigned long
974 ScmrCreateServiceW(handle_t BindingHandle,
975 unsigned int hSCManager,
976 wchar_t *lpServiceName,
977 wchar_t *lpDisplayName,
978 unsigned long dwDesiredAccess,
979 unsigned long dwServiceType,
980 unsigned long dwStartType,
981 unsigned long dwErrorControl,
982 wchar_t *lpBinaryPathName,
983 wchar_t *lpLoadOrderGroup,
984 unsigned long *lpdwTagId, /* in, out */
985 wchar_t *lpDependencies,
986 unsigned long dwDependenciesLength,
987 wchar_t *lpServiceStartName,
988 wchar_t *lpPassword,
989 unsigned long dwPasswordLength,
990 unsigned int *hService) /* out */
991 {
992 PMANAGER_HANDLE hManager;
993 DWORD dwError = ERROR_SUCCESS;
994 PSERVICE lpService = NULL;
995 SC_HANDLE hServiceHandle = NULL;
996 LPWSTR lpImagePath = NULL;
997 HKEY hServiceKey = NULL;
998
999 DPRINT("ScmrCreateServiceW() called\n");
1000 DPRINT("lpServiceName = %S\n", lpServiceName);
1001 DPRINT("lpDisplayName = %S\n", lpDisplayName);
1002 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess);
1003 DPRINT("dwServiceType = %lu\n", dwServiceType);
1004 DPRINT("dwStartType = %lu\n", dwStartType);
1005 DPRINT("dwErrorControl = %lu\n", dwErrorControl);
1006 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
1007 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
1008
1009 if (ScmShutdown)
1010 return ERROR_SHUTDOWN_IN_PROGRESS;
1011
1012 hManager = (PMANAGER_HANDLE)hSCManager;
1013 if (hManager->Handle.Tag != MANAGER_TAG)
1014 {
1015 DPRINT1("Invalid manager handle!\n");
1016 return ERROR_INVALID_HANDLE;
1017 }
1018
1019 /* Check access rights */
1020 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
1021 SC_MANAGER_CREATE_SERVICE))
1022 {
1023 DPRINT1("Insufficient access rights! 0x%lx\n",
1024 hManager->Handle.DesiredAccess);
1025 return ERROR_ACCESS_DENIED;
1026 }
1027
1028 /* Fail if the service already exists! */
1029 if (ScmGetServiceEntryByName(lpServiceName) != NULL)
1030 return ERROR_SERVICE_EXISTS;
1031
1032 if (dwServiceType & SERVICE_DRIVER)
1033 {
1034 /* FIXME: Adjust the image path
1035 * Following line is VERY BAD, because it assumes that the
1036 * first part of full file name is the OS directory */
1037 if (lpBinaryPathName[1] == ':') lpBinaryPathName += GetWindowsDirectoryW(NULL, 0);
1038
1039 lpImagePath = HeapAlloc(GetProcessHeap(),
1040 HEAP_ZERO_MEMORY,
1041 (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
1042 if (lpImagePath == NULL)
1043 {
1044 dwError = ERROR_NOT_ENOUGH_MEMORY;
1045 goto done;
1046 }
1047 wcscpy(lpImagePath, lpBinaryPathName);
1048 }
1049
1050 /* Allocate a new service entry */
1051 dwError = ScmCreateNewServiceRecord(lpServiceName,
1052 &lpService);
1053 if (dwError != ERROR_SUCCESS)
1054 goto done;
1055
1056 /* Fill the new service entry */
1057 lpService->Status.dwServiceType = dwServiceType;
1058 lpService->dwStartType = dwStartType;
1059 lpService->dwErrorControl = dwErrorControl;
1060
1061 /* Fill the display name */
1062 if (lpDisplayName != NULL &&
1063 *lpDisplayName != 0 &&
1064 wcsicmp(lpService->lpDisplayName, lpDisplayName) != 0)
1065 {
1066 lpService->lpDisplayName = HeapAlloc(GetProcessHeap(), 0,
1067 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
1068 if (lpService->lpDisplayName == NULL)
1069 {
1070 dwError = ERROR_NOT_ENOUGH_MEMORY;
1071 goto done;
1072 }
1073 wcscpy(lpService->lpDisplayName, lpDisplayName);
1074 }
1075
1076 /* Assign the service to a group */
1077 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
1078 {
1079 dwError = ScmSetServiceGroup(lpService,
1080 lpLoadOrderGroup);
1081 if (dwError != ERROR_SUCCESS)
1082 goto done;
1083 }
1084
1085 /* Assign a new tag */
1086 if (lpdwTagId != NULL)
1087 {
1088 dwError = ScmAssignNewTag(lpService);
1089 if (dwError != ERROR_SUCCESS)
1090 goto done;
1091 }
1092
1093 /* Write service data to the registry */
1094 /* Create the service key */
1095 dwError = ScmCreateServiceKey(lpServiceName,
1096 KEY_WRITE,
1097 &hServiceKey);
1098 if (dwError != ERROR_SUCCESS)
1099 goto done;
1100
1101 /* Set the display name */
1102 if (lpDisplayName != NULL && *lpDisplayName != 0)
1103 {
1104 RegSetValueExW(hServiceKey,
1105 L"DisplayName",
1106 0,
1107 REG_SZ,
1108 (LPBYTE)lpDisplayName,
1109 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
1110 }
1111
1112 /* Set the service type */
1113 dwError = RegSetValueExW(hServiceKey,
1114 L"Type",
1115 0,
1116 REG_DWORD,
1117 (LPBYTE)&dwServiceType,
1118 sizeof(DWORD));
1119 if (dwError != ERROR_SUCCESS)
1120 goto done;
1121
1122 /* Set the start value */
1123 dwError = RegSetValueExW(hServiceKey,
1124 L"Start",
1125 0,
1126 REG_DWORD,
1127 (LPBYTE)&dwStartType,
1128 sizeof(DWORD));
1129 if (dwError != ERROR_SUCCESS)
1130 goto done;
1131
1132 /* Set the error control value */
1133 dwError = RegSetValueExW(hServiceKey,
1134 L"ErrorControl",
1135 0,
1136 REG_DWORD,
1137 (LPBYTE)&dwErrorControl,
1138 sizeof(DWORD));
1139 if (dwError != ERROR_SUCCESS)
1140 goto done;
1141
1142 /* Set the image path */
1143 if (dwServiceType & SERVICE_WIN32)
1144 {
1145 dwError = RegSetValueExW(hServiceKey,
1146 L"ImagePath",
1147 0,
1148 REG_EXPAND_SZ,
1149 (LPBYTE)lpBinaryPathName,
1150 (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
1151 if (dwError != ERROR_SUCCESS)
1152 goto done;
1153 }
1154 else if (dwServiceType & SERVICE_DRIVER)
1155 {
1156 dwError = RegSetValueExW(hServiceKey,
1157 L"ImagePath",
1158 0,
1159 REG_EXPAND_SZ,
1160 (LPBYTE)lpImagePath,
1161 (wcslen(lpImagePath) + 1) *sizeof(WCHAR));
1162 if (dwError != ERROR_SUCCESS)
1163 goto done;
1164 }
1165
1166 /* Set the group name */
1167 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
1168 {
1169 dwError = RegSetValueExW(hServiceKey,
1170 L"Group",
1171 0,
1172 REG_SZ,
1173 (LPBYTE)lpLoadOrderGroup,
1174 (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
1175 if (dwError != ERROR_SUCCESS)
1176 goto done;
1177 }
1178
1179 if (lpdwTagId != NULL)
1180 {
1181 dwError = RegSetValueExW(hServiceKey,
1182 L"Tag",
1183 0,
1184 REG_DWORD,
1185 (LPBYTE)&lpService->dwTag,
1186 sizeof(DWORD));
1187 if (dwError != ERROR_SUCCESS)
1188 goto done;
1189 }
1190
1191 /* Write dependencies */
1192 if (lpDependencies != NULL && *lpDependencies != 0)
1193 {
1194 dwError = ScmWriteDependencies(hServiceKey,
1195 lpDependencies,
1196 dwDependenciesLength);
1197 if (dwError != ERROR_SUCCESS)
1198 goto done;
1199 }
1200
1201 if (lpPassword != NULL)
1202 {
1203 /* FIXME: Write password */
1204 }
1205
1206 dwError = ScmCreateServiceHandle(lpService,
1207 &hServiceHandle);
1208 if (dwError != ERROR_SUCCESS)
1209 goto done;
1210
1211 dwError = ScmCheckAccess(hServiceHandle,
1212 dwDesiredAccess);
1213 if (dwError != ERROR_SUCCESS)
1214 goto done;
1215
1216 done:;
1217 if (hServiceKey != NULL)
1218 RegCloseKey(hServiceKey);
1219
1220 if (dwError == ERROR_SUCCESS)
1221 {
1222 DPRINT("hService %lx\n", hServiceHandle);
1223 *hService = (unsigned int)hServiceHandle;
1224
1225 if (lpdwTagId != NULL)
1226 *lpdwTagId = lpService->dwTag;
1227 }
1228 else
1229 {
1230 /* Release the display name buffer */
1231 if (lpService->lpServiceName != lpService->lpDisplayName)
1232 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
1233
1234 if (hServiceHandle != NULL)
1235 {
1236 /* Remove the service handle */
1237 HeapFree(GetProcessHeap(), 0, hServiceHandle);
1238 }
1239
1240 if (lpService != NULL)
1241 {
1242 /* FIXME: remove the service entry */
1243 }
1244 }
1245
1246 if (lpImagePath != NULL)
1247 HeapFree(GetProcessHeap(), 0, lpImagePath);
1248
1249 DPRINT("ScmrCreateServiceW() done (Error %lu)\n", dwError);
1250
1251 return dwError;
1252 }
1253
1254
1255 /* Function 13 */
1256 unsigned long
1257 ScmrEnumDependentServicesW(handle_t BindingHandle,
1258 unsigned int hService,
1259 unsigned long dwServiceState,
1260 unsigned char *lpServices,
1261 unsigned long cbBufSize,
1262 unsigned long *pcbBytesNeeded,
1263 unsigned long *lpServicesReturned)
1264 {
1265 DWORD dwError = ERROR_SUCCESS;
1266
1267 DPRINT1("ScmrEnumDependentServicesW() called\n");
1268 *pcbBytesNeeded = 0;
1269 *lpServicesReturned = 0;
1270
1271 DPRINT1("ScmrEnumDependentServicesW() done (Error %lu)\n", dwError);
1272
1273 return dwError;
1274 }
1275
1276
1277 /* Function 14 */
1278 unsigned long
1279 ScmrEnumServicesStatusW(handle_t BindingHandle,
1280 unsigned int hSCManager,
1281 unsigned long dwServiceType,
1282 unsigned long dwServiceState,
1283 unsigned char *lpServices,
1284 unsigned long dwBufSize,
1285 unsigned long *pcbBytesNeeded,
1286 unsigned long *lpServicesReturned,
1287 unsigned long *lpResumeHandle)
1288 {
1289 PMANAGER_HANDLE hManager;
1290 PSERVICE lpService;
1291 DWORD dwError = ERROR_SUCCESS;
1292 PLIST_ENTRY ServiceEntry;
1293 PSERVICE CurrentService;
1294 DWORD dwState;
1295 DWORD dwRequiredSize;
1296 DWORD dwServiceCount;
1297 DWORD dwSize;
1298 DWORD dwLastResumeCount;
1299 LPENUM_SERVICE_STATUSW lpStatusPtr;
1300 LPWSTR lpStringPtr;
1301
1302 DPRINT("ScmrEnumServicesStatusW() called\n");
1303
1304 if (ScmShutdown)
1305 return ERROR_SHUTDOWN_IN_PROGRESS;
1306
1307 hManager = (PMANAGER_HANDLE)hSCManager;
1308 if (hManager->Handle.Tag != MANAGER_TAG)
1309 {
1310 DPRINT1("Invalid manager handle!\n");
1311 return ERROR_INVALID_HANDLE;
1312 }
1313
1314 /* Check access rights */
1315 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
1316 SC_MANAGER_ENUMERATE_SERVICE))
1317 {
1318 DPRINT1("Insufficient access rights! 0x%lx\n",
1319 hManager->Handle.DesiredAccess);
1320 return ERROR_ACCESS_DENIED;
1321 }
1322
1323 *pcbBytesNeeded = 0;
1324 *lpServicesReturned = 0;
1325
1326 dwLastResumeCount = *lpResumeHandle;
1327
1328 /* Lock the service list shared */
1329
1330 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
1331 if (lpService == NULL)
1332 {
1333 dwError = ERROR_SUCCESS;
1334 goto Done;
1335 }
1336
1337 dwRequiredSize = 0;
1338 dwServiceCount = 0;
1339
1340 for (ServiceEntry = &lpService->ServiceListEntry;
1341 ServiceEntry != &ServiceListHead;
1342 ServiceEntry = ServiceEntry->Flink)
1343 {
1344 CurrentService = CONTAINING_RECORD(ServiceEntry,
1345 SERVICE,
1346 ServiceListEntry);
1347
1348 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
1349 continue;
1350
1351 dwState = SERVICE_ACTIVE;
1352 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
1353 dwState = SERVICE_INACTIVE;
1354
1355 if ((dwState & dwServiceState) == 0)
1356 continue;
1357
1358 dwSize = sizeof(ENUM_SERVICE_STATUSW) +
1359 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
1360 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
1361
1362 if (dwRequiredSize + dwSize <= dwBufSize)
1363 {
1364 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
1365 dwRequiredSize += dwSize;
1366 dwServiceCount++;
1367 dwLastResumeCount = CurrentService->dwResumeCount;
1368 }
1369 else
1370 {
1371 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
1372 break;
1373 }
1374
1375 }
1376
1377 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
1378 DPRINT("dwServiceCount: %lu\n", dwServiceCount);
1379
1380 for (;
1381 ServiceEntry != &ServiceListHead;
1382 ServiceEntry = ServiceEntry->Flink)
1383 {
1384 CurrentService = CONTAINING_RECORD(ServiceEntry,
1385 SERVICE,
1386 ServiceListEntry);
1387
1388 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
1389 continue;
1390
1391 dwState = SERVICE_ACTIVE;
1392 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
1393 dwState = SERVICE_INACTIVE;
1394
1395 if ((dwState & dwServiceState) == 0)
1396 continue;
1397
1398 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) +
1399 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
1400 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
1401
1402 dwError = ERROR_MORE_DATA;
1403 }
1404
1405 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
1406
1407 *lpResumeHandle = dwLastResumeCount;
1408 *lpServicesReturned = dwServiceCount;
1409 *pcbBytesNeeded = dwRequiredSize;
1410
1411 lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpServices;
1412 lpStringPtr = (LPWSTR)((ULONG_PTR)lpServices +
1413 dwServiceCount * sizeof(ENUM_SERVICE_STATUSW));
1414
1415 dwRequiredSize = 0;
1416 for (ServiceEntry = &lpService->ServiceListEntry;
1417 ServiceEntry != &ServiceListHead;
1418 ServiceEntry = ServiceEntry->Flink)
1419 {
1420 CurrentService = CONTAINING_RECORD(ServiceEntry,
1421 SERVICE,
1422 ServiceListEntry);
1423
1424 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
1425 continue;
1426
1427 dwState = SERVICE_ACTIVE;
1428 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
1429 dwState = SERVICE_INACTIVE;
1430
1431 if ((dwState & dwServiceState) == 0)
1432 continue;
1433
1434 dwSize = sizeof(ENUM_SERVICE_STATUSW) +
1435 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
1436 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
1437
1438 if (dwRequiredSize + dwSize <= dwBufSize)
1439 {
1440 /* Copy the service name */
1441 wcscpy(lpStringPtr,
1442 CurrentService->lpServiceName);
1443 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
1444 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
1445
1446 /* Copy the display name */
1447 wcscpy(lpStringPtr,
1448 CurrentService->lpDisplayName);
1449 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
1450 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
1451
1452 /* Copy the status information */
1453 memcpy(&lpStatusPtr->ServiceStatus,
1454 &CurrentService->Status,
1455 sizeof(SERVICE_STATUS));
1456
1457 lpStatusPtr++;
1458 dwRequiredSize += dwSize;
1459 }
1460 else
1461 {
1462 break;
1463 }
1464
1465 }
1466
1467 Done:;
1468 /* Unlock the service list */
1469
1470 DPRINT("ScmrEnumServicesStatusW() done (Error %lu)\n", dwError);
1471
1472 return dwError;
1473 }
1474
1475
1476 /* Function 15 */
1477 unsigned long
1478 ScmrOpenSCManagerW(handle_t BindingHandle,
1479 wchar_t *lpMachineName,
1480 wchar_t *lpDatabaseName,
1481 unsigned long dwDesiredAccess,
1482 unsigned int *hScm)
1483 {
1484 DWORD dwError;
1485 SC_HANDLE hHandle;
1486
1487 DPRINT("ScmrOpenSCManagerW() called\n");
1488 DPRINT("lpMachineName = %p\n", lpMachineName);
1489 DPRINT("lpMachineName: %S\n", lpMachineName);
1490 DPRINT("lpDataBaseName = %p\n", lpDatabaseName);
1491 DPRINT("lpDataBaseName: %S\n", lpDatabaseName);
1492 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
1493
1494 if (ScmShutdown)
1495 return ERROR_SHUTDOWN_IN_PROGRESS;
1496
1497 dwError = ScmCreateManagerHandle(lpDatabaseName,
1498 &hHandle);
1499 if (dwError != ERROR_SUCCESS)
1500 {
1501 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError);
1502 return dwError;
1503 }
1504
1505 /* Check the desired access */
1506 dwError = ScmCheckAccess(hHandle,
1507 dwDesiredAccess | SC_MANAGER_CONNECT);
1508 if (dwError != ERROR_SUCCESS)
1509 {
1510 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
1511 HeapFree(GetProcessHeap(), 0, hHandle);
1512 return dwError;
1513 }
1514
1515 *hScm = (unsigned int)hHandle;
1516 DPRINT("*hScm = %x\n", *hScm);
1517
1518 DPRINT("ScmrOpenSCManagerW() done\n");
1519
1520 return ERROR_SUCCESS;
1521 }
1522
1523
1524 /* Function 16 */
1525 unsigned long
1526 ScmrOpenServiceW(handle_t BindingHandle,
1527 unsigned int hSCManager,
1528 wchar_t *lpServiceName,
1529 unsigned long dwDesiredAccess,
1530 unsigned int *hService)
1531 {
1532 PSERVICE lpService;
1533 PMANAGER_HANDLE hManager;
1534 SC_HANDLE hHandle;
1535 DWORD dwError;
1536
1537 DPRINT("ScmrOpenServiceW() called\n");
1538 DPRINT("hSCManager = %x\n", hSCManager);
1539 DPRINT("lpServiceName = %p\n", lpServiceName);
1540 DPRINT("lpServiceName: %S\n", lpServiceName);
1541 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
1542
1543 if (ScmShutdown)
1544 return ERROR_SHUTDOWN_IN_PROGRESS;
1545
1546 hManager = (PMANAGER_HANDLE)hSCManager;
1547 if (hManager->Handle.Tag != MANAGER_TAG)
1548 {
1549 DPRINT1("Invalid manager handle!\n");
1550 return ERROR_INVALID_HANDLE;
1551 }
1552
1553 /* FIXME: Lock the service list */
1554
1555 /* Get service database entry */
1556 lpService = ScmGetServiceEntryByName(lpServiceName);
1557 if (lpService == NULL)
1558 {
1559 DPRINT("Could not find a service!\n");
1560 return ERROR_SERVICE_DOES_NOT_EXIST;
1561 }
1562
1563 /* Create a service handle */
1564 dwError = ScmCreateServiceHandle(lpService,
1565 &hHandle);
1566 if (dwError != ERROR_SUCCESS)
1567 {
1568 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError);
1569 return dwError;
1570 }
1571
1572 /* Check the desired access */
1573 dwError = ScmCheckAccess(hHandle,
1574 dwDesiredAccess);
1575 if (dwError != ERROR_SUCCESS)
1576 {
1577 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
1578 HeapFree(GetProcessHeap(), 0, hHandle);
1579 return dwError;
1580 }
1581
1582 *hService = (unsigned int)hHandle;
1583 DPRINT("*hService = %x\n", *hService);
1584
1585 DPRINT("ScmrOpenServiceW() done\n");
1586
1587 return ERROR_SUCCESS;
1588 }
1589
1590
1591 /* Function 17 */
1592 unsigned long
1593 ScmrQueryServiceConfigW(handle_t BindingHandle,
1594 unsigned int hService,
1595 unsigned char *lpServiceConfig,
1596 unsigned long cbBufSize,
1597 unsigned long *pcbBytesNeeded)
1598 {
1599 DWORD dwError = ERROR_SUCCESS;
1600 PSERVICE_HANDLE hSvc;
1601 PSERVICE lpService = NULL;
1602 HKEY hServiceKey = NULL;
1603 LPWSTR lpImagePath = NULL;
1604 DWORD dwRequiredSize;
1605 LPQUERY_SERVICE_CONFIGW lpConfig;
1606 LPWSTR lpStr;
1607
1608 DPRINT("ScmrQueryServiceConfigW() called\n");
1609
1610 if (ScmShutdown)
1611 return ERROR_SHUTDOWN_IN_PROGRESS;
1612
1613 hSvc = (PSERVICE_HANDLE)hService;
1614 if (hSvc->Handle.Tag != SERVICE_TAG)
1615 {
1616 DPRINT1("Invalid handle tag!\n");
1617 return ERROR_INVALID_HANDLE;
1618 }
1619
1620 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
1621 SERVICE_QUERY_CONFIG))
1622 {
1623 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1624 return ERROR_ACCESS_DENIED;
1625 }
1626
1627 lpService = hSvc->ServiceEntry;
1628 if (lpService == NULL)
1629 {
1630 DPRINT1("lpService == NULL!\n");
1631 return ERROR_INVALID_HANDLE;
1632 }
1633
1634 /* FIXME: Lock the service database shared */
1635
1636 dwError = ScmOpenServiceKey(lpService->lpServiceName,
1637 KEY_READ,
1638 &hServiceKey);
1639 if (dwError != ERROR_SUCCESS)
1640 goto Done;
1641
1642 dwError = ScmReadString(hServiceKey,
1643 L"ImagePath",
1644 &lpImagePath);
1645 if (dwError != ERROR_SUCCESS)
1646 goto Done;
1647
1648 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
1649
1650 if (lpImagePath != NULL)
1651 dwRequiredSize += ((wcslen(lpImagePath) + 1) * sizeof(WCHAR));
1652
1653 if (lpService->lpGroup != NULL)
1654 dwRequiredSize += ((wcslen(lpService->lpGroup->lpGroupName) + 1) * sizeof(WCHAR));
1655
1656 /* FIXME: Add Dependencies length*/
1657
1658 /* FIXME: Add ServiceStartName length*/
1659
1660 if (lpService->lpDisplayName != NULL)
1661 dwRequiredSize += ((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR));
1662
1663 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
1664 {
1665 dwError = ERROR_INSUFFICIENT_BUFFER;
1666 }
1667 else
1668 {
1669 lpConfig = (LPQUERY_SERVICE_CONFIGW)lpServiceConfig;
1670 lpConfig->dwServiceType = lpService->Status.dwServiceType;
1671 lpConfig->dwStartType = lpService->dwStartType;
1672 lpConfig->dwErrorControl = lpService->dwErrorControl;
1673 lpConfig->dwTagId = lpService->dwTag;
1674
1675 lpStr = (LPWSTR)(lpConfig + 1);
1676
1677 if (lpImagePath != NULL)
1678 {
1679 wcscpy(lpStr, lpImagePath);
1680 lpConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1681 lpStr += (wcslen(lpImagePath) + 1);
1682 }
1683 else
1684 {
1685 lpConfig->lpBinaryPathName = NULL;
1686 }
1687
1688 if (lpService->lpGroup != NULL)
1689 {
1690 wcscpy(lpStr, lpService->lpGroup->lpGroupName);
1691 lpConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1692 lpStr += (wcslen(lpService->lpGroup->lpGroupName) + 1);
1693 }
1694 else
1695 {
1696 lpConfig->lpLoadOrderGroup = NULL;
1697 }
1698
1699 /* FIXME: Append Dependencies */
1700 lpConfig->lpDependencies = NULL;
1701
1702 /* FIXME: Append ServiceStartName */
1703 lpConfig->lpServiceStartName = NULL;
1704
1705 if (lpService->lpDisplayName != NULL)
1706 {
1707 wcscpy(lpStr, lpService->lpDisplayName);
1708 lpConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1709 }
1710 else
1711 {
1712 lpConfig->lpDisplayName = NULL;
1713 }
1714 }
1715
1716 if (pcbBytesNeeded != NULL)
1717 *pcbBytesNeeded = dwRequiredSize;
1718
1719 Done:;
1720 if (lpImagePath != NULL)
1721 HeapFree(GetProcessHeap(), 0, lpImagePath);
1722
1723 if (hServiceKey != NULL)
1724 RegCloseKey(hServiceKey);
1725
1726 /* FIXME: Unlock the service database */
1727
1728 DPRINT("ScmrQueryServiceConfigW() done\n");
1729
1730 return dwError;
1731 }
1732
1733
1734 /* Function 18 */
1735 unsigned long
1736 ScmrQueryServiceLockStatusW(handle_t BindingHandle,
1737 unsigned int hSCManager,
1738 unsigned char *lpLockStatus, /* [out, unique, size_is(cbBufSize)] */
1739 unsigned long cbBufSize, /* [in] */
1740 unsigned long *pcbBytesNeeded) /* [out] */
1741 {
1742 DPRINT1("ScmrQueryServiceLockStatusW() called\n");
1743 return ERROR_CALL_NOT_IMPLEMENTED;
1744 }
1745
1746
1747 /* Function 19 */
1748 unsigned long
1749 ScmrStartServiceW(handle_t BindingHandle,
1750 unsigned int hService,
1751 unsigned long dwNumServiceArgs,
1752 unsigned char *lpServiceArgBuffer,
1753 unsigned long cbBufSize)
1754 {
1755 DWORD dwError = ERROR_SUCCESS;
1756 PSERVICE_HANDLE hSvc;
1757 PSERVICE lpService = NULL;
1758 NTSTATUS Status;
1759
1760 DPRINT1("ScmrStartServiceW() called\n");
1761
1762 if (ScmShutdown)
1763 return ERROR_SHUTDOWN_IN_PROGRESS;
1764
1765 hSvc = (PSERVICE_HANDLE)hService;
1766 if (hSvc->Handle.Tag != SERVICE_TAG)
1767 {
1768 DPRINT1("Invalid handle tag!\n");
1769 return ERROR_INVALID_HANDLE;
1770 }
1771
1772 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
1773 SERVICE_START))
1774 {
1775 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1776 return ERROR_ACCESS_DENIED;
1777 }
1778
1779 lpService = hSvc->ServiceEntry;
1780 if (lpService == NULL)
1781 {
1782 DPRINT1("lpService == NULL!\n");
1783 return ERROR_INVALID_HANDLE;
1784 }
1785
1786 if (lpService->dwStartType == SERVICE_DISABLED)
1787 return ERROR_SERVICE_DISABLED;
1788
1789 if (lpService->bDeleted)
1790 return ERROR_SERVICE_MARKED_FOR_DELETE;
1791
1792 /* Start the service */
1793 Status = ScmStartService(lpService);
1794 if (!NT_SUCCESS(Status))
1795 return RtlNtStatusToDosError(Status);
1796
1797 return dwError;
1798 }
1799
1800
1801 /* Function 20 */
1802 unsigned long
1803 ScmrGetServiceDisplayNameW(handle_t BindingHandle,
1804 unsigned int hSCManager,
1805 wchar_t *lpServiceName,
1806 wchar_t *lpDisplayName, /* [out, unique] */
1807 unsigned long *lpcchBuffer)
1808 {
1809 // PMANAGER_HANDLE hManager;
1810 PSERVICE lpService;
1811 DWORD dwLength;
1812 DWORD dwError;
1813
1814 DPRINT("ScmrGetServiceDisplayNameW() called\n");
1815 DPRINT("hSCManager = %x\n", hSCManager);
1816 DPRINT("lpServiceName: %S\n", lpServiceName);
1817 DPRINT("lpDisplayName: %p\n", lpDisplayName);
1818 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
1819
1820 // hManager = (PMANAGER_HANDLE)hSCManager;
1821 // if (hManager->Handle.Tag != MANAGER_TAG)
1822 // {
1823 // DPRINT1("Invalid manager handle!\n");
1824 // return ERROR_INVALID_HANDLE;
1825 // }
1826
1827 /* Get service database entry */
1828 lpService = ScmGetServiceEntryByName(lpServiceName);
1829 if (lpService == NULL)
1830 {
1831 DPRINT1("Could not find a service!\n");
1832 return ERROR_SERVICE_DOES_NOT_EXIST;
1833 }
1834
1835 dwLength = wcslen(lpService->lpDisplayName) + 1;
1836
1837 if (lpDisplayName != NULL &&
1838 *lpcchBuffer >= dwLength)
1839 {
1840 wcscpy(lpDisplayName, lpService->lpDisplayName);
1841 }
1842
1843 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
1844
1845 *lpcchBuffer = dwLength;
1846
1847 return dwError;
1848 }
1849
1850
1851 /* Function 21 */
1852 unsigned long
1853 ScmrGetServiceKeyNameW(handle_t BindingHandle,
1854 unsigned int hSCManager,
1855 wchar_t *lpDisplayName,
1856 wchar_t *lpServiceName, /* [out, unique] */
1857 unsigned long *lpcchBuffer)
1858 {
1859 // PMANAGER_HANDLE hManager;
1860 PSERVICE lpService;
1861 DWORD dwLength;
1862 DWORD dwError;
1863
1864 DPRINT("ScmrGetServiceKeyNameW() called\n");
1865 DPRINT("hSCManager = %x\n", hSCManager);
1866 DPRINT("lpDisplayName: %S\n", lpDisplayName);
1867 DPRINT("lpServiceName: %p\n", lpServiceName);
1868 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
1869
1870 // hManager = (PMANAGER_HANDLE)hSCManager;
1871 // if (hManager->Handle.Tag != MANAGER_TAG)
1872 // {
1873 // DPRINT1("Invalid manager handle!\n");
1874 // return ERROR_INVALID_HANDLE;
1875 // }
1876
1877 /* Get service database entry */
1878 lpService = ScmGetServiceEntryByDisplayName(lpDisplayName);
1879 if (lpService == NULL)
1880 {
1881 DPRINT1("Could not find a service!\n");
1882 return ERROR_SERVICE_DOES_NOT_EXIST;
1883 }
1884
1885 dwLength = wcslen(lpService->lpServiceName) + 1;
1886
1887 if (lpServiceName != NULL &&
1888 *lpcchBuffer >= dwLength)
1889 {
1890 wcscpy(lpServiceName, lpService->lpServiceName);
1891 }
1892
1893 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
1894
1895 *lpcchBuffer = dwLength;
1896
1897 return dwError;
1898 }
1899
1900
1901 /* Function 22 */
1902 unsigned long
1903 ScmrSetServiceBitsA(handle_t BindingHandle,
1904 unsigned long hServiceStatus,
1905 unsigned long dwServiceBits,
1906 unsigned long bSetBitsOn,
1907 unsigned long bUpdateImmediately,
1908 char *lpString)
1909 {
1910 DPRINT1("ScmrSetServiceBitsA() is unimplemented\n");
1911 return ERROR_CALL_NOT_IMPLEMENTED;
1912 }
1913
1914
1915 /* Function 23 */
1916 unsigned long
1917 ScmrChangeServiceConfigA(handle_t BiningHandle,
1918 unsigned int hService,
1919 unsigned long dwServiceType,
1920 unsigned long dwStartType,
1921 unsigned long dwErrorControl,
1922 char *lpBinaryPathName,
1923 char *lpLoadOrderGroup,
1924 unsigned long *lpdwTagId,
1925 char *lpDependencies,
1926 unsigned long dwDependenciesLength,
1927 char *lpServiceStartName,
1928 char *lpPassword,
1929 unsigned long dwPasswordLength,
1930 char *lpDisplayName)
1931 {
1932 DPRINT1("ScmrChangeServiceConfigA() is unimplemented\n");
1933 return ERROR_CALL_NOT_IMPLEMENTED;
1934 }
1935
1936
1937 /* Function 24 */
1938 unsigned long
1939 ScmrCreateServiceA(handle_t BindingHandle,
1940 unsigned int hSCManager,
1941 char *lpServiceName,
1942 char *lpDisplayName,
1943 unsigned long dwDesiredAccess,
1944 unsigned long dwServiceType,
1945 unsigned long dwStartType,
1946 unsigned long dwErrorControl,
1947 char *lpBinaryPathName,
1948 char *lpLoadOrderGroup,
1949 unsigned long *lpdwTagId, /* in, out */
1950 char *lpDependencies,
1951 unsigned long dwDependenciesLength,
1952 char *lpServiceStartName,
1953 char *lpPassword,
1954 unsigned long dwPasswordLength,
1955 unsigned int *hService) /* out */
1956 {
1957 DPRINT1("ScmrCreateServiceA() is unimplemented\n");
1958 return ERROR_CALL_NOT_IMPLEMENTED;
1959 }
1960
1961
1962 /* Function 25 */
1963 unsigned long
1964 ScmrEnumDependentServicesA(handle_t BindingHandle,
1965 unsigned int hService,
1966 unsigned long dwServiceState,
1967 unsigned char *lpServices,
1968 unsigned long cbBufSize,
1969 unsigned long *pcbBytesNeeded,
1970 unsigned long *lpServicesReturned)
1971 {
1972 DPRINT1("ScmrEnumDependentServicesA() is unimplemented\n");
1973 *pcbBytesNeeded = 0;
1974 *lpServicesReturned = 0;
1975 return ERROR_CALL_NOT_IMPLEMENTED;
1976 }
1977
1978
1979 /* Function 26 */
1980 unsigned long
1981 ScmrEnumServicesStatusA(handle_t BindingHandle,
1982 unsigned int hSCManager,
1983 unsigned long dwServiceType,
1984 unsigned long dwServiceState,
1985 unsigned char *lpServices,
1986 unsigned long dwBufSize,
1987 unsigned long *pcbBytesNeeded,
1988 unsigned long *lpServicesReturned,
1989 unsigned long *lpResumeHandle)
1990 {
1991 DPRINT1("ScmrEnumServicesAtatusA() is unimplemented\n");
1992 return ERROR_CALL_NOT_IMPLEMENTED;
1993 }
1994
1995
1996 /* Function 27 */
1997 unsigned long
1998 ScmrOpenSCManagerA(handle_t BindingHandle,
1999 char *lpMachineName,
2000 char *lpDatabaseName,
2001 unsigned long dwDesiredAccess,
2002 unsigned int *hScm)
2003 {
2004 UNICODE_STRING MachineName;
2005 UNICODE_STRING DatabaseName;
2006 DWORD dwError;
2007
2008 DPRINT("ScmrOpenSCManagerA() called\n");
2009
2010 if (lpMachineName)
2011 RtlCreateUnicodeStringFromAsciiz(&MachineName,
2012 lpMachineName);
2013
2014 if (lpDatabaseName)
2015 RtlCreateUnicodeStringFromAsciiz(&DatabaseName,
2016 lpDatabaseName);
2017
2018 dwError = ScmrOpenSCManagerW(BindingHandle,
2019 lpMachineName ? MachineName.Buffer : NULL,
2020 lpDatabaseName ? DatabaseName.Buffer : NULL,
2021 dwDesiredAccess,
2022 hScm);
2023
2024 if (lpMachineName)
2025 RtlFreeUnicodeString(&MachineName);
2026
2027 if (lpDatabaseName)
2028 RtlFreeUnicodeString(&DatabaseName);
2029
2030 return dwError;
2031 }
2032
2033
2034 /* Function 28 */
2035 unsigned int
2036 ScmrOpenServiceA(handle_t BindingHandle,
2037 unsigned int hSCManager,
2038 char *lpServiceName,
2039 unsigned long dwDesiredAccess,
2040 unsigned int *hService)
2041 {
2042 UNICODE_STRING ServiceName;
2043 DWORD dwError;
2044
2045 DPRINT("ScmrOpenServiceA() called\n");
2046
2047 RtlCreateUnicodeStringFromAsciiz(&ServiceName,
2048 lpServiceName);
2049
2050 dwError = ScmrOpenServiceW(BindingHandle,
2051 hSCManager,
2052 ServiceName.Buffer,
2053 dwDesiredAccess,
2054 hService);
2055
2056 RtlFreeUnicodeString(&ServiceName);
2057
2058 return dwError;
2059 }
2060
2061
2062 /* Function 29 */
2063 unsigned long
2064 ScmrQueryServiceConfigA(handle_t BindingHandle,
2065 unsigned int hService,
2066 unsigned char *lpServiceConfig,
2067 unsigned long cbBufSize,
2068 unsigned long *pcbBytesNeeded)
2069 {
2070 DPRINT1("ScmrQueryServiceConfigA() is unimplemented\n");
2071 return ERROR_CALL_NOT_IMPLEMENTED;
2072 }
2073
2074
2075 /* Function 30 */
2076 unsigned long
2077 ScmrQueryServiceLockStatusA(handle_t BindingHandle,
2078 unsigned int hSCManager,
2079 unsigned char *lpLockStatus, /* [out, unique, size_is(cbBufSize)] */
2080 unsigned long cbBufSize, /* [in] */
2081 unsigned long *pcbBytesNeeded) /* [out] */
2082 {
2083 DPRINT1("ScmrQueryServiceLockStatusA() called\n");
2084 return ERROR_CALL_NOT_IMPLEMENTED;
2085 }
2086
2087
2088 /* Function 31 */
2089 unsigned long
2090 ScmrStartServiceA(handle_t BindingHandle,
2091 unsigned int hService,
2092 unsigned long dwNumServiceArgs,
2093 unsigned char *lpServiceArgBuffer,
2094 unsigned long cbBufSize)
2095 {
2096 DWORD dwError = ERROR_SUCCESS;
2097 PSERVICE_HANDLE hSvc;
2098 PSERVICE lpService = NULL;
2099 NTSTATUS Status;
2100
2101 DPRINT1("ScmrStartServiceA() called\n");
2102
2103 if (ScmShutdown)
2104 return ERROR_SHUTDOWN_IN_PROGRESS;
2105
2106 hSvc = (PSERVICE_HANDLE)hService;
2107 if (hSvc->Handle.Tag != SERVICE_TAG)
2108 {
2109 DPRINT1("Invalid handle tag!\n");
2110 return ERROR_INVALID_HANDLE;
2111 }
2112
2113 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
2114 SERVICE_START))
2115 {
2116 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
2117 return ERROR_ACCESS_DENIED;
2118 }
2119
2120 lpService = hSvc->ServiceEntry;
2121 if (lpService == NULL)
2122 {
2123 DPRINT1("lpService == NULL!\n");
2124 return ERROR_INVALID_HANDLE;
2125 }
2126
2127 if (lpService->dwStartType == SERVICE_DISABLED)
2128 return ERROR_SERVICE_DISABLED;
2129
2130 if (lpService->bDeleted)
2131 return ERROR_SERVICE_MARKED_FOR_DELETE;
2132
2133 /* FIXME: Convert argument vector to Unicode */
2134
2135 /* Start the service */
2136 Status = ScmStartService(lpService);
2137 if (!NT_SUCCESS(Status))
2138 return RtlNtStatusToDosError(Status);
2139
2140 return dwError;
2141 }
2142
2143
2144 /* Function 32 */
2145 unsigned long
2146 ScmrGetServiceDisplayNameA(handle_t BindingHandle,
2147 unsigned int hSCManager,
2148 char *lpServiceName,
2149 char *lpDisplayName, /* [out, unique] */
2150 unsigned long *lpcchBuffer)
2151 {
2152 DPRINT1("ScmrGetServiceDisplayNameA() is unimplemented\n");
2153 return ERROR_CALL_NOT_IMPLEMENTED;
2154 }
2155
2156
2157 /* Function 33 */
2158 unsigned long
2159 ScmrGetServiceKeyNameA(handle_t BindingHandle,
2160 unsigned int hSCManager,
2161 char *lpDisplayName,
2162 char *lpServiceName, /* [out, unique] */
2163 unsigned long *lpcchBuffer)
2164 {
2165 DPRINT1("ScmrGetServiceKeyNameA() is unimplemented\n");
2166 return ERROR_CALL_NOT_IMPLEMENTED;
2167 }
2168
2169
2170 /* Function 34 */
2171 unsigned long
2172 ScmrGetCurrentGroupStateW(handle_t BindingHandle)
2173 {
2174 DPRINT1("ScmrGetCurrentGroupStateW() is unimplemented\n");
2175 return ERROR_CALL_NOT_IMPLEMENTED;
2176 }
2177
2178
2179 /* Function 35 */
2180 unsigned long
2181 ScmrEnumServiceGroupW(handle_t BindingHandle)
2182 {
2183 DPRINT1("ScmrEnumServiceGroupW() is unimplemented\n");
2184 return ERROR_CALL_NOT_IMPLEMENTED;
2185 }
2186
2187
2188 /* Function 36 */
2189 unsigned long
2190 ScmrChangeServiceConfig2A(handle_t BindingHandle,
2191 unsigned int hService,
2192 unsigned long dwInfoLevel,
2193 unsigned char *lpInfo,
2194 unsigned long dwInfoSize)
2195 {
2196 DPRINT1("ScmrChangeServiceConfig2A() is unimplemented\n");
2197 return ERROR_CALL_NOT_IMPLEMENTED;
2198 }
2199
2200
2201 /* Function 37 */
2202 unsigned long
2203 ScmrChangeServiceConfig2W(handle_t BindingHandle,
2204 unsigned int hService,
2205 unsigned long dwInfoLevel,
2206 unsigned char *lpInfo,
2207 unsigned long dwInfoSize)
2208 {
2209 DPRINT1("ScmrChangeServiceConfig2W() is unimplemented\n");
2210 return ERROR_CALL_NOT_IMPLEMENTED;
2211 }
2212
2213
2214 /* Function 38 */
2215 unsigned long
2216 ScmrQueryServiceConfig2A(handle_t BindingHandle,
2217 unsigned int hService,
2218 unsigned long dwInfoLevel,
2219 unsigned char *lpBuffer,
2220 unsigned long cbBufSize,
2221 unsigned long *pcbBytesNeeded)
2222 {
2223 DPRINT1("ScmrQueryServiceConfig2A() is unimplemented\n");
2224 return ERROR_CALL_NOT_IMPLEMENTED;
2225 }
2226
2227
2228 /* Function 39 */
2229 unsigned long
2230 ScmrQueryServiceConfig2W(handle_t BindingHandle,
2231 unsigned int hService,
2232 unsigned long dwInfoLevel,
2233 unsigned char *lpBuffer,
2234 unsigned long cbBufSize,
2235 unsigned long *pcbBytesNeeded)
2236 {
2237 DPRINT1("ScmrQueryServiceConfig2W() is unimplemented\n");
2238 return ERROR_CALL_NOT_IMPLEMENTED;
2239 }
2240
2241
2242 /* Function 40 */
2243 unsigned long
2244 ScmrQueryServiceStatusEx(handle_t BindingHandle,
2245 unsigned int hService,
2246 unsigned long InfoLevel,
2247 unsigned char *lpBuffer, /* out */
2248 unsigned long cbBufSize,
2249 unsigned long *pcbBytesNeeded) /* out */
2250 {
2251 LPSERVICE_STATUS_PROCESS lpStatus;
2252 PSERVICE_HANDLE hSvc;
2253 PSERVICE lpService;
2254
2255 DPRINT("ScmrQueryServiceStatusEx() called\n");
2256
2257 if (ScmShutdown)
2258 return ERROR_SHUTDOWN_IN_PROGRESS;
2259
2260 if (InfoLevel != SC_STATUS_PROCESS_INFO)
2261 return ERROR_INVALID_LEVEL;
2262
2263 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
2264
2265 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
2266 return ERROR_INSUFFICIENT_BUFFER;
2267
2268 hSvc = (PSERVICE_HANDLE)hService;
2269 if (hSvc->Handle.Tag != SERVICE_TAG)
2270 {
2271 DPRINT1("Invalid handle tag!\n");
2272 return ERROR_INVALID_HANDLE;
2273 }
2274
2275 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
2276 SERVICE_QUERY_STATUS))
2277 {
2278 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
2279 return ERROR_ACCESS_DENIED;
2280 }
2281
2282 lpService = hSvc->ServiceEntry;
2283 if (lpService == NULL)
2284 {
2285 DPRINT1("lpService == NULL!\n");
2286 return ERROR_INVALID_HANDLE;
2287 }
2288
2289 lpStatus = (LPSERVICE_STATUS_PROCESS)lpBuffer;
2290
2291 /* Return service status information */
2292 RtlCopyMemory(lpStatus,
2293 &lpService->Status,
2294 sizeof(SERVICE_STATUS));
2295
2296 lpStatus->dwProcessId = lpService->ProcessId; /* FIXME */
2297 lpStatus->dwServiceFlags = 0; /* FIXME */
2298
2299 return ERROR_SUCCESS;
2300 }
2301
2302
2303 /* Function 41 */
2304 unsigned long
2305 ScmrEnumServicesStatusExA(handle_t BindingHandle,
2306 unsigned int hSCManager,
2307 unsigned long InfoLevel,
2308 unsigned long dwServiceType,
2309 unsigned long dwServiceState,
2310 unsigned char *lpServices,
2311 unsigned long dwBufSize,
2312 unsigned long *pcbBytesNeeded,
2313 unsigned long *lpServicesReturned,
2314 unsigned long *lpResumeHandle,
2315 char *pszGroupName)
2316 {
2317 DPRINT1("ScmrEnumServicesStatusExA() is unimplemented\n");
2318 *pcbBytesNeeded = 0;
2319 *lpServicesReturned = 0;
2320 return ERROR_CALL_NOT_IMPLEMENTED;
2321 }
2322
2323
2324 /* Function 42 */
2325 unsigned long
2326 ScmrEnumServicesStatusExW(handle_t BindingHandle,
2327 unsigned int hSCManager,
2328 unsigned long InfoLevel,
2329 unsigned long dwServiceType,
2330 unsigned long dwServiceState,
2331 unsigned char *lpServices,
2332 unsigned long dwBufSize,
2333 unsigned long *pcbBytesNeeded,
2334 unsigned long *lpServicesReturned,
2335 unsigned long *lpResumeHandle,
2336 wchar_t *pszGroupName)
2337 {
2338 PMANAGER_HANDLE hManager;
2339 PSERVICE lpService;
2340 DWORD dwError = ERROR_SUCCESS;
2341 PLIST_ENTRY ServiceEntry;
2342 PSERVICE CurrentService;
2343 DWORD dwState;
2344 DWORD dwRequiredSize;
2345 DWORD dwServiceCount;
2346 DWORD dwSize;
2347 DWORD dwLastResumeCount;
2348 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
2349 LPWSTR lpStringPtr;
2350
2351 DPRINT("ScmrEnumServicesStatusExW() called\n");
2352
2353 if (ScmShutdown)
2354 return ERROR_SHUTDOWN_IN_PROGRESS;
2355
2356 if (InfoLevel != SC_ENUM_PROCESS_INFO)
2357 return ERROR_INVALID_LEVEL;
2358
2359 hManager = (PMANAGER_HANDLE)hSCManager;
2360 if (hManager->Handle.Tag != MANAGER_TAG)
2361 {
2362 DPRINT1("Invalid manager handle!\n");
2363 return ERROR_INVALID_HANDLE;
2364 }
2365
2366 /* Check access rights */
2367 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
2368 SC_MANAGER_ENUMERATE_SERVICE))
2369 {
2370 DPRINT1("Insufficient access rights! 0x%lx\n",
2371 hManager->Handle.DesiredAccess);
2372 return ERROR_ACCESS_DENIED;
2373 }
2374
2375 *pcbBytesNeeded = 0;
2376 *lpServicesReturned = 0;
2377
2378 dwLastResumeCount = *lpResumeHandle;
2379
2380 /* Lock the service list shared */
2381
2382 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
2383 if (lpService == NULL)
2384 {
2385 dwError = ERROR_SUCCESS;
2386 goto Done;
2387 }
2388
2389 dwRequiredSize = 0;
2390 dwServiceCount = 0;
2391
2392 for (ServiceEntry = &lpService->ServiceListEntry;
2393 ServiceEntry != &ServiceListHead;
2394 ServiceEntry = ServiceEntry->Flink)
2395 {
2396 CurrentService = CONTAINING_RECORD(ServiceEntry,
2397 SERVICE,
2398 ServiceListEntry);
2399
2400 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2401 continue;
2402
2403 dwState = SERVICE_ACTIVE;
2404 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2405 dwState = SERVICE_INACTIVE;
2406
2407 if ((dwState & dwServiceState) == 0)
2408 continue;
2409
2410 if (pszGroupName)
2411 {
2412 if (*pszGroupName == 0)
2413 {
2414 if (CurrentService->lpGroup != NULL)
2415 continue;
2416 }
2417 else
2418 {
2419 if ((CurrentService->lpGroup == NULL) ||
2420 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
2421 continue;
2422 }
2423 }
2424
2425 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2426 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2427 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
2428
2429 if (dwRequiredSize + dwSize <= dwBufSize)
2430 {
2431 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
2432 dwRequiredSize += dwSize;
2433 dwServiceCount++;
2434 dwLastResumeCount = CurrentService->dwResumeCount;
2435 }
2436 else
2437 {
2438 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
2439 break;
2440 }
2441
2442 }
2443
2444 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
2445 DPRINT("dwServiceCount: %lu\n", dwServiceCount);
2446
2447 for (;
2448 ServiceEntry != &ServiceListHead;
2449 ServiceEntry = ServiceEntry->Flink)
2450 {
2451 CurrentService = CONTAINING_RECORD(ServiceEntry,
2452 SERVICE,
2453 ServiceListEntry);
2454
2455 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2456 continue;
2457
2458 dwState = SERVICE_ACTIVE;
2459 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2460 dwState = SERVICE_INACTIVE;
2461
2462 if ((dwState & dwServiceState) == 0)
2463 continue;
2464
2465 if (pszGroupName)
2466 {
2467 if (*pszGroupName == 0)
2468 {
2469 if (CurrentService->lpGroup != NULL)
2470 continue;
2471 }
2472 else
2473 {
2474 if ((CurrentService->lpGroup == NULL) ||
2475 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
2476 continue;
2477 }
2478 }
2479
2480 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2481 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2482 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
2483
2484 dwError = ERROR_MORE_DATA;
2485 }
2486
2487 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
2488
2489 *lpResumeHandle = dwLastResumeCount;
2490 *lpServicesReturned = dwServiceCount;
2491 *pcbBytesNeeded = dwRequiredSize;
2492
2493 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices;
2494 lpStringPtr = (LPWSTR)((ULONG_PTR)lpServices +
2495 dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
2496
2497 dwRequiredSize = 0;
2498 for (ServiceEntry = &lpService->ServiceListEntry;
2499 ServiceEntry != &ServiceListHead;
2500 ServiceEntry = ServiceEntry->Flink)
2501 {
2502 CurrentService = CONTAINING_RECORD(ServiceEntry,
2503 SERVICE,
2504 ServiceListEntry);
2505
2506 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2507 continue;
2508
2509 dwState = SERVICE_ACTIVE;
2510 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2511 dwState = SERVICE_INACTIVE;
2512
2513 if ((dwState & dwServiceState) == 0)
2514 continue;
2515
2516 if (pszGroupName)
2517 {
2518 if (*pszGroupName == 0)
2519 {
2520 if (CurrentService->lpGroup != NULL)
2521 continue;
2522 }
2523 else
2524 {
2525 if ((CurrentService->lpGroup == NULL) ||
2526 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
2527 continue;
2528 }
2529 }
2530
2531 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2532 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2533 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
2534
2535 if (dwRequiredSize + dwSize <= dwBufSize)
2536 {
2537 /* Copy the service name */
2538 wcscpy(lpStringPtr,
2539 CurrentService->lpServiceName);
2540 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
2541 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
2542
2543 /* Copy the display name */
2544 wcscpy(lpStringPtr,
2545 CurrentService->lpDisplayName);
2546 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
2547 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
2548
2549 /* Copy the status information */
2550 memcpy(&lpStatusPtr->ServiceStatusProcess,
2551 &CurrentService->Status,
2552 sizeof(SERVICE_STATUS));
2553 lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->ProcessId; /* FIXME */
2554 lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
2555
2556 lpStatusPtr++;
2557 dwRequiredSize += dwSize;
2558 }
2559 else
2560 {
2561 break;
2562 }
2563
2564 }
2565
2566 Done:;
2567 /* Unlock the service list */
2568
2569 DPRINT("ScmrEnumServicesStatusExW() done (Error %lu)\n", dwError);
2570
2571 return dwError;
2572 }
2573
2574
2575 /* Function 43 */
2576 /* ScmrSendTSMessage */
2577
2578
2579 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
2580 {
2581 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
2582 }
2583
2584
2585 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
2586 {
2587 HeapFree(GetProcessHeap(), 0, ptr);
2588 }
2589
2590 /* EOF */