396af8d440ea97cc7f1808f6a3ad737d8c84f9d4
[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->lpGroup->lpGroupName,
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->lpGroup->lpGroupName,
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 *pcbBytesNeeded = 0;
1256 *lpServicesReturned = 0;
1257
1258 DPRINT1("ScmrEnumDependentServicesW() done (Error %lu)\n", dwError);
1259
1260 return dwError;
1261 }
1262
1263
1264 /* Function 14 */
1265 unsigned long
1266 ScmrEnumServicesStatusW(handle_t BindingHandle,
1267 unsigned int hSCManager,
1268 unsigned long dwServiceType,
1269 unsigned long dwServiceState,
1270 unsigned char *lpServices,
1271 unsigned long dwBufSize,
1272 unsigned long *pcbBytesNeeded,
1273 unsigned long *lpServicesReturned,
1274 unsigned long *lpResumeHandle)
1275 {
1276 PMANAGER_HANDLE hManager;
1277 PSERVICE lpService;
1278 DWORD dwError = ERROR_SUCCESS;
1279 PLIST_ENTRY ServiceEntry;
1280 PSERVICE CurrentService;
1281 DWORD dwState;
1282 DWORD dwRequiredSize;
1283 DWORD dwServiceCount;
1284 DWORD dwSize;
1285 DWORD dwLastResumeCount;
1286 LPENUM_SERVICE_STATUSW lpStatusPtr;
1287 LPWSTR lpStringPtr;
1288
1289 DPRINT("ScmrEnumServicesStatusW() called\n");
1290
1291 if (ScmShutdown)
1292 return ERROR_SHUTDOWN_IN_PROGRESS;
1293
1294 hManager = (PMANAGER_HANDLE)hSCManager;
1295 if (hManager->Handle.Tag != MANAGER_TAG)
1296 {
1297 DPRINT1("Invalid manager handle!\n");
1298 return ERROR_INVALID_HANDLE;
1299 }
1300
1301 /* Check access rights */
1302 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
1303 SC_MANAGER_ENUMERATE_SERVICE))
1304 {
1305 DPRINT1("Insufficient access rights! 0x%lx\n",
1306 hManager->Handle.DesiredAccess);
1307 return ERROR_ACCESS_DENIED;
1308 }
1309
1310 *pcbBytesNeeded = 0;
1311 *lpServicesReturned = 0;
1312
1313 dwLastResumeCount = *lpResumeHandle;
1314
1315 /* Lock the service list shared */
1316
1317 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
1318 if (lpService == NULL)
1319 {
1320 dwError = ERROR_SUCCESS;
1321 goto Done;
1322 }
1323
1324 dwRequiredSize = 0;
1325 dwServiceCount = 0;
1326
1327 for (ServiceEntry = &lpService->ServiceListEntry;
1328 ServiceEntry != &ServiceListHead;
1329 ServiceEntry = ServiceEntry->Flink)
1330 {
1331 CurrentService = CONTAINING_RECORD(ServiceEntry,
1332 SERVICE,
1333 ServiceListEntry);
1334
1335 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
1336 continue;
1337
1338 dwState = SERVICE_ACTIVE;
1339 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
1340 dwState = SERVICE_INACTIVE;
1341
1342 if ((dwState & dwServiceState) == 0)
1343 continue;
1344
1345 dwSize = sizeof(ENUM_SERVICE_STATUSW) +
1346 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
1347 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
1348
1349 if (dwRequiredSize + dwSize <= dwBufSize)
1350 {
1351 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
1352 dwRequiredSize += dwSize;
1353 dwServiceCount++;
1354 dwLastResumeCount = CurrentService->dwResumeCount;
1355 }
1356 else
1357 {
1358 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
1359 break;
1360 }
1361
1362 }
1363
1364 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
1365 DPRINT("dwServiceCount: %lu\n", dwServiceCount);
1366
1367 for (;
1368 ServiceEntry != &ServiceListHead;
1369 ServiceEntry = ServiceEntry->Flink)
1370 {
1371 CurrentService = CONTAINING_RECORD(ServiceEntry,
1372 SERVICE,
1373 ServiceListEntry);
1374
1375 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
1376 continue;
1377
1378 dwState = SERVICE_ACTIVE;
1379 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
1380 dwState = SERVICE_INACTIVE;
1381
1382 if ((dwState & dwServiceState) == 0)
1383 continue;
1384
1385 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUSW) +
1386 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
1387 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
1388
1389 dwError = ERROR_MORE_DATA;
1390 }
1391
1392 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
1393
1394 *lpResumeHandle = dwLastResumeCount;
1395 *lpServicesReturned = dwServiceCount;
1396 *pcbBytesNeeded = dwRequiredSize;
1397
1398 lpStatusPtr = (LPENUM_SERVICE_STATUSW)lpServices;
1399 lpStringPtr = (LPWSTR)((ULONG_PTR)lpServices +
1400 dwServiceCount * sizeof(ENUM_SERVICE_STATUSW));
1401
1402 dwRequiredSize = 0;
1403 for (ServiceEntry = &lpService->ServiceListEntry;
1404 ServiceEntry != &ServiceListHead;
1405 ServiceEntry = ServiceEntry->Flink)
1406 {
1407 CurrentService = CONTAINING_RECORD(ServiceEntry,
1408 SERVICE,
1409 ServiceListEntry);
1410
1411 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
1412 continue;
1413
1414 dwState = SERVICE_ACTIVE;
1415 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
1416 dwState = SERVICE_INACTIVE;
1417
1418 if ((dwState & dwServiceState) == 0)
1419 continue;
1420
1421 dwSize = sizeof(ENUM_SERVICE_STATUSW) +
1422 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
1423 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
1424
1425 if (dwRequiredSize + dwSize <= dwBufSize)
1426 {
1427 /* Copy the service name */
1428 wcscpy(lpStringPtr,
1429 CurrentService->lpServiceName);
1430 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
1431 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
1432
1433 /* Copy the display name */
1434 wcscpy(lpStringPtr,
1435 CurrentService->lpDisplayName);
1436 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
1437 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
1438
1439 /* Copy the status information */
1440 memcpy(&lpStatusPtr->ServiceStatus,
1441 &CurrentService->Status,
1442 sizeof(SERVICE_STATUS));
1443
1444 lpStatusPtr++;
1445 dwRequiredSize += dwSize;
1446 }
1447 else
1448 {
1449 break;
1450 }
1451
1452 }
1453
1454 Done:;
1455 /* Unlock the service list */
1456
1457 DPRINT("ScmrEnumServicesStatusW() done (Error %lu)\n", dwError);
1458
1459 return dwError;
1460 }
1461
1462
1463 /* Function 15 */
1464 unsigned long
1465 ScmrOpenSCManagerW(handle_t BindingHandle,
1466 wchar_t *lpMachineName,
1467 wchar_t *lpDatabaseName,
1468 unsigned long dwDesiredAccess,
1469 unsigned int *hScm)
1470 {
1471 DWORD dwError;
1472 SC_HANDLE hHandle;
1473
1474 DPRINT("ScmrOpenSCManagerW() called\n");
1475 DPRINT("lpMachineName = %p\n", lpMachineName);
1476 DPRINT("lpMachineName: %S\n", lpMachineName);
1477 DPRINT("lpDataBaseName = %p\n", lpDatabaseName);
1478 DPRINT("lpDataBaseName: %S\n", lpDatabaseName);
1479 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
1480
1481 if (ScmShutdown)
1482 return ERROR_SHUTDOWN_IN_PROGRESS;
1483
1484 dwError = ScmCreateManagerHandle(lpDatabaseName,
1485 &hHandle);
1486 if (dwError != ERROR_SUCCESS)
1487 {
1488 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError);
1489 return dwError;
1490 }
1491
1492 /* Check the desired access */
1493 dwError = ScmCheckAccess(hHandle,
1494 dwDesiredAccess | SC_MANAGER_CONNECT);
1495 if (dwError != ERROR_SUCCESS)
1496 {
1497 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
1498 HeapFree(GetProcessHeap(), 0, hHandle);
1499 return dwError;
1500 }
1501
1502 *hScm = (unsigned int)hHandle;
1503 DPRINT("*hScm = %x\n", *hScm);
1504
1505 DPRINT("ScmrOpenSCManagerW() done\n");
1506
1507 return ERROR_SUCCESS;
1508 }
1509
1510
1511 /* Function 16 */
1512 unsigned int
1513 ScmrOpenServiceW(handle_t BindingHandle,
1514 unsigned int hSCManager,
1515 wchar_t *lpServiceName,
1516 unsigned long dwDesiredAccess,
1517 unsigned int *hService)
1518 {
1519 PSERVICE lpService;
1520 PMANAGER_HANDLE hManager;
1521 SC_HANDLE hHandle;
1522 DWORD dwError;
1523
1524 DPRINT("ScmrOpenServiceW() called\n");
1525 DPRINT("hSCManager = %x\n", hSCManager);
1526 DPRINT("lpServiceName = %p\n", lpServiceName);
1527 DPRINT("lpServiceName: %S\n", lpServiceName);
1528 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess);
1529
1530 if (ScmShutdown)
1531 return ERROR_SHUTDOWN_IN_PROGRESS;
1532
1533 hManager = (PMANAGER_HANDLE)hSCManager;
1534 if (hManager->Handle.Tag != MANAGER_TAG)
1535 {
1536 DPRINT1("Invalid manager handle!\n");
1537 return ERROR_INVALID_HANDLE;
1538 }
1539
1540 /* FIXME: Lock the service list */
1541
1542 /* Get service database entry */
1543 lpService = ScmGetServiceEntryByName(lpServiceName);
1544 if (lpService == NULL)
1545 {
1546 DPRINT("Could not find a service!\n");
1547 return ERROR_SERVICE_DOES_NOT_EXIST;
1548 }
1549
1550 /* Create a service handle */
1551 dwError = ScmCreateServiceHandle(lpService,
1552 &hHandle);
1553 if (dwError != ERROR_SUCCESS)
1554 {
1555 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError);
1556 return dwError;
1557 }
1558
1559 /* Check the desired access */
1560 dwError = ScmCheckAccess(hHandle,
1561 dwDesiredAccess);
1562 if (dwError != ERROR_SUCCESS)
1563 {
1564 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError);
1565 HeapFree(GetProcessHeap(), 0, hHandle);
1566 return dwError;
1567 }
1568
1569 *hService = (unsigned int)hHandle;
1570 DPRINT("*hService = %x\n", *hService);
1571
1572 DPRINT("ScmrOpenServiceW() done\n");
1573
1574 return ERROR_SUCCESS;
1575 }
1576
1577
1578 /* Function 17 */
1579 unsigned long
1580 ScmrQueryServiceConfigW(handle_t BindingHandle,
1581 unsigned int hService,
1582 unsigned char *lpServiceConfig,
1583 unsigned long cbBufSize,
1584 unsigned long *pcbBytesNeeded)
1585 {
1586 DWORD dwError = ERROR_SUCCESS;
1587 PSERVICE_HANDLE hSvc;
1588 PSERVICE lpService = NULL;
1589 HKEY hServiceKey = NULL;
1590 LPWSTR lpImagePath = NULL;
1591 DWORD dwRequiredSize;
1592 LPQUERY_SERVICE_CONFIGW lpConfig;
1593 LPWSTR lpStr;
1594
1595 DPRINT1("ScmrQueryServiceConfigW() called\n");
1596
1597 if (ScmShutdown)
1598 return ERROR_SHUTDOWN_IN_PROGRESS;
1599
1600 hSvc = (PSERVICE_HANDLE)hService;
1601 if (hSvc->Handle.Tag != SERVICE_TAG)
1602 {
1603 DPRINT1("Invalid handle tag!\n");
1604 return ERROR_INVALID_HANDLE;
1605 }
1606
1607 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
1608 SERVICE_QUERY_CONFIG))
1609 {
1610 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1611 return ERROR_ACCESS_DENIED;
1612 }
1613
1614 lpService = hSvc->ServiceEntry;
1615 if (lpService == NULL)
1616 {
1617 DPRINT1("lpService == NULL!\n");
1618 return ERROR_INVALID_HANDLE;
1619 }
1620
1621 /* FIXME: Lock the service database shared */
1622
1623 dwError = ScmOpenServiceKey(lpService->lpServiceName,
1624 KEY_READ,
1625 &hServiceKey);
1626 if (dwError != ERROR_SUCCESS)
1627 goto Done;
1628
1629 dwError = ScmReadString(hServiceKey,
1630 L"ImagePath",
1631 &lpImagePath);
1632 if (dwError != ERROR_SUCCESS)
1633 goto Done;
1634
1635 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
1636
1637 if (lpImagePath != NULL)
1638 dwRequiredSize += ((wcslen(lpImagePath) + 1) * sizeof(WCHAR));
1639
1640 if (lpService->lpGroup != NULL)
1641 dwRequiredSize += ((wcslen(lpService->lpGroup->lpGroupName) + 1) * sizeof(WCHAR));
1642
1643 /* FIXME: Add Dependencies length*/
1644
1645 /* FIXME: Add ServiceStartName length*/
1646
1647 if (lpService->lpDisplayName != NULL)
1648 dwRequiredSize += ((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR));
1649
1650 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
1651 {
1652 dwError = ERROR_INSUFFICIENT_BUFFER;
1653 }
1654 else
1655 {
1656 lpConfig = (LPQUERY_SERVICE_CONFIGW)lpServiceConfig;
1657 lpConfig->dwServiceType = lpService->Status.dwServiceType;
1658 lpConfig->dwStartType = lpService->dwStartType;
1659 lpConfig->dwErrorControl = lpService->dwErrorControl;
1660 lpConfig->dwTagId = lpService->dwTag;
1661
1662 lpStr = (LPWSTR)(lpConfig + 1);
1663
1664 if (lpImagePath != NULL)
1665 {
1666 wcscpy(lpStr, lpImagePath);
1667 lpConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1668 lpStr += (wcslen(lpImagePath) + 1);
1669 }
1670 else
1671 {
1672 lpConfig->lpBinaryPathName = NULL;
1673 }
1674
1675 if (lpService->lpGroup != NULL)
1676 {
1677 wcscpy(lpStr, lpService->lpGroup->lpGroupName);
1678 lpConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1679 lpStr += (wcslen(lpService->lpGroup->lpGroupName) + 1);
1680 }
1681 else
1682 {
1683 lpConfig->lpLoadOrderGroup = NULL;
1684 }
1685
1686 /* FIXME: Append Dependencies */
1687 lpConfig->lpDependencies = NULL;
1688
1689 /* FIXME: Append ServiceStartName */
1690 lpConfig->lpServiceStartName = NULL;
1691
1692 if (lpService->lpDisplayName != NULL)
1693 {
1694 wcscpy(lpStr, lpService->lpDisplayName);
1695 lpConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1696 }
1697 else
1698 {
1699 lpConfig->lpDisplayName = NULL;
1700 }
1701 }
1702
1703 if (pcbBytesNeeded != NULL)
1704 *pcbBytesNeeded = dwRequiredSize;
1705
1706 Done:;
1707 if (lpImagePath != NULL)
1708 HeapFree(GetProcessHeap(), 0, lpImagePath);
1709
1710 if (hServiceKey != NULL)
1711 RegCloseKey(hServiceKey);
1712
1713 /* FIXME: Unlock the service database */
1714
1715 DPRINT1("ScmrQueryServiceConfigW() done\n");
1716
1717 return dwError;
1718 }
1719
1720
1721 /* Function 18 */
1722 unsigned long
1723 ScmrQueryServiceLockStatusW(handle_t BindingHandle,
1724 unsigned int hSCManager,
1725 unsigned char *lpLockStatus, /* [out, unique, size_is(cbBufSize)] */
1726 unsigned long cbBufSize, /* [in] */
1727 unsigned long *pcbBytesNeeded) /* [out] */
1728 {
1729 DPRINT1("ScmrQueryServiceLockStatusW() called\n");
1730 return ERROR_CALL_NOT_IMPLEMENTED;
1731 }
1732
1733
1734 /* Function 19 */
1735 unsigned long
1736 ScmrStartServiceW(handle_t BindingHandle,
1737 unsigned int hService,
1738 unsigned long dwNumServiceArgs,
1739 unsigned char *lpServiceArgBuffer,
1740 unsigned long cbBufSize)
1741 {
1742 DWORD dwError = ERROR_SUCCESS;
1743 PSERVICE_HANDLE hSvc;
1744 PSERVICE lpService = NULL;
1745
1746 DPRINT1("ScmrStartServiceW() called\n");
1747
1748 if (ScmShutdown)
1749 return ERROR_SHUTDOWN_IN_PROGRESS;
1750
1751 hSvc = (PSERVICE_HANDLE)hService;
1752 if (hSvc->Handle.Tag != SERVICE_TAG)
1753 {
1754 DPRINT1("Invalid handle tag!\n");
1755 return ERROR_INVALID_HANDLE;
1756 }
1757
1758 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
1759 SERVICE_START))
1760 {
1761 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1762 return ERROR_ACCESS_DENIED;
1763 }
1764
1765 lpService = hSvc->ServiceEntry;
1766 if (lpService == NULL)
1767 {
1768 DPRINT1("lpService == NULL!\n");
1769 return ERROR_INVALID_HANDLE;
1770 }
1771
1772 if (lpService->dwStartType == SERVICE_DISABLED)
1773 return ERROR_SERVICE_DISABLED;
1774
1775 if (lpService->bDeleted)
1776 return ERROR_SERVICE_MARKED_FOR_DELETE;
1777
1778 /* FIXME: Start the service */
1779
1780 return dwError;
1781 }
1782
1783
1784 /* Function 20 */
1785 unsigned long
1786 ScmrGetServiceDisplayNameW(handle_t BindingHandle,
1787 unsigned int hSCManager,
1788 wchar_t *lpServiceName,
1789 wchar_t *lpDisplayName, /* [out, unique] */
1790 unsigned long *lpcchBuffer)
1791 {
1792 // PMANAGER_HANDLE hManager;
1793 PSERVICE lpService;
1794 DWORD dwLength;
1795 DWORD dwError;
1796
1797 DPRINT("ScmrGetServiceDisplayNameW() called\n");
1798 DPRINT("hSCManager = %x\n", hSCManager);
1799 DPRINT("lpServiceName: %S\n", lpServiceName);
1800 DPRINT("lpDisplayName: %p\n", lpDisplayName);
1801 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
1802
1803 // hManager = (PMANAGER_HANDLE)hSCManager;
1804 // if (hManager->Handle.Tag != MANAGER_TAG)
1805 // {
1806 // DPRINT1("Invalid manager handle!\n");
1807 // return ERROR_INVALID_HANDLE;
1808 // }
1809
1810 /* Get service database entry */
1811 lpService = ScmGetServiceEntryByName(lpServiceName);
1812 if (lpService == NULL)
1813 {
1814 DPRINT1("Could not find a service!\n");
1815 return ERROR_SERVICE_DOES_NOT_EXIST;
1816 }
1817
1818 dwLength = wcslen(lpService->lpDisplayName) + 1;
1819
1820 if (lpDisplayName != NULL &&
1821 *lpcchBuffer >= dwLength)
1822 {
1823 wcscpy(lpDisplayName, lpService->lpDisplayName);
1824 }
1825
1826 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
1827
1828 *lpcchBuffer = dwLength;
1829
1830 return dwError;
1831 }
1832
1833
1834 /* Function 21 */
1835 unsigned long
1836 ScmrGetServiceKeyNameW(handle_t BindingHandle,
1837 unsigned int hSCManager,
1838 wchar_t *lpDisplayName,
1839 wchar_t *lpServiceName, /* [out, unique] */
1840 unsigned long *lpcchBuffer)
1841 {
1842 // PMANAGER_HANDLE hManager;
1843 PSERVICE lpService;
1844 DWORD dwLength;
1845 DWORD dwError;
1846
1847 DPRINT("ScmrGetServiceKeyNameW() called\n");
1848 DPRINT("hSCManager = %x\n", hSCManager);
1849 DPRINT("lpDisplayName: %S\n", lpDisplayName);
1850 DPRINT("lpServiceName: %p\n", lpServiceName);
1851 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
1852
1853 // hManager = (PMANAGER_HANDLE)hSCManager;
1854 // if (hManager->Handle.Tag != MANAGER_TAG)
1855 // {
1856 // DPRINT1("Invalid manager handle!\n");
1857 // return ERROR_INVALID_HANDLE;
1858 // }
1859
1860 /* Get service database entry */
1861 lpService = ScmGetServiceEntryByDisplayName(lpDisplayName);
1862 if (lpService == NULL)
1863 {
1864 DPRINT1("Could not find a service!\n");
1865 return ERROR_SERVICE_DOES_NOT_EXIST;
1866 }
1867
1868 dwLength = wcslen(lpService->lpServiceName) + 1;
1869
1870 if (lpServiceName != NULL &&
1871 *lpcchBuffer >= dwLength)
1872 {
1873 wcscpy(lpServiceName, lpService->lpServiceName);
1874 }
1875
1876 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
1877
1878 *lpcchBuffer = dwLength;
1879
1880 return dwError;
1881 }
1882
1883
1884 /* Function 22 */
1885 unsigned long
1886 ScmrSetServiceBitsA(handle_t BindingHandle,
1887 unsigned long hServiceStatus,
1888 unsigned long dwServiceBits,
1889 unsigned long bSetBitsOn,
1890 unsigned long bUpdateImmediately,
1891 char *lpString)
1892 {
1893 DPRINT1("ScmrSetServiceBitsA() is unimplemented\n");
1894 return ERROR_CALL_NOT_IMPLEMENTED;
1895 }
1896
1897
1898 /* Function 23 */
1899 unsigned long
1900 ScmrChangeServiceConfigA(handle_t BiningHandle,
1901 unsigned int hService,
1902 unsigned long dwServiceType,
1903 unsigned long dwStartType,
1904 unsigned long dwErrorControl,
1905 char *lpBinaryPathName,
1906 char *lpLoadOrderGroup,
1907 unsigned long *lpdwTagId,
1908 char *lpDependencies,
1909 unsigned long dwDependenciesLength,
1910 char *lpServiceStartName,
1911 char *lpPassword,
1912 unsigned long dwPasswordLength,
1913 char *lpDisplayName)
1914 {
1915 DPRINT1("ScmrChangeServiceConfigA() is unimplemented\n");
1916 return ERROR_CALL_NOT_IMPLEMENTED;
1917 }
1918
1919
1920 /* Function 24 */
1921 unsigned long
1922 ScmrCreateServiceA(handle_t BindingHandle,
1923 unsigned int hSCManager,
1924 char *lpServiceName,
1925 char *lpDisplayName,
1926 unsigned long dwDesiredAccess,
1927 unsigned long dwServiceType,
1928 unsigned long dwStartType,
1929 unsigned long dwErrorControl,
1930 char *lpBinaryPathName,
1931 char *lpLoadOrderGroup,
1932 unsigned long *lpdwTagId, /* in, out */
1933 char *lpDependencies,
1934 unsigned long dwDependenciesLength,
1935 char *lpServiceStartName,
1936 char *lpPassword,
1937 unsigned long dwPasswordLength,
1938 unsigned int *hService) /* out */
1939 {
1940 DPRINT1("ScmrCreateServiceA() is unimplemented\n");
1941 return ERROR_CALL_NOT_IMPLEMENTED;
1942 }
1943
1944
1945 /* Function 25 */
1946 unsigned long
1947 ScmrEnumDependentServicesA(handle_t BindingHandle,
1948 unsigned int hService,
1949 unsigned long dwServiceState,
1950 unsigned char *lpServices,
1951 unsigned long cbBufSize,
1952 unsigned long *pcbBytesNeeded,
1953 unsigned long *lpServicesReturned)
1954 {
1955 DPRINT1("ScmrEnumDependentServicesA() is unimplemented\n");
1956 *pcbBytesNeeded = 0;
1957 *lpServicesReturned = 0;
1958 return ERROR_CALL_NOT_IMPLEMENTED;
1959 }
1960
1961
1962 /* Function 26 */
1963 unsigned long
1964 ScmrEnumServicesStatusA(handle_t BindingHandle,
1965 unsigned int hSCManager,
1966 unsigned long dwServiceType,
1967 unsigned long dwServiceState,
1968 unsigned char *lpServices,
1969 unsigned long dwBufSize,
1970 unsigned long *pcbBytesNeeded,
1971 unsigned long *lpServicesReturned,
1972 unsigned long *lpResumeHandle)
1973 {
1974 DPRINT1("ScmrEnumServicesAtatusA() is unimplemented\n");
1975 return ERROR_CALL_NOT_IMPLEMENTED;
1976 }
1977
1978
1979 /* Function 27 */
1980 unsigned long
1981 ScmrOpenSCManagerA(handle_t BindingHandle,
1982 char *lpMachineName,
1983 char *lpDatabaseName,
1984 unsigned long dwDesiredAccess,
1985 unsigned int *hScm)
1986 {
1987 UNICODE_STRING MachineName;
1988 UNICODE_STRING DatabaseName;
1989 DWORD dwError;
1990
1991 DPRINT("ScmrOpenSCManagerA() called\n");
1992
1993 if (lpMachineName)
1994 RtlCreateUnicodeStringFromAsciiz(&MachineName,
1995 lpMachineName);
1996
1997 if (lpDatabaseName)
1998 RtlCreateUnicodeStringFromAsciiz(&DatabaseName,
1999 lpDatabaseName);
2000
2001 dwError = ScmrOpenSCManagerW(BindingHandle,
2002 lpMachineName ? MachineName.Buffer : NULL,
2003 lpDatabaseName ? DatabaseName.Buffer : NULL,
2004 dwDesiredAccess,
2005 hScm);
2006
2007 if (lpMachineName)
2008 RtlFreeUnicodeString(&MachineName);
2009
2010 if (lpDatabaseName)
2011 RtlFreeUnicodeString(&DatabaseName);
2012
2013 return dwError;
2014 }
2015
2016
2017 /* Function 28 */
2018 unsigned int
2019 ScmrOpenServiceA(handle_t BindingHandle,
2020 unsigned int hSCManager,
2021 char *lpServiceName,
2022 unsigned long dwDesiredAccess,
2023 unsigned int *hService)
2024 {
2025 UNICODE_STRING ServiceName;
2026 DWORD dwError;
2027
2028 DPRINT("ScmrOpenServiceA() called\n");
2029
2030 RtlCreateUnicodeStringFromAsciiz(&ServiceName,
2031 lpServiceName);
2032
2033 dwError = ScmrOpenServiceW(BindingHandle,
2034 hSCManager,
2035 ServiceName.Buffer,
2036 dwDesiredAccess,
2037 hService);
2038
2039 RtlFreeUnicodeString(&ServiceName);
2040
2041 return dwError;
2042 }
2043
2044
2045 /* Function 29 */
2046 unsigned long
2047 ScmrQueryServiceConfigA(handle_t BindingHandle,
2048 unsigned int hService,
2049 unsigned char *lpServiceConfig,
2050 unsigned long cbBufSize,
2051 unsigned long *pcbBytesNeeded)
2052 {
2053 DPRINT1("ScmrQueryServiceConfigA() is unimplemented\n");
2054 return ERROR_CALL_NOT_IMPLEMENTED;
2055 }
2056
2057
2058 /* Function 30 */
2059 unsigned long
2060 ScmrQueryServiceLockStatusA(handle_t BindingHandle,
2061 unsigned int hSCManager,
2062 unsigned char *lpLockStatus, /* [out, unique, size_is(cbBufSize)] */
2063 unsigned long cbBufSize, /* [in] */
2064 unsigned long *pcbBytesNeeded) /* [out] */
2065 {
2066 DPRINT1("ScmrQueryServiceLockStatusA() called\n");
2067 return ERROR_CALL_NOT_IMPLEMENTED;
2068 }
2069
2070
2071 /* Function 31 */
2072 unsigned long
2073 ScmrStartServiceA(handle_t BindingHandle,
2074 unsigned int hService,
2075 unsigned long dwNumServiceArgs,
2076 unsigned char *lpServiceArgBuffer,
2077 unsigned long cbBufSize)
2078 {
2079 DPRINT1("ScmrStartServiceA() called\n");
2080 return ERROR_SUCCESS;
2081 // return ERROR_CALL_NOT_IMPLEMENTED;
2082 }
2083
2084
2085 /* Function 32 */
2086 unsigned long
2087 ScmrGetServiceDisplayNameA(handle_t BindingHandle,
2088 unsigned int hSCManager,
2089 char *lpServiceName,
2090 char *lpDisplayName, /* [out, unique] */
2091 unsigned long *lpcchBuffer)
2092 {
2093 DPRINT1("ScmrGetServiceDisplayNameA() is unimplemented\n");
2094 return ERROR_CALL_NOT_IMPLEMENTED;
2095 }
2096
2097
2098 /* Function 33 */
2099 unsigned long
2100 ScmrGetServiceKeyNameA(handle_t BindingHandle,
2101 unsigned int hSCManager,
2102 char *lpDisplayName,
2103 char *lpServiceName, /* [out, unique] */
2104 unsigned long *lpcchBuffer)
2105 {
2106 DPRINT1("ScmrGetServiceKeyNameA() is unimplemented\n");
2107 return ERROR_CALL_NOT_IMPLEMENTED;
2108 }
2109
2110
2111 /* Function 34 */
2112 unsigned long
2113 ScmrGetCurrentGroupStateW(handle_t BindingHandle)
2114 {
2115 DPRINT1("ScmrGetCurrentGroupStateW() is unimplemented\n");
2116 return ERROR_CALL_NOT_IMPLEMENTED;
2117 }
2118
2119
2120 /* Function 35 */
2121 unsigned long
2122 ScmrEnumServiceGroupW(handle_t BindingHandle)
2123 {
2124 DPRINT1("ScmrEnumServiceGroupW() is unimplemented\n");
2125 return ERROR_CALL_NOT_IMPLEMENTED;
2126 }
2127
2128
2129 /* Function 36 */
2130 unsigned long
2131 ScmrChangeServiceConfig2A(handle_t BindingHandle,
2132 unsigned int hService,
2133 unsigned long dwInfoLevel,
2134 unsigned char *lpInfo,
2135 unsigned long dwInfoSize)
2136 {
2137 DPRINT1("ScmrChangeServiceConfig2A() is unimplemented\n");
2138 return ERROR_CALL_NOT_IMPLEMENTED;
2139 }
2140
2141
2142 /* Function 37 */
2143 unsigned long
2144 ScmrChangeServiceConfig2W(handle_t BindingHandle,
2145 unsigned int hService,
2146 unsigned long dwInfoLevel,
2147 unsigned char *lpInfo,
2148 unsigned long dwInfoSize)
2149 {
2150 DPRINT1("ScmrChangeServiceConfig2W() is unimplemented\n");
2151 return ERROR_CALL_NOT_IMPLEMENTED;
2152 }
2153
2154
2155 /* Function 38 */
2156 unsigned long
2157 ScmrQueryServiceConfig2A(handle_t BindingHandle,
2158 unsigned int hService,
2159 unsigned long dwInfoLevel,
2160 unsigned char *lpBuffer,
2161 unsigned long cbBufSize,
2162 unsigned long *pcbBytesNeeded)
2163 {
2164 DPRINT1("ScmrQueryServiceConfig2A() is unimplemented\n");
2165 return ERROR_CALL_NOT_IMPLEMENTED;
2166 }
2167
2168
2169 /* Function 39 */
2170 unsigned long
2171 ScmrQueryServiceConfig2W(handle_t BindingHandle,
2172 unsigned int hService,
2173 unsigned long dwInfoLevel,
2174 unsigned char *lpBuffer,
2175 unsigned long cbBufSize,
2176 unsigned long *pcbBytesNeeded)
2177 {
2178 DPRINT1("ScmrQueryServiceConfig2W() is unimplemented\n");
2179 return ERROR_CALL_NOT_IMPLEMENTED;
2180 }
2181
2182
2183 /* Function 40 */
2184 unsigned long
2185 ScmrQueryServiceStatusEx(handle_t BindingHandle,
2186 unsigned int hService,
2187 unsigned long InfoLevel,
2188 unsigned char *lpBuffer, /* out */
2189 unsigned long cbBufSize,
2190 unsigned long *pcbBytesNeeded) /* out */
2191 {
2192 LPSERVICE_STATUS_PROCESS lpStatus;
2193 PSERVICE_HANDLE hSvc;
2194 PSERVICE lpService;
2195
2196 DPRINT("ScmrQueryServiceStatusEx() called\n");
2197
2198 if (ScmShutdown)
2199 return ERROR_SHUTDOWN_IN_PROGRESS;
2200
2201 if (InfoLevel != SC_STATUS_PROCESS_INFO)
2202 return ERROR_INVALID_LEVEL;
2203
2204 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
2205
2206 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
2207 return ERROR_INSUFFICIENT_BUFFER;
2208
2209 hSvc = (PSERVICE_HANDLE)hService;
2210 if (hSvc->Handle.Tag != SERVICE_TAG)
2211 {
2212 DPRINT1("Invalid handle tag!\n");
2213 return ERROR_INVALID_HANDLE;
2214 }
2215
2216 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
2217 SERVICE_QUERY_STATUS))
2218 {
2219 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
2220 return ERROR_ACCESS_DENIED;
2221 }
2222
2223 lpService = hSvc->ServiceEntry;
2224 if (lpService == NULL)
2225 {
2226 DPRINT1("lpService == NULL!\n");
2227 return ERROR_INVALID_HANDLE;
2228 }
2229
2230 lpStatus = (LPSERVICE_STATUS_PROCESS)lpBuffer;
2231
2232 /* Return service status information */
2233 RtlCopyMemory(lpStatus,
2234 &lpService->Status,
2235 sizeof(SERVICE_STATUS));
2236
2237 lpStatus->dwProcessId = lpService->ProcessId; /* FIXME */
2238 lpStatus->dwServiceFlags = 0; /* FIXME */
2239
2240 return ERROR_SUCCESS;
2241 }
2242
2243
2244 /* Function 41 */
2245 unsigned long
2246 ScmrEnumServicesStatusExA(handle_t BindingHandle,
2247 unsigned int hSCManager,
2248 unsigned long InfoLevel,
2249 unsigned long dwServiceType,
2250 unsigned long dwServiceState,
2251 unsigned char *lpServices,
2252 unsigned long dwBufSize,
2253 unsigned long *pcbBytesNeeded,
2254 unsigned long *lpServicesReturned,
2255 unsigned long *lpResumeHandle,
2256 char *pszGroupName)
2257 {
2258 DPRINT1("ScmrEnumServicesStatusExA() is unimplemented\n");
2259 *pcbBytesNeeded = 0;
2260 *lpServicesReturned = 0;
2261 return ERROR_CALL_NOT_IMPLEMENTED;
2262 }
2263
2264
2265 /* Function 42 */
2266 unsigned long
2267 ScmrEnumServicesStatusExW(handle_t BindingHandle,
2268 unsigned int hSCManager,
2269 unsigned long InfoLevel,
2270 unsigned long dwServiceType,
2271 unsigned long dwServiceState,
2272 unsigned char *lpServices,
2273 unsigned long dwBufSize,
2274 unsigned long *pcbBytesNeeded,
2275 unsigned long *lpServicesReturned,
2276 unsigned long *lpResumeHandle,
2277 wchar_t *pszGroupName)
2278 {
2279 PMANAGER_HANDLE hManager;
2280 PSERVICE lpService;
2281 DWORD dwError = ERROR_SUCCESS;
2282 PLIST_ENTRY ServiceEntry;
2283 PSERVICE CurrentService;
2284 DWORD dwState;
2285 DWORD dwRequiredSize;
2286 DWORD dwServiceCount;
2287 DWORD dwSize;
2288 DWORD dwLastResumeCount;
2289 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
2290 LPWSTR lpStringPtr;
2291
2292 DPRINT("ScmrEnumServicesStatusExW() called\n");
2293
2294 if (ScmShutdown)
2295 return ERROR_SHUTDOWN_IN_PROGRESS;
2296
2297 if (InfoLevel != SC_ENUM_PROCESS_INFO)
2298 return ERROR_INVALID_LEVEL;
2299
2300 hManager = (PMANAGER_HANDLE)hSCManager;
2301 if (hManager->Handle.Tag != MANAGER_TAG)
2302 {
2303 DPRINT1("Invalid manager handle!\n");
2304 return ERROR_INVALID_HANDLE;
2305 }
2306
2307 /* Check access rights */
2308 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
2309 SC_MANAGER_ENUMERATE_SERVICE))
2310 {
2311 DPRINT1("Insufficient access rights! 0x%lx\n",
2312 hManager->Handle.DesiredAccess);
2313 return ERROR_ACCESS_DENIED;
2314 }
2315
2316 *pcbBytesNeeded = 0;
2317 *lpServicesReturned = 0;
2318
2319 dwLastResumeCount = *lpResumeHandle;
2320
2321 /* Lock the service list shared */
2322
2323 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
2324 if (lpService == NULL)
2325 {
2326 dwError = ERROR_SUCCESS;
2327 goto Done;
2328 }
2329
2330 dwRequiredSize = 0;
2331 dwServiceCount = 0;
2332
2333 for (ServiceEntry = &lpService->ServiceListEntry;
2334 ServiceEntry != &ServiceListHead;
2335 ServiceEntry = ServiceEntry->Flink)
2336 {
2337 CurrentService = CONTAINING_RECORD(ServiceEntry,
2338 SERVICE,
2339 ServiceListEntry);
2340
2341 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2342 continue;
2343
2344 dwState = SERVICE_ACTIVE;
2345 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2346 dwState = SERVICE_INACTIVE;
2347
2348 if ((dwState & dwServiceState) == 0)
2349 continue;
2350
2351 if (pszGroupName)
2352 {
2353 if (*pszGroupName == 0)
2354 {
2355 if (CurrentService->lpGroup != NULL)
2356 continue;
2357 }
2358 else
2359 {
2360 if ((CurrentService->lpGroup == NULL) ||
2361 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
2362 continue;
2363 }
2364 }
2365
2366 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2367 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2368 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
2369
2370 if (dwRequiredSize + dwSize <= dwBufSize)
2371 {
2372 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
2373 dwRequiredSize += dwSize;
2374 dwServiceCount++;
2375 dwLastResumeCount = CurrentService->dwResumeCount;
2376 }
2377 else
2378 {
2379 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
2380 break;
2381 }
2382
2383 }
2384
2385 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
2386 DPRINT("dwServiceCount: %lu\n", dwServiceCount);
2387
2388 for (;
2389 ServiceEntry != &ServiceListHead;
2390 ServiceEntry = ServiceEntry->Flink)
2391 {
2392 CurrentService = CONTAINING_RECORD(ServiceEntry,
2393 SERVICE,
2394 ServiceListEntry);
2395
2396 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2397 continue;
2398
2399 dwState = SERVICE_ACTIVE;
2400 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2401 dwState = SERVICE_INACTIVE;
2402
2403 if ((dwState & dwServiceState) == 0)
2404 continue;
2405
2406 if (pszGroupName)
2407 {
2408 if (*pszGroupName == 0)
2409 {
2410 if (CurrentService->lpGroup != NULL)
2411 continue;
2412 }
2413 else
2414 {
2415 if ((CurrentService->lpGroup == NULL) ||
2416 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
2417 continue;
2418 }
2419 }
2420
2421 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2422 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2423 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
2424
2425 dwError = ERROR_MORE_DATA;
2426 }
2427
2428 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
2429
2430 *lpResumeHandle = dwLastResumeCount;
2431 *lpServicesReturned = dwServiceCount;
2432 *pcbBytesNeeded = dwRequiredSize;
2433
2434 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices;
2435 lpStringPtr = (LPWSTR)((ULONG_PTR)lpServices +
2436 dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
2437
2438 dwRequiredSize = 0;
2439 for (ServiceEntry = &lpService->ServiceListEntry;
2440 ServiceEntry != &ServiceListHead;
2441 ServiceEntry = ServiceEntry->Flink)
2442 {
2443 CurrentService = CONTAINING_RECORD(ServiceEntry,
2444 SERVICE,
2445 ServiceListEntry);
2446
2447 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2448 continue;
2449
2450 dwState = SERVICE_ACTIVE;
2451 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2452 dwState = SERVICE_INACTIVE;
2453
2454 if ((dwState & dwServiceState) == 0)
2455 continue;
2456
2457 if (pszGroupName)
2458 {
2459 if (*pszGroupName == 0)
2460 {
2461 if (CurrentService->lpGroup != NULL)
2462 continue;
2463 }
2464 else
2465 {
2466 if ((CurrentService->lpGroup == NULL) ||
2467 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
2468 continue;
2469 }
2470 }
2471
2472 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2473 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2474 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
2475
2476 if (dwRequiredSize + dwSize <= dwBufSize)
2477 {
2478 /* Copy the service name */
2479 wcscpy(lpStringPtr,
2480 CurrentService->lpServiceName);
2481 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
2482 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
2483
2484 /* Copy the display name */
2485 wcscpy(lpStringPtr,
2486 CurrentService->lpDisplayName);
2487 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
2488 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
2489
2490 /* Copy the status information */
2491 memcpy(&lpStatusPtr->ServiceStatusProcess,
2492 &CurrentService->Status,
2493 sizeof(SERVICE_STATUS));
2494 lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->ProcessId; /* FIXME */
2495 lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
2496
2497 lpStatusPtr++;
2498 dwRequiredSize += dwSize;
2499 }
2500 else
2501 {
2502 break;
2503 }
2504
2505 }
2506
2507 Done:;
2508 /* Unlock the service list */
2509
2510 DPRINT("ScmrEnumServicesStatusExW() done (Error %lu)\n", dwError);
2511
2512 return dwError;
2513 }
2514
2515
2516 /* Function 43 */
2517 /* ScmrSendTSMessage */
2518
2519
2520 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
2521 {
2522 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
2523 }
2524
2525
2526 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
2527 {
2528 HeapFree(GetProcessHeap(), 0, ptr);
2529 }
2530
2531 /* EOF */