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