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