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