f982ab37e630772bcab5b706526b95f776c60b85
[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(LPWSTR lpServiceGroup,
224 LPDWORD lpdwTagId)
225 {
226 /* FIXME */
227 DPRINT("Assigning new tag in group %S\n", lpServiceGroup);
228 *lpdwTagId = 0;
229 return ERROR_SUCCESS;
230 }
231
232
233 /* Function 0 */
234 unsigned long
235 ScmrCloseServiceHandle(handle_t BindingHandle,
236 unsigned int hScObject)
237 {
238 PMANAGER_HANDLE hManager;
239
240 DPRINT("ScmrCloseServiceHandle() called\n");
241
242 DPRINT("hScObject = %X\n", hScObject);
243
244 if (hScObject == 0)
245 return ERROR_INVALID_HANDLE;
246
247 hManager = (PMANAGER_HANDLE)hScObject;
248 if (hManager->Handle.Tag == MANAGER_TAG)
249 {
250 DPRINT("Found manager handle\n");
251
252 hManager->Handle.RefCount--;
253 if (hManager->Handle.RefCount == 0)
254 {
255 /* FIXME: add cleanup code */
256
257 HeapFree(GetProcessHeap(), 0, hManager);
258 }
259
260 DPRINT("ScmrCloseServiceHandle() done\n");
261 return ERROR_SUCCESS;
262 }
263 else if (hManager->Handle.Tag == SERVICE_TAG)
264 {
265 DPRINT("Found service handle\n");
266
267 hManager->Handle.RefCount--;
268 if (hManager->Handle.RefCount == 0)
269 {
270 /* FIXME: add cleanup code */
271
272 HeapFree(GetProcessHeap(), 0, hManager);
273 }
274
275 DPRINT("ScmrCloseServiceHandle() done\n");
276 return ERROR_SUCCESS;
277 }
278
279 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager->Handle.Tag);
280
281 return ERROR_INVALID_HANDLE;
282 }
283
284
285 /* Function 1 */
286 unsigned long
287 ScmrControlService(handle_t BindingHandle,
288 unsigned int hService,
289 unsigned long dwControl,
290 LPSERVICE_STATUS lpServiceStatus)
291 {
292 PSERVICE_HANDLE hSvc;
293 PSERVICE lpService;
294 ACCESS_MASK DesiredAccess;
295 DWORD dwError = ERROR_SUCCESS;
296
297 DPRINT("ScmrControlService() called\n");
298
299 if (ScmShutdown)
300 return ERROR_SHUTDOWN_IN_PROGRESS;
301
302 /* Check the service handle */
303 hSvc = (PSERVICE_HANDLE)hService;
304 if (hSvc->Handle.Tag != SERVICE_TAG)
305 {
306 DPRINT1("Invalid handle tag!\n");
307 return ERROR_INVALID_HANDLE;
308 }
309
310 /* Check access rights */
311 switch (dwControl)
312 {
313 case SERVICE_CONTROL_STOP:
314 DesiredAccess = SERVICE_STOP;
315 break;
316
317 case SERVICE_CONTROL_PAUSE:
318 case SERVICE_CONTROL_CONTINUE:
319 DesiredAccess = SERVICE_PAUSE_CONTINUE;
320 break;
321
322 case SERVICE_INTERROGATE:
323 DesiredAccess = SERVICE_INTERROGATE;
324 break;
325
326 default:
327 if (dwControl >= 128 && dwControl <= 255)
328 DesiredAccess = SERVICE_USER_DEFINED_CONTROL;
329 else
330 DesiredAccess = SERVICE_QUERY_CONFIG |
331 SERVICE_CHANGE_CONFIG |
332 SERVICE_QUERY_STATUS |
333 SERVICE_START |
334 SERVICE_PAUSE_CONTINUE;
335 break;
336 }
337
338 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
339 DesiredAccess))
340 return ERROR_ACCESS_DENIED;
341
342 /* Check the service entry point */
343 lpService = hSvc->ServiceEntry;
344 if (lpService == NULL)
345 {
346 DPRINT1("lpService == NULL!\n");
347 return ERROR_INVALID_HANDLE;
348 }
349
350 if (lpService->Status.dwServiceType & SERVICE_DRIVER)
351 {
352 /* Send control code to the driver */
353 dwError = ScmControlDriver(lpService,
354 dwControl,
355 lpServiceStatus);
356 }
357 else
358 {
359 /* FIXME: Send control code to the service */
360 #if 0
361 dwError = ScmControlService(lpService,
362 dwControl,
363 lpServiceStatus);
364 #endif
365 dwError = ERROR_INVALID_SERVICE_CONTROL;
366 }
367
368 /* Return service status information */
369 RtlCopyMemory(lpServiceStatus,
370 &lpService->Status,
371 sizeof(SERVICE_STATUS));
372
373 return dwError;
374 }
375
376
377 /* Function 2 */
378 unsigned long
379 ScmrDeleteService(handle_t BindingHandle,
380 unsigned int hService)
381 {
382 PSERVICE_HANDLE hSvc;
383 PSERVICE lpService;
384 DWORD dwError;
385
386 DPRINT("ScmrDeleteService() called\n");
387
388 if (ScmShutdown)
389 return ERROR_SHUTDOWN_IN_PROGRESS;
390
391 hSvc = (PSERVICE_HANDLE)hService;
392 if (hSvc->Handle.Tag != SERVICE_TAG)
393 return ERROR_INVALID_HANDLE;
394
395 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
396 STANDARD_RIGHTS_REQUIRED))
397 return ERROR_ACCESS_DENIED;
398
399 lpService = hSvc->ServiceEntry;
400 if (lpService == NULL)
401 {
402 DPRINT1("lpService == NULL!\n");
403 return ERROR_INVALID_HANDLE;
404 }
405
406 /* FIXME: Acquire service database lock exclusively */
407
408 if (lpService->bDeleted)
409 {
410 DPRINT1("The service has already been marked for delete!\n");
411 return ERROR_SERVICE_MARKED_FOR_DELETE;
412 }
413
414 /* Mark service for delete */
415 lpService->bDeleted = TRUE;
416
417 dwError = ScmMarkServiceForDelete(lpService);
418
419 /* FIXME: Release service database lock */
420
421 DPRINT("ScmrDeleteService() done\n");
422
423 return dwError;
424 }
425
426
427 /* Function 3 */
428 unsigned long
429 ScmrLockServiceDatabase(handle_t BindingHandle,
430 unsigned int hSCManager,
431 unsigned int *hLock)
432 {
433 PMANAGER_HANDLE hMgr;
434
435 DPRINT("ScmrLockServiceDatabase() called\n");
436
437 *hLock = 0;
438
439 hMgr = (PMANAGER_HANDLE)hSCManager;
440 if (hMgr->Handle.Tag != MANAGER_TAG)
441 return ERROR_INVALID_HANDLE;
442
443 if (!RtlAreAllAccessesGranted(hMgr->Handle.DesiredAccess,
444 SC_MANAGER_LOCK))
445 return ERROR_ACCESS_DENIED;
446
447 // return ScmLockDatabase(0, hMgr->0xC, hLock);
448
449 /* FIXME: Lock the database */
450 *hLock = 0x12345678; /* Dummy! */
451
452 return ERROR_SUCCESS;
453 }
454
455
456 /* Function 4 */
457 unsigned long
458 ScmrQueryServiceObjectSecurity(handle_t BindingHandle,
459 unsigned int hService,
460 unsigned long dwSecurityInformation,
461 unsigned char *lpSecurityDescriptor,
462 unsigned long dwSecuityDescriptorSize,
463 unsigned long *pcbBytesNeeded)
464 {
465 #if 0
466 PSERVICE_HANDLE hSvc;
467 PSERVICE lpService;
468 ULONG DesiredAccess = 0;
469 NTSTATUS Status;
470 DWORD dwBytesNeeded;
471 DWORD dwError;
472
473 DPRINT("ScmrQueryServiceObjectSecurity() called\n");
474
475 hSvc = (PSERVICE_HANDLE)hService;
476 if (hSvc->Handle.Tag != SERVICE_TAG)
477 {
478 DPRINT1("Invalid handle tag!\n");
479 return ERROR_INVALID_HANDLE;
480 }
481
482 if (dwSecurityInformation & (DACL_SECURITY_INFORMATION ||
483 GROUP_SECURITY_INFORMATION ||
484 OWNER_SECURITY_INFORMATION))
485 DesiredAccess |= READ_CONTROL;
486
487 if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
488 DesiredAccess |= ACCESS_SYSTEM_SECURITY;
489
490 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
491 DesiredAccess))
492 {
493 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
494 return ERROR_ACCESS_DENIED;
495 }
496
497 lpService = hSvc->ServiceEntry;
498 if (lpService == NULL)
499 {
500 DPRINT1("lpService == NULL!\n");
501 return ERROR_INVALID_HANDLE;
502 }
503
504 /* FIXME: Lock the service list */
505
506 Status = RtlQuerySecurityObject(lpService->lpSecurityDescriptor,
507 dwSecurityInformation,
508 (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
509 dwSecuityDescriptorSize,
510 &dwBytesNeeded);
511
512 /* FIXME: Unlock the service list */
513
514 if (NT_SUCCESS(Status))
515 {
516 *pcbBytesNeeded = dwBytesNeeded;
517 dwError = STATUS_SUCCESS;
518 }
519 else if (Status == STATUS_BUFFER_TOO_SMALL)
520 {
521 *pcbBytesNeeded = dwBytesNeeded;
522 dwError = ERROR_INSUFFICIENT_BUFFER;
523 }
524 else if (Status == STATUS_BAD_DESCRIPTOR_FORMAT)
525 {
526 dwError = ERROR_GEN_FAILURE;
527 }
528 else
529 {
530 dwError = RtlNtStatusToDosError(Status);
531 }
532
533 return dwError;
534 #endif
535 DPRINT1("ScmrQueryServiceObjectSecurity() is unimplemented\n");
536 return ERROR_CALL_NOT_IMPLEMENTED;
537 }
538
539
540 /* Function 5 */
541 unsigned long
542 ScmrSetServiceObjectSecurity(handle_t BindingHandle,
543 unsigned int hService,
544 unsigned long dwSecurityInformation,
545 unsigned char *lpSecurityDescriptor,
546 unsigned long dwSecuityDescriptorSize)
547 {
548 #if 0
549 PSERVICE_HANDLE hSvc;
550 PSERVICE lpService;
551 ULONG DesiredAccess = 0;
552 HANDLE hToken = NULL;
553 HKEY hServiceKey;
554 NTSTATUS Status;
555 DWORD dwError;
556
557 DPRINT1("ScmrSetServiceObjectSecurity() called\n");
558
559 hSvc = (PSERVICE_HANDLE)hService;
560 if (hSvc->Handle.Tag != SERVICE_TAG)
561 {
562 DPRINT1("Invalid handle tag!\n");
563 return ERROR_INVALID_HANDLE;
564 }
565
566 if (dwSecurityInformation == 0 ||
567 dwSecurityInformation & ~0xF)
568 return 0x57;
569
570 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR)lpSecurityDescriptor))
571 return 0x57;
572
573 if (dwSecurityInformation & SACL_SECURITY_INFORMATION)
574 DesiredAccess |= ACCESS_SYSTEM_SECURITY;
575
576 if (dwSecurityInformation & DACL_SECURITY_INFORMATION)
577 DesiredAccess |= 0x40000;
578
579 if (dwSecurityInformation & (OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION))
580 DesiredAccess |= 0x80000;
581
582 if ((dwSecurityInformation & OWNER_SECURITY_INFORMATION) &&
583 (((PSECURITY_DESCRIPTOR)lpSecurityDescriptor)->Owner == NULL))
584 return 0x57;
585
586 if ((dwSecurityInformation & GROUP_SECURITY_INFORMATION) &&
587 (((PSECURITY_DESCRIPTOR)lpSecurityDescriptor)->Group == NULL))
588 return 0x57;
589
590 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
591 DesiredAccess))
592 {
593 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
594 return ERROR_ACCESS_DENIED;
595 }
596
597 lpService = hSvc->ServiceEntry;
598 if (lpService == NULL)
599 {
600 DPRINT1("lpService == NULL!\n");
601 return ERROR_INVALID_HANDLE;
602 }
603
604 if (lpService->bDeleted)
605 return 0x430;
606
607 // RpcImpersonateClient(NULL);
608
609 Status = NtOpenThreadToken(NtCurrentThread(),
610 8,
611 1,
612 &hToken);
613 if (!NT_SUCCESS(Status))
614 return RtlNtStatusToDosError(Status);
615
616 // RpcRevertToSelf();
617
618 /* FIXME: Lock service database */
619
620 Status = RtlSetSecurityObject(dwSecurityInformation,
621 (PSECURITY_DESCRIPTOR)lpSecurityDescriptor,
622 &lpService->lpSecurityDescriptor,
623 &ScmServiceMapping,
624 hToken);
625 if (!NT_SUCCESS(Status))
626 {
627 dwError = RtlNtStatusToDosError(Status);
628 goto Done;
629 }
630
631 dwError = ScmOpenServiceKey(lpService->lpServiceName,
632 0x20006,
633 &hServiceKey);
634 if (dwError != ERROR_SUCCESS)
635 goto Done;
636
637 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
638 // lpService->lpSecurityDescriptor);
639
640 RegFlushKey(hServiceKey);
641 RegCloseKey(hServiceKey);
642
643 Done:;
644
645 if (hToken != NULL)
646 NtClose(hToken);
647
648 /* FIXME: Unlock service database */
649
650 DPRINT1("ScmrSetServiceObjectSecurity() done (Error %lu)\n", dwError);
651
652 return dwError;
653 #endif
654
655 DPRINT1("ScmrSetServiceObjectSecurity() is unimplemented\n");
656 return ERROR_CALL_NOT_IMPLEMENTED;
657 }
658
659
660 /* Function 6 */
661 unsigned long
662 ScmrQueryServiceStatus(handle_t BindingHandle,
663 unsigned int hService,
664 LPSERVICE_STATUS lpServiceStatus)
665 {
666 PSERVICE_HANDLE hSvc;
667 PSERVICE lpService;
668
669 DPRINT("ScmrQueryServiceStatus() called\n");
670
671 if (ScmShutdown)
672 return ERROR_SHUTDOWN_IN_PROGRESS;
673
674 hSvc = (PSERVICE_HANDLE)hService;
675 if (hSvc->Handle.Tag != SERVICE_TAG)
676 {
677 DPRINT1("Invalid handle tag!\n");
678 return ERROR_INVALID_HANDLE;
679 }
680
681 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
682 SERVICE_QUERY_STATUS))
683 {
684 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
685 return ERROR_ACCESS_DENIED;
686 }
687
688 lpService = hSvc->ServiceEntry;
689 if (lpService == NULL)
690 {
691 DPRINT1("lpService == NULL!\n");
692 return ERROR_INVALID_HANDLE;
693 }
694
695 /* Return service status information */
696 RtlCopyMemory(lpServiceStatus,
697 &lpService->Status,
698 sizeof(SERVICE_STATUS));
699
700 return ERROR_SUCCESS;
701 }
702
703
704 /* Function 7 */
705 unsigned long
706 ScmrSetServiceStatus(handle_t BindingHandle,
707 unsigned long hServiceStatus) /* FIXME */
708 {
709 DPRINT1("ScmrSetServiceStatus() is unimplemented\n");
710 /* FIXME */
711 return ERROR_CALL_NOT_IMPLEMENTED;
712 }
713
714
715 /* Function 8 */
716 unsigned long
717 ScmrUnlockServiceDatabase(handle_t BindingHandle,
718 unsigned int hLock)
719 {
720 DPRINT1("ScmrUnlockServiceDatabase() called\n");
721 /* FIXME */
722 return ERROR_SUCCESS;
723 }
724
725
726 /* Function 9 */
727 unsigned long
728 ScmrNotifyBootConfigStatus(handle_t BindingHandle,
729 unsigned long BootAcceptable)
730 {
731 DPRINT1("ScmrNotifyBootConfigStatus() called\n");
732 /* FIXME */
733 return ERROR_CALL_NOT_IMPLEMENTED;
734 }
735
736
737 /* Function 10 */
738 unsigned long
739 ScmrSetServiceBitsW(handle_t BindingHandle,
740 unsigned long hServiceStatus,
741 unsigned long dwServiceBits,
742 unsigned long bSetBitsOn,
743 unsigned long bUpdateImmediately,
744 wchar_t *lpString)
745 {
746 DPRINT1("ScmrSetServiceBitsW() called\n");
747 /* FIXME */
748 return ERROR_CALL_NOT_IMPLEMENTED;
749 }
750
751
752 /* Function 11 */
753 unsigned long
754 ScmrChangeServiceConfigW(handle_t BiningHandle,
755 unsigned int hService,
756 unsigned long dwServiceType,
757 unsigned long dwStartType,
758 unsigned long dwErrorControl,
759 wchar_t *lpBinaryPathName,
760 wchar_t *lpLoadOrderGroup,
761 unsigned long *lpdwTagId, /* in, out, unique */
762 wchar_t *lpDependencies,
763 unsigned long dwDependenciesLength,
764 wchar_t *lpServiceStartName,
765 wchar_t *lpPassword,
766 unsigned long dwPasswordLength,
767 wchar_t *lpDisplayName)
768 {
769 DWORD dwError = ERROR_SUCCESS;
770 PSERVICE_HANDLE hSvc;
771 PSERVICE lpService = NULL;
772 HKEY hServiceKey = NULL;
773
774 DPRINT("ScmrChangeServiceConfigW() called\n");
775 DPRINT("dwServiceType = %lu\n", dwServiceType);
776 DPRINT("dwStartType = %lu\n", dwStartType);
777 DPRINT("dwErrorControl = %lu\n", dwErrorControl);
778 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName);
779 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup);
780 DPRINT("lpDisplayName = %S\n", lpDisplayName);
781
782 if (ScmShutdown)
783 return ERROR_SHUTDOWN_IN_PROGRESS;
784
785 hSvc = (PSERVICE_HANDLE)hService;
786 if (hSvc->Handle.Tag != SERVICE_TAG)
787 {
788 DPRINT1("Invalid handle tag!\n");
789 return ERROR_INVALID_HANDLE;
790 }
791
792 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
793 SERVICE_CHANGE_CONFIG))
794 {
795 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
796 return ERROR_ACCESS_DENIED;
797 }
798
799 lpService = hSvc->ServiceEntry;
800 if (lpService == NULL)
801 {
802 DPRINT1("lpService == NULL!\n");
803 return ERROR_INVALID_HANDLE;
804 }
805
806 /* FIXME: Lock database exclusively */
807
808 if (lpService->bDeleted)
809 {
810 /* FIXME: Unlock database */
811 DPRINT1("The service has already been marked for delete!\n");
812 return ERROR_SERVICE_MARKED_FOR_DELETE;
813 }
814
815 /* Open the service key */
816 dwError = ScmOpenServiceKey(lpService->szServiceName,
817 KEY_SET_VALUE,
818 &hServiceKey);
819 if (dwError != ERROR_SUCCESS)
820 goto done;
821
822 /* Write service data to the registry */
823 /* Set the display name */
824 if (lpDisplayName != NULL && *lpDisplayName != 0)
825 {
826 RegSetValueExW(hServiceKey,
827 L"DisplayName",
828 0,
829 REG_SZ,
830 (LPBYTE)lpDisplayName,
831 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
832 /* FIXME: update lpService->lpDisplayName */
833 }
834
835 if (dwServiceType != SERVICE_NO_CHANGE)
836 {
837 /* Set the service type */
838 dwError = RegSetValueExW(hServiceKey,
839 L"Type",
840 0,
841 REG_DWORD,
842 (LPBYTE)&dwServiceType,
843 sizeof(DWORD));
844 if (dwError != ERROR_SUCCESS)
845 goto done;
846
847 lpService->Status.dwServiceType = dwServiceType;
848 }
849
850 if (dwStartType != SERVICE_NO_CHANGE)
851 {
852 /* Set the start value */
853 dwError = RegSetValueExW(hServiceKey,
854 L"Start",
855 0,
856 REG_DWORD,
857 (LPBYTE)&dwStartType,
858 sizeof(DWORD));
859 if (dwError != ERROR_SUCCESS)
860 goto done;
861
862 lpService->dwStartType = dwStartType;
863 }
864
865 if (dwErrorControl != SERVICE_NO_CHANGE)
866 {
867 /* Set the error control value */
868 dwError = RegSetValueExW(hServiceKey,
869 L"ErrorControl",
870 0,
871 REG_DWORD,
872 (LPBYTE)&dwErrorControl,
873 sizeof(DWORD));
874 if (dwError != ERROR_SUCCESS)
875 goto done;
876
877 lpService->dwErrorControl = dwErrorControl;
878 }
879
880 #if 0
881 /* FIXME: set the new ImagePath value */
882
883 /* Set the image path */
884 if (dwServiceType & SERVICE_WIN32)
885 {
886 if (lpBinaryPathName != NULL && *lpBinaryPathName != 0)
887 {
888 dwError = RegSetValueExW(hServiceKey,
889 L"ImagePath",
890 0,
891 REG_EXPAND_SZ,
892 (LPBYTE)lpBinaryPathName,
893 (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
894 if (dwError != ERROR_SUCCESS)
895 goto done;
896 }
897 }
898 else if (dwServiceType & SERVICE_DRIVER)
899 {
900 if (lpImagePath != NULL && *lpImagePath != 0)
901 {
902 dwError = RegSetValueExW(hServiceKey,
903 L"ImagePath",
904 0,
905 REG_EXPAND_SZ,
906 (LPBYTE)lpImagePath,
907 (wcslen(lpImagePath) + 1) *sizeof(WCHAR));
908 if (dwError != ERROR_SUCCESS)
909 goto done;
910 }
911 }
912 #endif
913
914 /* Set the group name */
915 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
916 {
917 dwError = RegSetValueExW(hServiceKey,
918 L"Group",
919 0,
920 REG_SZ,
921 (LPBYTE)lpLoadOrderGroup,
922 (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
923 if (dwError != ERROR_SUCCESS)
924 goto done;
925 /* FIXME: update lpService->lpServiceGroup */
926 }
927
928 if (lpdwTagId != NULL)
929 {
930 dwError = ScmAssignNewTag(lpService->lpServiceGroup,
931 &lpService->dwTag);
932 if (dwError != ERROR_SUCCESS)
933 goto done;
934 dwError = RegSetValueExW(hServiceKey,
935 L"Tag",
936 0,
937 REG_DWORD,
938 (LPBYTE)&lpService->dwTag,
939 sizeof(DWORD));
940 if (dwError != ERROR_SUCCESS)
941 goto done;
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 /* Write service data to the registry */
1077 /* Create the service key */
1078 dwError = ScmCreateServiceKey(lpServiceName,
1079 KEY_WRITE,
1080 &hServiceKey);
1081 if (dwError != ERROR_SUCCESS)
1082 goto done;
1083
1084 /* Set the display name */
1085 if (lpDisplayName != NULL && *lpDisplayName != 0)
1086 {
1087 RegSetValueExW(hServiceKey,
1088 L"DisplayName",
1089 0,
1090 REG_SZ,
1091 (LPBYTE)lpDisplayName,
1092 (wcslen(lpDisplayName) + 1) * sizeof(WCHAR));
1093 }
1094
1095 /* Set the service type */
1096 dwError = RegSetValueExW(hServiceKey,
1097 L"Type",
1098 0,
1099 REG_DWORD,
1100 (LPBYTE)&dwServiceType,
1101 sizeof(DWORD));
1102 if (dwError != ERROR_SUCCESS)
1103 goto done;
1104
1105 /* Set the start value */
1106 dwError = RegSetValueExW(hServiceKey,
1107 L"Start",
1108 0,
1109 REG_DWORD,
1110 (LPBYTE)&dwStartType,
1111 sizeof(DWORD));
1112 if (dwError != ERROR_SUCCESS)
1113 goto done;
1114
1115 /* Set the error control value */
1116 dwError = RegSetValueExW(hServiceKey,
1117 L"ErrorControl",
1118 0,
1119 REG_DWORD,
1120 (LPBYTE)&dwErrorControl,
1121 sizeof(DWORD));
1122 if (dwError != ERROR_SUCCESS)
1123 goto done;
1124
1125 /* Set the image path */
1126 if (dwServiceType & SERVICE_WIN32)
1127 {
1128 dwError = RegSetValueExW(hServiceKey,
1129 L"ImagePath",
1130 0,
1131 REG_EXPAND_SZ,
1132 (LPBYTE)lpBinaryPathName,
1133 (wcslen(lpBinaryPathName) + 1) * sizeof(WCHAR));
1134 if (dwError != ERROR_SUCCESS)
1135 goto done;
1136 }
1137 else if (dwServiceType & SERVICE_DRIVER)
1138 {
1139 dwError = RegSetValueExW(hServiceKey,
1140 L"ImagePath",
1141 0,
1142 REG_EXPAND_SZ,
1143 (LPBYTE)lpImagePath,
1144 (wcslen(lpImagePath) + 1) *sizeof(WCHAR));
1145 if (dwError != ERROR_SUCCESS)
1146 goto done;
1147 }
1148
1149 /* Set the group name */
1150 if (lpLoadOrderGroup != NULL && *lpLoadOrderGroup != 0)
1151 {
1152 dwError = RegSetValueExW(hServiceKey,
1153 L"Group",
1154 0,
1155 REG_SZ,
1156 (LPBYTE)lpLoadOrderGroup,
1157 (wcslen(lpLoadOrderGroup) + 1) * sizeof(WCHAR));
1158 if (dwError != ERROR_SUCCESS)
1159 goto done;
1160 }
1161
1162 if (lpdwTagId != NULL)
1163 {
1164 dwError = ScmAssignNewTag(lpService->lpServiceGroup,
1165 &lpService->dwTag);
1166 if (dwError != ERROR_SUCCESS)
1167 goto done;
1168 dwError = RegSetValueExW(hServiceKey,
1169 L"Tag",
1170 0,
1171 REG_DWORD,
1172 (LPBYTE)&lpService->dwTag,
1173 sizeof(DWORD));
1174 if (dwError != ERROR_SUCCESS)
1175 goto done;
1176 }
1177
1178 /* Write dependencies */
1179 if (lpDependencies != NULL && *lpDependencies != 0)
1180 {
1181 dwError = ScmWriteDependencies(hServiceKey,
1182 lpDependencies,
1183 dwDependenciesLength);
1184 if (dwError != ERROR_SUCCESS)
1185 goto done;
1186 }
1187
1188 if (lpPassword != NULL)
1189 {
1190 /* FIXME: Write password */
1191 }
1192
1193 dwError = ScmCreateServiceHandle(lpService,
1194 &hServiceHandle);
1195 if (dwError != ERROR_SUCCESS)
1196 goto done;
1197
1198 dwError = ScmCheckAccess(hServiceHandle,
1199 dwDesiredAccess);
1200 if (dwError != ERROR_SUCCESS)
1201 goto done;
1202
1203 done:;
1204 if (hServiceKey != NULL)
1205 RegCloseKey(hServiceKey);
1206
1207 if (dwError == ERROR_SUCCESS)
1208 {
1209 DPRINT("hService %lx\n", hServiceHandle);
1210 *hService = (unsigned int)hServiceHandle;
1211
1212 if (lpdwTagId != NULL)
1213 *lpdwTagId = lpService->dwTag;
1214 }
1215 else
1216 {
1217 /* Release the display name buffer */
1218 if (lpService->lpServiceName != lpService->lpDisplayName)
1219 HeapFree(GetProcessHeap(), 0, lpService->lpDisplayName);
1220
1221 if (hServiceHandle != NULL)
1222 {
1223 /* Remove the service handle */
1224 HeapFree(GetProcessHeap(), 0, hServiceHandle);
1225 }
1226
1227 if (lpService != NULL)
1228 {
1229 /* FIXME: remove the service entry */
1230 }
1231 }
1232
1233 if (lpImagePath != NULL)
1234 HeapFree(GetProcessHeap(), 0, lpImagePath);
1235
1236 DPRINT("ScmrCreateServiceW() done (Error %lu)\n", dwError);
1237
1238 return dwError;
1239 }
1240
1241
1242 /* Function 13 */
1243 unsigned long
1244 ScmrEnumDependentServicesW(handle_t BindingHandle,
1245 unsigned int hService,
1246 unsigned long dwServiceState,
1247 unsigned char *lpServices,
1248 unsigned long cbBufSize,
1249 unsigned long *pcbBytesNeeded,
1250 unsigned long *lpServicesReturned)
1251 {
1252 DWORD dwError = ERROR_SUCCESS;
1253
1254 DPRINT1("ScmrEnumDependentServicesW() called\n");
1255
1256 DPRINT1("ScmrEnumDependentServicesW() done (Error %lu)\n", dwError);
1257
1258 return dwError;
1259 }
1260
1261
1262 /* Function 14 */
1263 unsigned long
1264 ScmrEnumServicesStatusW(handle_t BindingHandle,
1265 unsigned int hSCManager,
1266 unsigned long dwServiceType,
1267 unsigned long dwServiceState,
1268 unsigned char *lpServices,
1269 unsigned long dwBufSize,
1270 unsigned long *pcbBytesNeeded,
1271 unsigned long *lpServicesReturned,
1272 unsigned long *lpResumeHandle)
1273 {
1274 PMANAGER_HANDLE hManager;
1275 PSERVICE lpService;
1276 DWORD dwError = ERROR_SUCCESS;
1277 PLIST_ENTRY ServiceEntry;
1278 PSERVICE CurrentService;
1279 DWORD dwState;
1280 DWORD dwRequiredSize;
1281 DWORD dwServiceCount;
1282 DWORD dwSize;
1283 DWORD dwLastResumeCount;
1284 LPENUM_SERVICE_STATUSW lpStatusPtr;
1285 LPWSTR lpStringPtr;
1286
1287 DPRINT("ScmrEnumServicesStatusW() called\n");
1288
1289 if (ScmShutdown)
1290 return ERROR_SHUTDOWN_IN_PROGRESS;
1291
1292 hManager = (PMANAGER_HANDLE)hSCManager;
1293 if (hManager->Handle.Tag != MANAGER_TAG)
1294 {
1295 DPRINT1("Invalid manager handle!\n");
1296 return ERROR_INVALID_HANDLE;
1297 }
1298
1299 /* Check access rights */
1300 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
1301 SC_MANAGER_ENUMERATE_SERVICE))
1302 {
1303 DPRINT1("Insufficient access rights! 0x%lx\n",
1304 hManager->Handle.DesiredAccess);
1305 return ERROR_ACCESS_DENIED;
1306 }
1307
1308 *pcbBytesNeeded = 0;
1309 *lpServicesReturned = 0;
1310
1311 dwLastResumeCount = *lpResumeHandle;
1312
1313 /* Lock the service list shared */
1314
1315 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
1316 if (lpService == NULL)
1317 {
1318 dwError = ERROR_SUCCESS;
1319 goto Done;
1320 }
1321
1322 dwRequiredSize = 0;
1323 dwServiceCount = 0;
1324
1325 for (ServiceEntry = &lpService->ServiceListEntry;
1326 ServiceEntry != &ServiceListHead;
1327 ServiceEntry = ServiceEntry->Flink)
1328 {
1329 CurrentService = CONTAINING_RECORD(ServiceEntry,
1330 SERVICE,
1331 ServiceListEntry);
1332
1333 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
1334 continue;
1335
1336 dwState = SERVICE_ACTIVE;
1337 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
1338 dwState = SERVICE_INACTIVE;
1339
1340 if ((dwState & dwServiceState) == 0)
1341 continue;
1342
1343 dwSize = sizeof(ENUM_SERVICE_STATUSW) +
1344 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
1345 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
1346
1347 if (dwRequiredSize + dwSize <= dwBufSize)
1348 {
1349 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
1350 dwRequiredSize += dwSize;
1351 dwServiceCount++;
1352 dwLastResumeCount = CurrentService->dwResumeCount;
1353 }
1354 else
1355 {
1356 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
1357 break;
1358 }
1359
1360 }
1361
1362 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
1363 DPRINT("dwServiceCount: %lu\n", dwServiceCount);
1364
1365 for (;
1366 ServiceEntry != &ServiceListHead;
1367 ServiceEntry = ServiceEntry->Flink)
1368 {
1369 CurrentService = CONTAINING_RECORD(ServiceEntry,
1370 SERVICE,
1371 ServiceListEntry);
1372
1373 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
1374 continue;
1375
1376 dwState = SERVICE_ACTIVE;
1377 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
1378 dwState = SERVICE_INACTIVE;
1379
1380 if ((dwState & dwServiceState) == 0)
1381 continue;
1382
1383 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) +
1384 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
1385 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
1386
1387 dwError = ERROR_MORE_DATA;
1388 }
1389
1390 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
1391
1392 *lpResumeHandle = dwLastResumeCount;
1393 *lpServicesReturned = dwServiceCount;
1394 *pcbBytesNeeded = dwRequiredSize;
1395
1396 lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpServices;
1397 lpStringPtr = (LPWSTR)((ULONG_PTR)lpServices +
1398 dwServiceCount * sizeof(ENUM_SERVICE_STATUSW));
1399
1400 dwRequiredSize = 0;
1401 for (ServiceEntry = &lpService->ServiceListEntry;
1402 ServiceEntry != &ServiceListHead;
1403 ServiceEntry = ServiceEntry->Flink)
1404 {
1405 CurrentService = CONTAINING_RECORD(ServiceEntry,
1406 SERVICE,
1407 ServiceListEntry);
1408
1409 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
1410 continue;
1411
1412 dwState = SERVICE_ACTIVE;
1413 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
1414 dwState = SERVICE_INACTIVE;
1415
1416 if ((dwState & dwServiceState) == 0)
1417 continue;
1418
1419 dwSize = sizeof(ENUM_SERVICE_STATUSW) +
1420 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
1421 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
1422
1423 if (dwRequiredSize + dwSize <= dwBufSize)
1424 {
1425 /* Copy the service name */
1426 wcscpy(lpStringPtr,
1427 CurrentService->lpServiceName);
1428 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
1429 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
1430
1431 /* Copy the display name */
1432 wcscpy(lpStringPtr,
1433 CurrentService->lpDisplayName);
1434 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
1435 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
1436
1437 /* Copy the status information */
1438 memcpy(&lpStatusPtr->ServiceStatus,
1439 &CurrentService->Status,
1440 sizeof(SERVICE_STATUS));
1441
1442 lpStatusPtr++;
1443 dwRequiredSize += dwSize;
1444 }
1445 else
1446 {
1447 break;
1448 }
1449
1450 }
1451
1452 Done:;
1453 /* Unlock the service list */
1454
1455 DPRINT("ScmrEnumServicesStatusW() done (Error %lu)\n", dwError);
1456
1457 return dwError;
1458 }
1459
1460
1461 /* Function 15 */
1462 unsigned long
1463 ScmrOpenSCManagerW(handle_t BindingHandle,
1464 wchar_t *lpMachineName,
1465 wchar_t *lpDatabaseName,
1466 unsigned long dwDesiredAccess,
1467 unsigned int *hScm)
1468 {
1469 DWORD dwError;
1470 SC_HANDLE hHandle;
1471
1472 DPRINT("ScmrOpenSCManagerW() called\n");
1473 DPRINT("lpMachineName = %p\n", lpMachineName);
1474 DPRINT("lpMachineName: %S\n", lpMachineName);
1475 DPRINT("lpDataBaseName = %p\n", lpDatabaseName);
1476 DPRINT("lpDataBaseName: %S\n", lpDatabaseName);
1477 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
1478
1479 if (ScmShutdown)
1480 return ERROR_SHUTDOWN_IN_PROGRESS;
1481
1482 dwError = ScmCreateManagerHandle(lpDatabaseName,
1483 &hHandle);
1484 if (dwError != ERROR_SUCCESS)
1485 {
1486 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError);
1487 return dwError;
1488 }
1489
1490 /* Check the desired access */
1491 dwError = ScmCheckAccess(hHandle,
1492 dwDesiredAccess | SC_MANAGER_CONNECT);
1493 if (dwError != ERROR_SUCCESS)
1494 {
1495 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
1496 HeapFree(GetProcessHeap(), 0, hHandle);
1497 return dwError;
1498 }
1499
1500 *hScm = (unsigned int)hHandle;
1501 DPRINT("*hScm = %x\n", *hScm);
1502
1503 DPRINT("ScmrOpenSCManagerW() done\n");
1504
1505 return ERROR_SUCCESS;
1506 }
1507
1508
1509 /* Function 16 */
1510 unsigned int
1511 ScmrOpenServiceW(handle_t BindingHandle,
1512 unsigned int hSCManager,
1513 wchar_t *lpServiceName,
1514 unsigned long dwDesiredAccess,
1515 unsigned int *hService)
1516 {
1517 PSERVICE lpService;
1518 PMANAGER_HANDLE hManager;
1519 SC_HANDLE hHandle;
1520 DWORD dwError;
1521
1522 DPRINT("ScmrOpenServiceW() called\n");
1523 DPRINT("hSCManager = %x\n", hSCManager);
1524 DPRINT("lpServiceName = %p\n", lpServiceName);
1525 DPRINT("lpServiceName: %S\n", lpServiceName);
1526 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
1527
1528 if (ScmShutdown)
1529 return ERROR_SHUTDOWN_IN_PROGRESS;
1530
1531 hManager = (PMANAGER_HANDLE)hSCManager;
1532 if (hManager->Handle.Tag != MANAGER_TAG)
1533 {
1534 DPRINT1("Invalid manager handle!\n");
1535 return ERROR_INVALID_HANDLE;
1536 }
1537
1538 /* FIXME: Lock the service list */
1539
1540 /* Get service database entry */
1541 lpService = ScmGetServiceEntryByName(lpServiceName);
1542 if (lpService == NULL)
1543 {
1544 DPRINT("Could not find a service!\n");
1545 return ERROR_SERVICE_DOES_NOT_EXIST;
1546 }
1547
1548 /* Create a service handle */
1549 dwError = ScmCreateServiceHandle(lpService,
1550 &hHandle);
1551 if (dwError != ERROR_SUCCESS)
1552 {
1553 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError);
1554 return dwError;
1555 }
1556
1557 /* Check the desired access */
1558 dwError = ScmCheckAccess(hHandle,
1559 dwDesiredAccess);
1560 if (dwError != ERROR_SUCCESS)
1561 {
1562 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
1563 HeapFree(GetProcessHeap(), 0, hHandle);
1564 return dwError;
1565 }
1566
1567 *hService = (unsigned int)hHandle;
1568 DPRINT("*hService = %x\n", *hService);
1569
1570 DPRINT("ScmrOpenServiceW() done\n");
1571
1572 return ERROR_SUCCESS;
1573 }
1574
1575
1576 /* Function 17 */
1577 unsigned long
1578 ScmrQueryServiceConfigW(handle_t BindingHandle,
1579 unsigned int hService,
1580 unsigned char *lpServiceConfig,
1581 unsigned long cbBufSize,
1582 unsigned long *pcbBytesNeeded)
1583 {
1584 DWORD dwError = ERROR_SUCCESS;
1585 PSERVICE_HANDLE hSvc;
1586 PSERVICE lpService = NULL;
1587 HKEY hServiceKey = NULL;
1588 LPWSTR lpImagePath = NULL;
1589 DWORD dwRequiredSize;
1590 LPQUERY_SERVICE_CONFIGW lpConfig;
1591 LPWSTR lpStr;
1592
1593 DPRINT1("ScmrQueryServiceConfigW() called\n");
1594
1595 if (ScmShutdown)
1596 return ERROR_SHUTDOWN_IN_PROGRESS;
1597
1598 hSvc = (PSERVICE_HANDLE)hService;
1599 if (hSvc->Handle.Tag != SERVICE_TAG)
1600 {
1601 DPRINT1("Invalid handle tag!\n");
1602 return ERROR_INVALID_HANDLE;
1603 }
1604
1605 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
1606 SERVICE_QUERY_CONFIG))
1607 {
1608 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1609 return ERROR_ACCESS_DENIED;
1610 }
1611
1612 lpService = hSvc->ServiceEntry;
1613 if (lpService == NULL)
1614 {
1615 DPRINT1("lpService == NULL!\n");
1616 return ERROR_INVALID_HANDLE;
1617 }
1618
1619 /* FIXME: Lock the service database shared */
1620
1621 dwError = ScmOpenServiceKey(lpService->lpServiceName,
1622 KEY_READ,
1623 &hServiceKey);
1624 if (dwError != ERROR_SUCCESS)
1625 goto Done;
1626
1627 dwError = ScmReadString(hServiceKey,
1628 L"ImagePath",
1629 &lpImagePath);
1630 if (dwError != ERROR_SUCCESS)
1631 goto Done;
1632
1633 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
1634
1635 if (lpImagePath != NULL)
1636 dwRequiredSize += ((wcslen(lpImagePath) + 1) * sizeof(WCHAR));
1637
1638 if (lpService->lpServiceGroup != NULL)
1639 dwRequiredSize += ((wcslen(lpService->lpServiceGroup) + 1) * sizeof(WCHAR));
1640
1641 /* FIXME: Add Dependencies length*/
1642
1643 /* FIXME: Add ServiceStartName length*/
1644
1645 if (lpService->lpDisplayName != NULL)
1646 dwRequiredSize += ((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR));
1647
1648 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
1649 {
1650 dwError = ERROR_INSUFFICIENT_BUFFER;
1651 }
1652 else
1653 {
1654 lpConfig = (LPQUERY_SERVICE_CONFIGW)lpServiceConfig;
1655 lpConfig->dwServiceType = lpService->Status.dwServiceType;
1656 lpConfig->dwStartType = lpService->dwStartType;
1657 lpConfig->dwErrorControl = lpService->dwErrorControl;
1658 lpConfig->dwTagId = lpService->dwTag;
1659
1660 lpStr = (LPWSTR)(lpConfig + 1);
1661
1662 if (lpImagePath != NULL)
1663 {
1664 wcscpy(lpStr, lpImagePath);
1665 lpConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1666 lpStr += (wcslen(lpImagePath) + 1);
1667 }
1668 else
1669 {
1670 lpConfig->lpBinaryPathName = NULL;
1671 }
1672
1673 if (lpService->lpServiceGroup != NULL)
1674 {
1675 wcscpy(lpStr, lpService->lpServiceGroup);
1676 lpConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1677 lpStr += (wcslen(lpService->lpServiceGroup) + 1);
1678 }
1679 else
1680 {
1681 lpConfig->lpLoadOrderGroup = NULL;
1682 }
1683
1684 /* FIXME: Append Dependencies */
1685 lpConfig->lpDependencies = NULL;
1686
1687 /* FIXME: Append ServiceStartName */
1688 lpConfig->lpServiceStartName = NULL;
1689
1690 if (lpService->lpDisplayName != NULL)
1691 {
1692 wcscpy(lpStr, lpService->lpDisplayName);
1693 lpConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1694 }
1695 else
1696 {
1697 lpConfig->lpDisplayName = NULL;
1698 }
1699 }
1700
1701 if (pcbBytesNeeded != NULL)
1702 *pcbBytesNeeded = dwRequiredSize;
1703
1704 Done:;
1705 if (lpImagePath != NULL)
1706 HeapFree(GetProcessHeap(), 0, lpImagePath);
1707
1708 if (hServiceKey != NULL)
1709 RegCloseKey(hServiceKey);
1710
1711 /* FIXME: Unlock the service database */
1712
1713 DPRINT1("ScmrQueryServiceConfigW() done\n");
1714
1715 return dwError;
1716 }
1717
1718
1719 /* Function 18 */
1720 unsigned long
1721 ScmrQueryServiceLockStatusW(handle_t BindingHandle,
1722 unsigned int hSCManager,
1723 unsigned char *lpLockStatus, /* [out, unique, size_is(cbBufSize)] */
1724 unsigned long cbBufSize, /* [in] */
1725 unsigned long *pcbBytesNeeded) /* [out] */
1726 {
1727 DPRINT1("ScmrQueryServiceLockStatusW() called\n");
1728 return ERROR_CALL_NOT_IMPLEMENTED;
1729 }
1730
1731
1732 /* Function 19 */
1733 /* ScmrStartServiceW */
1734
1735
1736 /* Function 20 */
1737 unsigned long
1738 ScmrGetServiceDisplayNameW(handle_t BindingHandle,
1739 unsigned int hSCManager,
1740 wchar_t *lpServiceName,
1741 wchar_t *lpDisplayName, /* [out, unique] */
1742 unsigned long *lpcchBuffer)
1743 {
1744 // PMANAGER_HANDLE hManager;
1745 PSERVICE lpService;
1746 DWORD dwLength;
1747 DWORD dwError;
1748
1749 DPRINT("ScmrGetServiceDisplayNameW() called\n");
1750 DPRINT("hSCManager = %x\n", hSCManager);
1751 DPRINT("lpServiceName: %S\n", lpServiceName);
1752 DPRINT("lpDisplayName: %p\n", lpDisplayName);
1753 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
1754
1755 // hManager = (PMANAGER_HANDLE)hSCManager;
1756 // if (hManager->Handle.Tag != MANAGER_TAG)
1757 // {
1758 // DPRINT1("Invalid manager handle!\n");
1759 // return ERROR_INVALID_HANDLE;
1760 // }
1761
1762 /* Get service database entry */
1763 lpService = ScmGetServiceEntryByName(lpServiceName);
1764 if (lpService == NULL)
1765 {
1766 DPRINT1("Could not find a service!\n");
1767 return ERROR_SERVICE_DOES_NOT_EXIST;
1768 }
1769
1770 dwLength = wcslen(lpService->lpDisplayName) + 1;
1771
1772 if (lpDisplayName != NULL &&
1773 *lpcchBuffer >= dwLength)
1774 {
1775 wcscpy(lpDisplayName, lpService->lpDisplayName);
1776 }
1777
1778 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
1779
1780 *lpcchBuffer = dwLength;
1781
1782 return dwError;
1783 }
1784
1785
1786 /* Function 21 */
1787 unsigned long
1788 ScmrGetServiceKeyNameW(handle_t BindingHandle,
1789 unsigned int hSCManager,
1790 wchar_t *lpDisplayName,
1791 wchar_t *lpServiceName, /* [out, unique] */
1792 unsigned long *lpcchBuffer)
1793 {
1794 // PMANAGER_HANDLE hManager;
1795 PSERVICE lpService;
1796 DWORD dwLength;
1797 DWORD dwError;
1798
1799 DPRINT("ScmrGetServiceKeyNameW() called\n");
1800 DPRINT("hSCManager = %x\n", hSCManager);
1801 DPRINT("lpDisplayName: %S\n", lpDisplayName);
1802 DPRINT("lpServiceName: %p\n", lpServiceName);
1803 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
1804
1805 // hManager = (PMANAGER_HANDLE)hSCManager;
1806 // if (hManager->Handle.Tag != MANAGER_TAG)
1807 // {
1808 // DPRINT1("Invalid manager handle!\n");
1809 // return ERROR_INVALID_HANDLE;
1810 // }
1811
1812 /* Get service database entry */
1813 lpService = ScmGetServiceEntryByDisplayName(lpDisplayName);
1814 if (lpService == NULL)
1815 {
1816 DPRINT1("Could not find a service!\n");
1817 return ERROR_SERVICE_DOES_NOT_EXIST;
1818 }
1819
1820 dwLength = wcslen(lpService->lpServiceName) + 1;
1821
1822 if (lpServiceName != NULL &&
1823 *lpcchBuffer >= dwLength)
1824 {
1825 wcscpy(lpServiceName, lpService->lpServiceName);
1826 }
1827
1828 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
1829
1830 *lpcchBuffer = dwLength;
1831
1832 return dwError;
1833 }
1834
1835
1836 /* Function 22 */
1837 unsigned long
1838 ScmrSetServiceBitsA(handle_t BindingHandle,
1839 unsigned long hServiceStatus,
1840 unsigned long dwServiceBits,
1841 unsigned long bSetBitsOn,
1842 unsigned long bUpdateImmediately,
1843 char *lpString)
1844 {
1845 DPRINT1("ScmrSetServiceBitsA() is unimplemented\n");
1846 return ERROR_CALL_NOT_IMPLEMENTED;
1847 }
1848
1849
1850 /* Function 23 */
1851 unsigned long
1852 ScmrChangeServiceConfigA(handle_t BiningHandle,
1853 unsigned int hService,
1854 unsigned long dwServiceType,
1855 unsigned long dwStartType,
1856 unsigned long dwErrorControl,
1857 char *lpBinaryPathName,
1858 char *lpLoadOrderGroup,
1859 unsigned long *lpdwTagId,
1860 char *lpDependencies,
1861 unsigned long dwDependenciesLength,
1862 char *lpServiceStartName,
1863 char *lpPassword,
1864 unsigned long dwPasswordLength,
1865 char *lpDisplayName)
1866 {
1867 DPRINT1("ScmrChangeServiceConfigA() is unimplemented\n");
1868 return ERROR_CALL_NOT_IMPLEMENTED;
1869 }
1870
1871
1872 /* Function 24 */
1873 unsigned long
1874 ScmrCreateServiceA(handle_t BindingHandle,
1875 unsigned int hSCManager,
1876 char *lpServiceName,
1877 char *lpDisplayName,
1878 unsigned long dwDesiredAccess,
1879 unsigned long dwServiceType,
1880 unsigned long dwStartType,
1881 unsigned long dwErrorControl,
1882 char *lpBinaryPathName,
1883 char *lpLoadOrderGroup,
1884 unsigned long *lpdwTagId, /* in, out */
1885 char *lpDependencies,
1886 unsigned long dwDependenciesLength,
1887 char *lpServiceStartName,
1888 char *lpPassword,
1889 unsigned long dwPasswordLength,
1890 unsigned int *hService) /* out */
1891 {
1892 DPRINT1("ScmrCreateServiceA() is unimplemented\n");
1893 return ERROR_CALL_NOT_IMPLEMENTED;
1894 }
1895
1896
1897 /* Function 25 */
1898 unsigned long
1899 ScmrEnumDependentServicesA(handle_t BindingHandle,
1900 unsigned int hService,
1901 unsigned long dwServiceState,
1902 unsigned char *lpServices,
1903 unsigned long cbBufSize,
1904 unsigned long *pcbBytesNeeded,
1905 unsigned long *lpServicesReturned)
1906 {
1907 DPRINT1("ScmrEnumDependentServicesA() is unimplemented\n");
1908 return ERROR_CALL_NOT_IMPLEMENTED;
1909 }
1910
1911
1912 /* Function 26 */
1913 unsigned long
1914 ScmrEnumServicesStatusA(handle_t BindingHandle,
1915 unsigned int hSCManager,
1916 unsigned long dwServiceType,
1917 unsigned long dwServiceState,
1918 unsigned char *lpServices,
1919 unsigned long dwBufSize,
1920 unsigned long *pcbBytesNeeded,
1921 unsigned long *lpServicesReturned,
1922 unsigned long *lpResumeHandle)
1923 {
1924 DPRINT1("ScmrEnumServicesAtatusA() is unimplemented\n");
1925 return ERROR_CALL_NOT_IMPLEMENTED;
1926 }
1927
1928
1929 /* Function 27 */
1930 unsigned long
1931 ScmrOpenSCManagerA(handle_t BindingHandle,
1932 char *lpMachineName,
1933 char *lpDatabaseName,
1934 unsigned long dwDesiredAccess,
1935 unsigned int *hScm)
1936 {
1937 UNICODE_STRING MachineName;
1938 UNICODE_STRING DatabaseName;
1939 DWORD dwError;
1940
1941 DPRINT("ScmrOpenSCManagerA() called\n");
1942
1943 if (lpMachineName)
1944 RtlCreateUnicodeStringFromAsciiz(&MachineName,
1945 lpMachineName);
1946
1947 if (lpDatabaseName)
1948 RtlCreateUnicodeStringFromAsciiz(&DatabaseName,
1949 lpDatabaseName);
1950
1951 dwError = ScmrOpenSCManagerW(BindingHandle,
1952 lpMachineName ? MachineName.Buffer : NULL,
1953 lpDatabaseName ? DatabaseName.Buffer : NULL,
1954 dwDesiredAccess,
1955 hScm);
1956
1957 if (lpMachineName)
1958 RtlFreeUnicodeString(&MachineName);
1959
1960 if (lpDatabaseName)
1961 RtlFreeUnicodeString(&DatabaseName);
1962
1963 return dwError;
1964 }
1965
1966
1967 /* Function 28 */
1968 unsigned int
1969 ScmrOpenServiceA(handle_t BindingHandle,
1970 unsigned int hSCManager,
1971 char *lpServiceName,
1972 unsigned long dwDesiredAccess,
1973 unsigned int *hService)
1974 {
1975 UNICODE_STRING ServiceName;
1976 DWORD dwError;
1977
1978 DPRINT("ScmrOpenServiceA() called\n");
1979
1980 RtlCreateUnicodeStringFromAsciiz(&ServiceName,
1981 lpServiceName);
1982
1983 dwError = ScmrOpenServiceW(BindingHandle,
1984 hSCManager,
1985 ServiceName.Buffer,
1986 dwDesiredAccess,
1987 hService);
1988
1989 RtlFreeUnicodeString(&ServiceName);
1990
1991 return dwError;
1992 }
1993
1994
1995 /* Function 29 */
1996 unsigned long
1997 ScmrQueryServiceConfigA(handle_t BindingHandle,
1998 unsigned int hService,
1999 unsigned char *lpServiceConfig,
2000 unsigned long cbBufSize,
2001 unsigned long *pcbBytesNeeded)
2002 {
2003 DPRINT1("ScmrQueryServiceConfigA() is unimplemented\n");
2004 return ERROR_CALL_NOT_IMPLEMENTED;
2005 }
2006
2007
2008 /* Function 30 */
2009 unsigned long
2010 ScmrQueryServiceLockStatusA(handle_t BindingHandle,
2011 unsigned int hSCManager,
2012 unsigned char *lpLockStatus, /* [out, unique, size_is(cbBufSize)] */
2013 unsigned long cbBufSize, /* [in] */
2014 unsigned long *pcbBytesNeeded) /* [out] */
2015 {
2016 DPRINT1("ScmrQueryServiceLockStatusA() called\n");
2017 return ERROR_CALL_NOT_IMPLEMENTED;
2018 }
2019
2020
2021 /* Function 31 */
2022 /* ScmrStartServiceA */
2023
2024
2025 /* Function 32 */
2026 unsigned long
2027 ScmrGetServiceDisplayNameA(handle_t BindingHandle,
2028 unsigned int hSCManager,
2029 char *lpServiceName,
2030 char *lpDisplayName, /* [out, unique] */
2031 unsigned long *lpcchBuffer)
2032 {
2033 DPRINT1("ScmrGetServiceDisplayNameA() is unimplemented\n");
2034 return ERROR_CALL_NOT_IMPLEMENTED;
2035 }
2036
2037
2038 /* Function 33 */
2039 unsigned long
2040 ScmrGetServiceKeyNameA(handle_t BindingHandle,
2041 unsigned int hSCManager,
2042 char *lpDisplayName,
2043 char *lpServiceName, /* [out, unique] */
2044 unsigned long *lpcchBuffer)
2045 {
2046 DPRINT1("ScmrGetServiceKeyNameA() is unimplemented\n");
2047 return ERROR_CALL_NOT_IMPLEMENTED;
2048 }
2049
2050
2051 /* Function 34 */
2052 /* ScmrGetCurrentGroupStateW */
2053
2054
2055 /* Function 35 */
2056 /* ScmrEnumServiceGroupW */
2057
2058
2059 /* Function 36 */
2060 /* ScmrChangeServiceConfig2A */
2061
2062
2063 /* Function 37 */
2064 unsigned long
2065 ScmrChangeServiceConfig2W(handle_t BindingHandle,
2066 unsigned int hService,
2067 unsigned long dwInfoLevel,
2068 unsigned char *lpInfo,
2069 unsigned long dwInfoSize)
2070 {
2071 DPRINT1("ScmrChangeServiceConfig2W() is unimplemented\n");
2072 return ERROR_CALL_NOT_IMPLEMENTED;
2073 }
2074
2075
2076 /* Function 38 */
2077 /* ScmrQueryServiceConfig2A */
2078
2079
2080 /* Function 39 */
2081 /* ScmrQueryServiceConfig2W */
2082
2083
2084 /* Function 40 */
2085 unsigned long
2086 ScmrQueryServiceStatusEx(handle_t BindingHandle,
2087 unsigned int hService,
2088 unsigned long InfoLevel,
2089 unsigned char *lpBuffer, /* out */
2090 unsigned long cbBufSize,
2091 unsigned long *pcbBytesNeeded) /* out */
2092 {
2093 LPSERVICE_STATUS_PROCESS lpStatus;
2094 PSERVICE_HANDLE hSvc;
2095 PSERVICE lpService;
2096
2097 DPRINT("ScmrQueryServiceStatusEx() called\n");
2098
2099 if (ScmShutdown)
2100 return ERROR_SHUTDOWN_IN_PROGRESS;
2101
2102 if (InfoLevel != SC_STATUS_PROCESS_INFO)
2103 return ERROR_INVALID_LEVEL;
2104
2105 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
2106
2107 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
2108 return ERROR_INSUFFICIENT_BUFFER;
2109
2110 hSvc = (PSERVICE_HANDLE)hService;
2111 if (hSvc->Handle.Tag != SERVICE_TAG)
2112 {
2113 DPRINT1("Invalid handle tag!\n");
2114 return ERROR_INVALID_HANDLE;
2115 }
2116
2117 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
2118 SERVICE_QUERY_STATUS))
2119 {
2120 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
2121 return ERROR_ACCESS_DENIED;
2122 }
2123
2124 lpService = hSvc->ServiceEntry;
2125 if (lpService == NULL)
2126 {
2127 DPRINT1("lpService == NULL!\n");
2128 return ERROR_INVALID_HANDLE;
2129 }
2130
2131 lpStatus = (LPSERVICE_STATUS_PROCESS)lpBuffer;
2132
2133 /* Return service status information */
2134 RtlCopyMemory(lpStatus,
2135 &lpService->Status,
2136 sizeof(SERVICE_STATUS));
2137
2138 lpStatus->dwProcessId = lpService->ProcessId; /* FIXME */
2139 lpStatus->dwServiceFlags = 0; /* FIXME */
2140
2141 return ERROR_SUCCESS;
2142 }
2143
2144
2145 /* Function 41 */
2146 /* ScmrEnumServicesStatusExA */
2147
2148
2149 /* Function 42 */
2150 unsigned long
2151 ScmrEnumServicesStatusExW(handle_t BindingHandle,
2152 unsigned int hSCManager,
2153 unsigned long InfoLevel,
2154 unsigned long dwServiceType,
2155 unsigned long dwServiceState,
2156 unsigned char *lpServices,
2157 unsigned long dwBufSize,
2158 unsigned long *pcbBytesNeeded,
2159 unsigned long *lpServicesReturned,
2160 unsigned long *lpResumeHandle,
2161 wchar_t *pszGroupName)
2162 {
2163 PMANAGER_HANDLE hManager;
2164 PSERVICE lpService;
2165 DWORD dwError = ERROR_SUCCESS;
2166 PLIST_ENTRY ServiceEntry;
2167 PSERVICE CurrentService;
2168 DWORD dwState;
2169 DWORD dwRequiredSize;
2170 DWORD dwServiceCount;
2171 DWORD dwSize;
2172 DWORD dwLastResumeCount;
2173 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
2174 LPWSTR lpStringPtr;
2175
2176 DPRINT("ScmrEnumServicesStatusExW() called\n");
2177
2178 if (ScmShutdown)
2179 return ERROR_SHUTDOWN_IN_PROGRESS;
2180
2181 if (InfoLevel != SC_ENUM_PROCESS_INFO)
2182 return ERROR_INVALID_LEVEL;
2183
2184 hManager = (PMANAGER_HANDLE)hSCManager;
2185 if (hManager->Handle.Tag != MANAGER_TAG)
2186 {
2187 DPRINT1("Invalid manager handle!\n");
2188 return ERROR_INVALID_HANDLE;
2189 }
2190
2191 /* Check access rights */
2192 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
2193 SC_MANAGER_ENUMERATE_SERVICE))
2194 {
2195 DPRINT1("Insufficient access rights! 0x%lx\n",
2196 hManager->Handle.DesiredAccess);
2197 return ERROR_ACCESS_DENIED;
2198 }
2199
2200 *pcbBytesNeeded = 0;
2201 *lpServicesReturned = 0;
2202
2203 dwLastResumeCount = *lpResumeHandle;
2204
2205 /* Lock the service list shared */
2206
2207 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
2208 if (lpService == NULL)
2209 {
2210 dwError = ERROR_SUCCESS;
2211 goto Done;
2212 }
2213
2214 dwRequiredSize = 0;
2215 dwServiceCount = 0;
2216
2217 for (ServiceEntry = &lpService->ServiceListEntry;
2218 ServiceEntry != &ServiceListHead;
2219 ServiceEntry = ServiceEntry->Flink)
2220 {
2221 CurrentService = CONTAINING_RECORD(ServiceEntry,
2222 SERVICE,
2223 ServiceListEntry);
2224
2225 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2226 continue;
2227
2228 dwState = SERVICE_ACTIVE;
2229 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2230 dwState = SERVICE_INACTIVE;
2231
2232 if ((dwState & dwServiceState) == 0)
2233 continue;
2234
2235 if (pszGroupName)
2236 {
2237 if (_wcsicmp(pszGroupName, CurrentService->lpServiceGroup))
2238 continue;
2239 }
2240
2241 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2242 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2243 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
2244
2245 if (dwRequiredSize + dwSize <= dwBufSize)
2246 {
2247 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
2248 dwRequiredSize += dwSize;
2249 dwServiceCount++;
2250 dwLastResumeCount = CurrentService->dwResumeCount;
2251 }
2252 else
2253 {
2254 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
2255 break;
2256 }
2257
2258 }
2259
2260 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
2261 DPRINT("dwServiceCount: %lu\n", dwServiceCount);
2262
2263 for (;
2264 ServiceEntry != &ServiceListHead;
2265 ServiceEntry = ServiceEntry->Flink)
2266 {
2267 CurrentService = CONTAINING_RECORD(ServiceEntry,
2268 SERVICE,
2269 ServiceListEntry);
2270
2271 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2272 continue;
2273
2274 dwState = SERVICE_ACTIVE;
2275 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2276 dwState = SERVICE_INACTIVE;
2277
2278 if ((dwState & dwServiceState) == 0)
2279 continue;
2280
2281 if (pszGroupName)
2282 {
2283 if (_wcsicmp(pszGroupName, CurrentService->lpServiceGroup))
2284 continue;
2285 }
2286
2287 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2288 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2289 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
2290
2291 dwError = ERROR_MORE_DATA;
2292 }
2293
2294 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
2295
2296 *lpResumeHandle = dwLastResumeCount;
2297 *lpServicesReturned = dwServiceCount;
2298 *pcbBytesNeeded = dwRequiredSize;
2299
2300 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices;
2301 lpStringPtr = (LPWSTR)((ULONG_PTR)lpServices +
2302 dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
2303
2304 dwRequiredSize = 0;
2305 for (ServiceEntry = &lpService->ServiceListEntry;
2306 ServiceEntry != &ServiceListHead;
2307 ServiceEntry = ServiceEntry->Flink)
2308 {
2309 CurrentService = CONTAINING_RECORD(ServiceEntry,
2310 SERVICE,
2311 ServiceListEntry);
2312
2313 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2314 continue;
2315
2316 dwState = SERVICE_ACTIVE;
2317 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2318 dwState = SERVICE_INACTIVE;
2319
2320 if ((dwState & dwServiceState) == 0)
2321 continue;
2322
2323 if (pszGroupName)
2324 {
2325 if (_wcsicmp(pszGroupName, CurrentService->lpServiceGroup))
2326 continue;
2327 }
2328
2329 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2330 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2331 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
2332
2333 if (dwRequiredSize + dwSize <= dwBufSize)
2334 {
2335 /* Copy the service name */
2336 wcscpy(lpStringPtr,
2337 CurrentService->lpServiceName);
2338 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
2339 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
2340
2341 /* Copy the display name */
2342 wcscpy(lpStringPtr,
2343 CurrentService->lpDisplayName);
2344 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
2345 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
2346
2347 /* Copy the status information */
2348 memcpy(&lpStatusPtr->ServiceStatusProcess,
2349 &CurrentService->Status,
2350 sizeof(SERVICE_STATUS));
2351 lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->ProcessId; /* FIXME */
2352 lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
2353
2354 lpStatusPtr++;
2355 dwRequiredSize += dwSize;
2356 }
2357 else
2358 {
2359 break;
2360 }
2361
2362 }
2363
2364 Done:;
2365 /* Unlock the service list */
2366
2367 DPRINT("ScmrEnumServicesStatusExW() done (Error %lu)\n", dwError);
2368
2369 return dwError;
2370 }
2371
2372
2373 /* Function 43 */
2374 /* ScmrSendTSMessage */
2375
2376
2377 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
2378 {
2379 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
2380 }
2381
2382
2383 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
2384 {
2385 HeapFree(GetProcessHeap(), 0, ptr);
2386 }
2387
2388 /* EOF */