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