Revert, thx Thomas, wasnt sure.
[reactos.git] / reactos / subsys / 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 int
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 DPRINT1("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 DPRINT1("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
1759 DPRINT1("ScmrStartServiceW() called\n");
1760
1761 if (ScmShutdown)
1762 return ERROR_SHUTDOWN_IN_PROGRESS;
1763
1764 hSvc = (PSERVICE_HANDLE)hService;
1765 if (hSvc->Handle.Tag != SERVICE_TAG)
1766 {
1767 DPRINT1("Invalid handle tag!\n");
1768 return ERROR_INVALID_HANDLE;
1769 }
1770
1771 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
1772 SERVICE_START))
1773 {
1774 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1775 return ERROR_ACCESS_DENIED;
1776 }
1777
1778 lpService = hSvc->ServiceEntry;
1779 if (lpService == NULL)
1780 {
1781 DPRINT1("lpService == NULL!\n");
1782 return ERROR_INVALID_HANDLE;
1783 }
1784
1785 if (lpService->dwStartType == SERVICE_DISABLED)
1786 return ERROR_SERVICE_DISABLED;
1787
1788 if (lpService->bDeleted)
1789 return ERROR_SERVICE_MARKED_FOR_DELETE;
1790
1791 /* FIXME: Start the service */
1792
1793 return dwError;
1794 }
1795
1796
1797 /* Function 20 */
1798 unsigned long
1799 ScmrGetServiceDisplayNameW(handle_t BindingHandle,
1800 unsigned int hSCManager,
1801 wchar_t *lpServiceName,
1802 wchar_t *lpDisplayName, /* [out, unique] */
1803 unsigned long *lpcchBuffer)
1804 {
1805 // PMANAGER_HANDLE hManager;
1806 PSERVICE lpService;
1807 DWORD dwLength;
1808 DWORD dwError;
1809
1810 DPRINT("ScmrGetServiceDisplayNameW() called\n");
1811 DPRINT("hSCManager = %x\n", hSCManager);
1812 DPRINT("lpServiceName: %S\n", lpServiceName);
1813 DPRINT("lpDisplayName: %p\n", lpDisplayName);
1814 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
1815
1816 // hManager = (PMANAGER_HANDLE)hSCManager;
1817 // if (hManager->Handle.Tag != MANAGER_TAG)
1818 // {
1819 // DPRINT1("Invalid manager handle!\n");
1820 // return ERROR_INVALID_HANDLE;
1821 // }
1822
1823 /* Get service database entry */
1824 lpService = ScmGetServiceEntryByName(lpServiceName);
1825 if (lpService == NULL)
1826 {
1827 DPRINT1("Could not find a service!\n");
1828 return ERROR_SERVICE_DOES_NOT_EXIST;
1829 }
1830
1831 dwLength = wcslen(lpService->lpDisplayName) + 1;
1832
1833 if (lpDisplayName != NULL &&
1834 *lpcchBuffer >= dwLength)
1835 {
1836 wcscpy(lpDisplayName, lpService->lpDisplayName);
1837 }
1838
1839 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
1840
1841 *lpcchBuffer = dwLength;
1842
1843 return dwError;
1844 }
1845
1846
1847 /* Function 21 */
1848 unsigned long
1849 ScmrGetServiceKeyNameW(handle_t BindingHandle,
1850 unsigned int hSCManager,
1851 wchar_t *lpDisplayName,
1852 wchar_t *lpServiceName, /* [out, unique] */
1853 unsigned long *lpcchBuffer)
1854 {
1855 // PMANAGER_HANDLE hManager;
1856 PSERVICE lpService;
1857 DWORD dwLength;
1858 DWORD dwError;
1859
1860 DPRINT("ScmrGetServiceKeyNameW() called\n");
1861 DPRINT("hSCManager = %x\n", hSCManager);
1862 DPRINT("lpDisplayName: %S\n", lpDisplayName);
1863 DPRINT("lpServiceName: %p\n", lpServiceName);
1864 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
1865
1866 // hManager = (PMANAGER_HANDLE)hSCManager;
1867 // if (hManager->Handle.Tag != MANAGER_TAG)
1868 // {
1869 // DPRINT1("Invalid manager handle!\n");
1870 // return ERROR_INVALID_HANDLE;
1871 // }
1872
1873 /* Get service database entry */
1874 lpService = ScmGetServiceEntryByDisplayName(lpDisplayName);
1875 if (lpService == NULL)
1876 {
1877 DPRINT1("Could not find a service!\n");
1878 return ERROR_SERVICE_DOES_NOT_EXIST;
1879 }
1880
1881 dwLength = wcslen(lpService->lpServiceName) + 1;
1882
1883 if (lpServiceName != NULL &&
1884 *lpcchBuffer >= dwLength)
1885 {
1886 wcscpy(lpServiceName, lpService->lpServiceName);
1887 }
1888
1889 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
1890
1891 *lpcchBuffer = dwLength;
1892
1893 return dwError;
1894 }
1895
1896
1897 /* Function 22 */
1898 unsigned long
1899 ScmrSetServiceBitsA(handle_t BindingHandle,
1900 unsigned long hServiceStatus,
1901 unsigned long dwServiceBits,
1902 unsigned long bSetBitsOn,
1903 unsigned long bUpdateImmediately,
1904 char *lpString)
1905 {
1906 DPRINT1("ScmrSetServiceBitsA() is unimplemented\n");
1907 return ERROR_CALL_NOT_IMPLEMENTED;
1908 }
1909
1910
1911 /* Function 23 */
1912 unsigned long
1913 ScmrChangeServiceConfigA(handle_t BiningHandle,
1914 unsigned int hService,
1915 unsigned long dwServiceType,
1916 unsigned long dwStartType,
1917 unsigned long dwErrorControl,
1918 char *lpBinaryPathName,
1919 char *lpLoadOrderGroup,
1920 unsigned long *lpdwTagId,
1921 char *lpDependencies,
1922 unsigned long dwDependenciesLength,
1923 char *lpServiceStartName,
1924 char *lpPassword,
1925 unsigned long dwPasswordLength,
1926 char *lpDisplayName)
1927 {
1928 DPRINT1("ScmrChangeServiceConfigA() is unimplemented\n");
1929 return ERROR_CALL_NOT_IMPLEMENTED;
1930 }
1931
1932
1933 /* Function 24 */
1934 unsigned long
1935 ScmrCreateServiceA(handle_t BindingHandle,
1936 unsigned int hSCManager,
1937 char *lpServiceName,
1938 char *lpDisplayName,
1939 unsigned long dwDesiredAccess,
1940 unsigned long dwServiceType,
1941 unsigned long dwStartType,
1942 unsigned long dwErrorControl,
1943 char *lpBinaryPathName,
1944 char *lpLoadOrderGroup,
1945 unsigned long *lpdwTagId, /* in, out */
1946 char *lpDependencies,
1947 unsigned long dwDependenciesLength,
1948 char *lpServiceStartName,
1949 char *lpPassword,
1950 unsigned long dwPasswordLength,
1951 unsigned int *hService) /* out */
1952 {
1953 DPRINT1("ScmrCreateServiceA() is unimplemented\n");
1954 return ERROR_CALL_NOT_IMPLEMENTED;
1955 }
1956
1957
1958 /* Function 25 */
1959 unsigned long
1960 ScmrEnumDependentServicesA(handle_t BindingHandle,
1961 unsigned int hService,
1962 unsigned long dwServiceState,
1963 unsigned char *lpServices,
1964 unsigned long cbBufSize,
1965 unsigned long *pcbBytesNeeded,
1966 unsigned long *lpServicesReturned)
1967 {
1968 DPRINT1("ScmrEnumDependentServicesA() is unimplemented\n");
1969 *pcbBytesNeeded = 0;
1970 *lpServicesReturned = 0;
1971 return ERROR_CALL_NOT_IMPLEMENTED;
1972 }
1973
1974
1975 /* Function 26 */
1976 unsigned long
1977 ScmrEnumServicesStatusA(handle_t BindingHandle,
1978 unsigned int hSCManager,
1979 unsigned long dwServiceType,
1980 unsigned long dwServiceState,
1981 unsigned char *lpServices,
1982 unsigned long dwBufSize,
1983 unsigned long *pcbBytesNeeded,
1984 unsigned long *lpServicesReturned,
1985 unsigned long *lpResumeHandle)
1986 {
1987 DPRINT1("ScmrEnumServicesAtatusA() is unimplemented\n");
1988 return ERROR_CALL_NOT_IMPLEMENTED;
1989 }
1990
1991
1992 /* Function 27 */
1993 unsigned long
1994 ScmrOpenSCManagerA(handle_t BindingHandle,
1995 char *lpMachineName,
1996 char *lpDatabaseName,
1997 unsigned long dwDesiredAccess,
1998 unsigned int *hScm)
1999 {
2000 UNICODE_STRING MachineName;
2001 UNICODE_STRING DatabaseName;
2002 DWORD dwError;
2003
2004 DPRINT("ScmrOpenSCManagerA() called\n");
2005
2006 if (lpMachineName)
2007 RtlCreateUnicodeStringFromAsciiz(&MachineName,
2008 lpMachineName);
2009
2010 if (lpDatabaseName)
2011 RtlCreateUnicodeStringFromAsciiz(&DatabaseName,
2012 lpDatabaseName);
2013
2014 dwError = ScmrOpenSCManagerW(BindingHandle,
2015 lpMachineName ? MachineName.Buffer : NULL,
2016 lpDatabaseName ? DatabaseName.Buffer : NULL,
2017 dwDesiredAccess,
2018 hScm);
2019
2020 if (lpMachineName)
2021 RtlFreeUnicodeString(&MachineName);
2022
2023 if (lpDatabaseName)
2024 RtlFreeUnicodeString(&DatabaseName);
2025
2026 return dwError;
2027 }
2028
2029
2030 /* Function 28 */
2031 unsigned int
2032 ScmrOpenServiceA(handle_t BindingHandle,
2033 unsigned int hSCManager,
2034 char *lpServiceName,
2035 unsigned long dwDesiredAccess,
2036 unsigned int *hService)
2037 {
2038 UNICODE_STRING ServiceName;
2039 DWORD dwError;
2040
2041 DPRINT("ScmrOpenServiceA() called\n");
2042
2043 RtlCreateUnicodeStringFromAsciiz(&ServiceName,
2044 lpServiceName);
2045
2046 dwError = ScmrOpenServiceW(BindingHandle,
2047 hSCManager,
2048 ServiceName.Buffer,
2049 dwDesiredAccess,
2050 hService);
2051
2052 RtlFreeUnicodeString(&ServiceName);
2053
2054 return dwError;
2055 }
2056
2057
2058 /* Function 29 */
2059 unsigned long
2060 ScmrQueryServiceConfigA(handle_t BindingHandle,
2061 unsigned int hService,
2062 unsigned char *lpServiceConfig,
2063 unsigned long cbBufSize,
2064 unsigned long *pcbBytesNeeded)
2065 {
2066 DPRINT1("ScmrQueryServiceConfigA() is unimplemented\n");
2067 return ERROR_CALL_NOT_IMPLEMENTED;
2068 }
2069
2070
2071 /* Function 30 */
2072 unsigned long
2073 ScmrQueryServiceLockStatusA(handle_t BindingHandle,
2074 unsigned int hSCManager,
2075 unsigned char *lpLockStatus, /* [out, unique, size_is(cbBufSize)] */
2076 unsigned long cbBufSize, /* [in] */
2077 unsigned long *pcbBytesNeeded) /* [out] */
2078 {
2079 DPRINT1("ScmrQueryServiceLockStatusA() called\n");
2080 return ERROR_CALL_NOT_IMPLEMENTED;
2081 }
2082
2083
2084 /* Function 31 */
2085 unsigned long
2086 ScmrStartServiceA(handle_t BindingHandle,
2087 unsigned int hService,
2088 unsigned long dwNumServiceArgs,
2089 unsigned char *lpServiceArgBuffer,
2090 unsigned long cbBufSize)
2091 {
2092 DPRINT1("ScmrStartServiceA() called\n");
2093 return ERROR_SUCCESS;
2094 // return ERROR_CALL_NOT_IMPLEMENTED;
2095 }
2096
2097
2098 /* Function 32 */
2099 unsigned long
2100 ScmrGetServiceDisplayNameA(handle_t BindingHandle,
2101 unsigned int hSCManager,
2102 char *lpServiceName,
2103 char *lpDisplayName, /* [out, unique] */
2104 unsigned long *lpcchBuffer)
2105 {
2106 DPRINT1("ScmrGetServiceDisplayNameA() is unimplemented\n");
2107 return ERROR_CALL_NOT_IMPLEMENTED;
2108 }
2109
2110
2111 /* Function 33 */
2112 unsigned long
2113 ScmrGetServiceKeyNameA(handle_t BindingHandle,
2114 unsigned int hSCManager,
2115 char *lpDisplayName,
2116 char *lpServiceName, /* [out, unique] */
2117 unsigned long *lpcchBuffer)
2118 {
2119 DPRINT1("ScmrGetServiceKeyNameA() is unimplemented\n");
2120 return ERROR_CALL_NOT_IMPLEMENTED;
2121 }
2122
2123
2124 /* Function 34 */
2125 unsigned long
2126 ScmrGetCurrentGroupStateW(handle_t BindingHandle)
2127 {
2128 DPRINT1("ScmrGetCurrentGroupStateW() is unimplemented\n");
2129 return ERROR_CALL_NOT_IMPLEMENTED;
2130 }
2131
2132
2133 /* Function 35 */
2134 unsigned long
2135 ScmrEnumServiceGroupW(handle_t BindingHandle)
2136 {
2137 DPRINT1("ScmrEnumServiceGroupW() is unimplemented\n");
2138 return ERROR_CALL_NOT_IMPLEMENTED;
2139 }
2140
2141
2142 /* Function 36 */
2143 unsigned long
2144 ScmrChangeServiceConfig2A(handle_t BindingHandle,
2145 unsigned int hService,
2146 unsigned long dwInfoLevel,
2147 unsigned char *lpInfo,
2148 unsigned long dwInfoSize)
2149 {
2150 DPRINT1("ScmrChangeServiceConfig2A() is unimplemented\n");
2151 return ERROR_CALL_NOT_IMPLEMENTED;
2152 }
2153
2154
2155 /* Function 37 */
2156 unsigned long
2157 ScmrChangeServiceConfig2W(handle_t BindingHandle,
2158 unsigned int hService,
2159 unsigned long dwInfoLevel,
2160 unsigned char *lpInfo,
2161 unsigned long dwInfoSize)
2162 {
2163 DPRINT1("ScmrChangeServiceConfig2W() is unimplemented\n");
2164 return ERROR_CALL_NOT_IMPLEMENTED;
2165 }
2166
2167
2168 /* Function 38 */
2169 unsigned long
2170 ScmrQueryServiceConfig2A(handle_t BindingHandle,
2171 unsigned int hService,
2172 unsigned long dwInfoLevel,
2173 unsigned char *lpBuffer,
2174 unsigned long cbBufSize,
2175 unsigned long *pcbBytesNeeded)
2176 {
2177 DPRINT1("ScmrQueryServiceConfig2A() is unimplemented\n");
2178 return ERROR_CALL_NOT_IMPLEMENTED;
2179 }
2180
2181
2182 /* Function 39 */
2183 unsigned long
2184 ScmrQueryServiceConfig2W(handle_t BindingHandle,
2185 unsigned int hService,
2186 unsigned long dwInfoLevel,
2187 unsigned char *lpBuffer,
2188 unsigned long cbBufSize,
2189 unsigned long *pcbBytesNeeded)
2190 {
2191 DPRINT1("ScmrQueryServiceConfig2W() is unimplemented\n");
2192 return ERROR_CALL_NOT_IMPLEMENTED;
2193 }
2194
2195
2196 /* Function 40 */
2197 unsigned long
2198 ScmrQueryServiceStatusEx(handle_t BindingHandle,
2199 unsigned int hService,
2200 unsigned long InfoLevel,
2201 unsigned char *lpBuffer, /* out */
2202 unsigned long cbBufSize,
2203 unsigned long *pcbBytesNeeded) /* out */
2204 {
2205 LPSERVICE_STATUS_PROCESS lpStatus;
2206 PSERVICE_HANDLE hSvc;
2207 PSERVICE lpService;
2208
2209 DPRINT("ScmrQueryServiceStatusEx() called\n");
2210
2211 if (ScmShutdown)
2212 return ERROR_SHUTDOWN_IN_PROGRESS;
2213
2214 if (InfoLevel != SC_STATUS_PROCESS_INFO)
2215 return ERROR_INVALID_LEVEL;
2216
2217 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
2218
2219 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
2220 return ERROR_INSUFFICIENT_BUFFER;
2221
2222 hSvc = (PSERVICE_HANDLE)hService;
2223 if (hSvc->Handle.Tag != SERVICE_TAG)
2224 {
2225 DPRINT1("Invalid handle tag!\n");
2226 return ERROR_INVALID_HANDLE;
2227 }
2228
2229 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
2230 SERVICE_QUERY_STATUS))
2231 {
2232 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
2233 return ERROR_ACCESS_DENIED;
2234 }
2235
2236 lpService = hSvc->ServiceEntry;
2237 if (lpService == NULL)
2238 {
2239 DPRINT1("lpService == NULL!\n");
2240 return ERROR_INVALID_HANDLE;
2241 }
2242
2243 lpStatus = (LPSERVICE_STATUS_PROCESS)lpBuffer;
2244
2245 /* Return service status information */
2246 RtlCopyMemory(lpStatus,
2247 &lpService->Status,
2248 sizeof(SERVICE_STATUS));
2249
2250 lpStatus->dwProcessId = lpService->ProcessId; /* FIXME */
2251 lpStatus->dwServiceFlags = 0; /* FIXME */
2252
2253 return ERROR_SUCCESS;
2254 }
2255
2256
2257 /* Function 41 */
2258 unsigned long
2259 ScmrEnumServicesStatusExA(handle_t BindingHandle,
2260 unsigned int hSCManager,
2261 unsigned long InfoLevel,
2262 unsigned long dwServiceType,
2263 unsigned long dwServiceState,
2264 unsigned char *lpServices,
2265 unsigned long dwBufSize,
2266 unsigned long *pcbBytesNeeded,
2267 unsigned long *lpServicesReturned,
2268 unsigned long *lpResumeHandle,
2269 char *pszGroupName)
2270 {
2271 DPRINT1("ScmrEnumServicesStatusExA() is unimplemented\n");
2272 *pcbBytesNeeded = 0;
2273 *lpServicesReturned = 0;
2274 return ERROR_CALL_NOT_IMPLEMENTED;
2275 }
2276
2277
2278 /* Function 42 */
2279 unsigned long
2280 ScmrEnumServicesStatusExW(handle_t BindingHandle,
2281 unsigned int hSCManager,
2282 unsigned long InfoLevel,
2283 unsigned long dwServiceType,
2284 unsigned long dwServiceState,
2285 unsigned char *lpServices,
2286 unsigned long dwBufSize,
2287 unsigned long *pcbBytesNeeded,
2288 unsigned long *lpServicesReturned,
2289 unsigned long *lpResumeHandle,
2290 wchar_t *pszGroupName)
2291 {
2292 PMANAGER_HANDLE hManager;
2293 PSERVICE lpService;
2294 DWORD dwError = ERROR_SUCCESS;
2295 PLIST_ENTRY ServiceEntry;
2296 PSERVICE CurrentService;
2297 DWORD dwState;
2298 DWORD dwRequiredSize;
2299 DWORD dwServiceCount;
2300 DWORD dwSize;
2301 DWORD dwLastResumeCount;
2302 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
2303 LPWSTR lpStringPtr;
2304
2305 DPRINT("ScmrEnumServicesStatusExW() called\n");
2306
2307 if (ScmShutdown)
2308 return ERROR_SHUTDOWN_IN_PROGRESS;
2309
2310 if (InfoLevel != SC_ENUM_PROCESS_INFO)
2311 return ERROR_INVALID_LEVEL;
2312
2313 hManager = (PMANAGER_HANDLE)hSCManager;
2314 if (hManager->Handle.Tag != MANAGER_TAG)
2315 {
2316 DPRINT1("Invalid manager handle!\n");
2317 return ERROR_INVALID_HANDLE;
2318 }
2319
2320 /* Check access rights */
2321 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
2322 SC_MANAGER_ENUMERATE_SERVICE))
2323 {
2324 DPRINT1("Insufficient access rights! 0x%lx\n",
2325 hManager->Handle.DesiredAccess);
2326 return ERROR_ACCESS_DENIED;
2327 }
2328
2329 *pcbBytesNeeded = 0;
2330 *lpServicesReturned = 0;
2331
2332 dwLastResumeCount = *lpResumeHandle;
2333
2334 /* Lock the service list shared */
2335
2336 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
2337 if (lpService == NULL)
2338 {
2339 dwError = ERROR_SUCCESS;
2340 goto Done;
2341 }
2342
2343 dwRequiredSize = 0;
2344 dwServiceCount = 0;
2345
2346 for (ServiceEntry = &lpService->ServiceListEntry;
2347 ServiceEntry != &ServiceListHead;
2348 ServiceEntry = ServiceEntry->Flink)
2349 {
2350 CurrentService = CONTAINING_RECORD(ServiceEntry,
2351 SERVICE,
2352 ServiceListEntry);
2353
2354 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2355 continue;
2356
2357 dwState = SERVICE_ACTIVE;
2358 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2359 dwState = SERVICE_INACTIVE;
2360
2361 if ((dwState & dwServiceState) == 0)
2362 continue;
2363
2364 if (pszGroupName)
2365 {
2366 if (*pszGroupName == 0)
2367 {
2368 if (CurrentService->lpGroup != NULL)
2369 continue;
2370 }
2371 else
2372 {
2373 if ((CurrentService->lpGroup == NULL) ||
2374 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
2375 continue;
2376 }
2377 }
2378
2379 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2380 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2381 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
2382
2383 if (dwRequiredSize + dwSize <= dwBufSize)
2384 {
2385 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
2386 dwRequiredSize += dwSize;
2387 dwServiceCount++;
2388 dwLastResumeCount = CurrentService->dwResumeCount;
2389 }
2390 else
2391 {
2392 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
2393 break;
2394 }
2395
2396 }
2397
2398 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
2399 DPRINT("dwServiceCount: %lu\n", dwServiceCount);
2400
2401 for (;
2402 ServiceEntry != &ServiceListHead;
2403 ServiceEntry = ServiceEntry->Flink)
2404 {
2405 CurrentService = CONTAINING_RECORD(ServiceEntry,
2406 SERVICE,
2407 ServiceListEntry);
2408
2409 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2410 continue;
2411
2412 dwState = SERVICE_ACTIVE;
2413 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2414 dwState = SERVICE_INACTIVE;
2415
2416 if ((dwState & dwServiceState) == 0)
2417 continue;
2418
2419 if (pszGroupName)
2420 {
2421 if (*pszGroupName == 0)
2422 {
2423 if (CurrentService->lpGroup != NULL)
2424 continue;
2425 }
2426 else
2427 {
2428 if ((CurrentService->lpGroup == NULL) ||
2429 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
2430 continue;
2431 }
2432 }
2433
2434 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2435 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2436 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
2437
2438 dwError = ERROR_MORE_DATA;
2439 }
2440
2441 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
2442
2443 *lpResumeHandle = dwLastResumeCount;
2444 *lpServicesReturned = dwServiceCount;
2445 *pcbBytesNeeded = dwRequiredSize;
2446
2447 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices;
2448 lpStringPtr = (LPWSTR)((ULONG_PTR)lpServices +
2449 dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
2450
2451 dwRequiredSize = 0;
2452 for (ServiceEntry = &lpService->ServiceListEntry;
2453 ServiceEntry != &ServiceListHead;
2454 ServiceEntry = ServiceEntry->Flink)
2455 {
2456 CurrentService = CONTAINING_RECORD(ServiceEntry,
2457 SERVICE,
2458 ServiceListEntry);
2459
2460 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2461 continue;
2462
2463 dwState = SERVICE_ACTIVE;
2464 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2465 dwState = SERVICE_INACTIVE;
2466
2467 if ((dwState & dwServiceState) == 0)
2468 continue;
2469
2470 if (pszGroupName)
2471 {
2472 if (*pszGroupName == 0)
2473 {
2474 if (CurrentService->lpGroup != NULL)
2475 continue;
2476 }
2477 else
2478 {
2479 if ((CurrentService->lpGroup == NULL) ||
2480 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
2481 continue;
2482 }
2483 }
2484
2485 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2486 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2487 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
2488
2489 if (dwRequiredSize + dwSize <= dwBufSize)
2490 {
2491 /* Copy the service name */
2492 wcscpy(lpStringPtr,
2493 CurrentService->lpServiceName);
2494 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
2495 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
2496
2497 /* Copy the display name */
2498 wcscpy(lpStringPtr,
2499 CurrentService->lpDisplayName);
2500 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
2501 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
2502
2503 /* Copy the status information */
2504 memcpy(&lpStatusPtr->ServiceStatusProcess,
2505 &CurrentService->Status,
2506 sizeof(SERVICE_STATUS));
2507 lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->ProcessId; /* FIXME */
2508 lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
2509
2510 lpStatusPtr++;
2511 dwRequiredSize += dwSize;
2512 }
2513 else
2514 {
2515 break;
2516 }
2517
2518 }
2519
2520 Done:;
2521 /* Unlock the service list */
2522
2523 DPRINT("ScmrEnumServicesStatusExW() done (Error %lu)\n", dwError);
2524
2525 return dwError;
2526 }
2527
2528
2529 /* Function 43 */
2530 /* ScmrSendTSMessage */
2531
2532
2533 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
2534 {
2535 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
2536 }
2537
2538
2539 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
2540 {
2541 HeapFree(GetProcessHeap(), 0, ptr);
2542 }
2543
2544 /* EOF */