add the account name to the QueryServiceConfig RPC call
[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 LPWSTR lpServiceStartName = NULL;
1622 DWORD dwRequiredSize;
1623 LPQUERY_SERVICE_CONFIGW lpConfig;
1624 LPWSTR lpStr;
1625
1626 DPRINT("ScmrQueryServiceConfigW() called\n");
1627
1628 if (ScmShutdown)
1629 return ERROR_SHUTDOWN_IN_PROGRESS;
1630
1631 hSvc = (PSERVICE_HANDLE)hService;
1632 if (hSvc->Handle.Tag != SERVICE_TAG)
1633 {
1634 DPRINT1("Invalid handle tag!\n");
1635 return ERROR_INVALID_HANDLE;
1636 }
1637
1638 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
1639 SERVICE_QUERY_CONFIG))
1640 {
1641 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1642 return ERROR_ACCESS_DENIED;
1643 }
1644
1645 lpService = hSvc->ServiceEntry;
1646 if (lpService == NULL)
1647 {
1648 DPRINT1("lpService == NULL!\n");
1649 return ERROR_INVALID_HANDLE;
1650 }
1651
1652 /* FIXME: Lock the service database shared */
1653
1654 dwError = ScmOpenServiceKey(lpService->lpServiceName,
1655 KEY_READ,
1656 &hServiceKey);
1657 if (dwError != ERROR_SUCCESS)
1658 goto Done;
1659
1660 dwError = ScmReadString(hServiceKey,
1661 L"ImagePath",
1662 &lpImagePath);
1663 if (dwError != ERROR_SUCCESS)
1664 goto Done;
1665
1666 ScmReadString(hServiceKey,
1667 L"ObjectName",
1668 &lpServiceStartName);
1669
1670 dwRequiredSize = sizeof(QUERY_SERVICE_CONFIGW);
1671
1672 if (lpImagePath != NULL)
1673 dwRequiredSize += ((wcslen(lpImagePath) + 1) * sizeof(WCHAR));
1674
1675 if (lpService->lpGroup != NULL)
1676 dwRequiredSize += ((wcslen(lpService->lpGroup->lpGroupName) + 1) * sizeof(WCHAR));
1677
1678 /* FIXME: Add Dependencies length*/
1679
1680 if (lpServiceStartName != NULL)
1681 dwRequiredSize += ((wcslen(lpServiceStartName) + 1) * sizeof(WCHAR));
1682
1683 if (lpService->lpDisplayName != NULL)
1684 dwRequiredSize += ((wcslen(lpService->lpDisplayName) + 1) * sizeof(WCHAR));
1685
1686 if (lpServiceConfig == NULL || cbBufSize < dwRequiredSize)
1687 {
1688 dwError = ERROR_INSUFFICIENT_BUFFER;
1689 }
1690 else
1691 {
1692 lpConfig = (LPQUERY_SERVICE_CONFIGW)lpServiceConfig;
1693 lpConfig->dwServiceType = lpService->Status.dwServiceType;
1694 lpConfig->dwStartType = lpService->dwStartType;
1695 lpConfig->dwErrorControl = lpService->dwErrorControl;
1696 lpConfig->dwTagId = lpService->dwTag;
1697
1698 lpStr = (LPWSTR)(lpConfig + 1);
1699
1700 if (lpImagePath != NULL)
1701 {
1702 wcscpy(lpStr, lpImagePath);
1703 lpConfig->lpBinaryPathName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1704 lpStr += (wcslen(lpImagePath) + 1);
1705 }
1706 else
1707 {
1708 lpConfig->lpBinaryPathName = NULL;
1709 }
1710
1711 if (lpService->lpGroup != NULL)
1712 {
1713 wcscpy(lpStr, lpService->lpGroup->lpGroupName);
1714 lpConfig->lpLoadOrderGroup = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1715 lpStr += (wcslen(lpService->lpGroup->lpGroupName) + 1);
1716 }
1717 else
1718 {
1719 lpConfig->lpLoadOrderGroup = NULL;
1720 }
1721
1722 /* FIXME: Append Dependencies */
1723 lpConfig->lpDependencies = NULL;
1724
1725 if (lpServiceStartName != NULL)
1726 {
1727 wcscpy(lpStr, lpServiceStartName);
1728 lpConfig->lpServiceStartName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1729 lpStr += (wcslen(lpServiceStartName) + 1);
1730 }
1731 else
1732 {
1733 lpConfig->lpServiceStartName = NULL;
1734 }
1735
1736 if (lpService->lpDisplayName != NULL)
1737 {
1738 wcscpy(lpStr, lpService->lpDisplayName);
1739 lpConfig->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpConfig);
1740 }
1741 else
1742 {
1743 lpConfig->lpDisplayName = NULL;
1744 }
1745 }
1746
1747 if (pcbBytesNeeded != NULL)
1748 *pcbBytesNeeded = dwRequiredSize;
1749
1750 Done:;
1751 if (lpImagePath != NULL)
1752 HeapFree(GetProcessHeap(), 0, lpImagePath);
1753
1754 if (lpServiceStartName != NULL)
1755 HeapFree(GetProcessHeap(), 0, lpServiceStartName);
1756
1757 if (hServiceKey != NULL)
1758 RegCloseKey(hServiceKey);
1759
1760 /* FIXME: Unlock the service database */
1761
1762 DPRINT("ScmrQueryServiceConfigW() done\n");
1763
1764 return dwError;
1765 }
1766
1767
1768 /* Function 18 */
1769 unsigned long
1770 ScmrQueryServiceLockStatusW(handle_t BindingHandle,
1771 unsigned int hSCManager,
1772 unsigned char *lpLockStatus, /* [out, unique, size_is(cbBufSize)] */
1773 unsigned long cbBufSize, /* [in] */
1774 unsigned long *pcbBytesNeeded) /* [out] */
1775 {
1776 DPRINT1("ScmrQueryServiceLockStatusW() called\n");
1777 return ERROR_CALL_NOT_IMPLEMENTED;
1778 }
1779
1780
1781 /* Function 19 */
1782 unsigned long
1783 ScmrStartServiceW(handle_t BindingHandle,
1784 unsigned int hService,
1785 unsigned long dwNumServiceArgs,
1786 unsigned char *lpServiceArgBuffer,
1787 unsigned long cbBufSize)
1788 {
1789 DWORD dwError = ERROR_SUCCESS;
1790 PSERVICE_HANDLE hSvc;
1791 PSERVICE lpService = NULL;
1792
1793 DPRINT("ScmrStartServiceW() called\n");
1794
1795 if (ScmShutdown)
1796 return ERROR_SHUTDOWN_IN_PROGRESS;
1797
1798 hSvc = (PSERVICE_HANDLE)hService;
1799 if (hSvc->Handle.Tag != SERVICE_TAG)
1800 {
1801 DPRINT1("Invalid handle tag!\n");
1802 return ERROR_INVALID_HANDLE;
1803 }
1804
1805 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
1806 SERVICE_START))
1807 {
1808 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
1809 return ERROR_ACCESS_DENIED;
1810 }
1811
1812 lpService = hSvc->ServiceEntry;
1813 if (lpService == NULL)
1814 {
1815 DPRINT1("lpService == NULL!\n");
1816 return ERROR_INVALID_HANDLE;
1817 }
1818
1819 if (lpService->dwStartType == SERVICE_DISABLED)
1820 return ERROR_SERVICE_DISABLED;
1821
1822 if (lpService->bDeleted)
1823 return ERROR_SERVICE_MARKED_FOR_DELETE;
1824
1825 /* Start the service */
1826 dwError = ScmStartService(lpService, (LPWSTR)lpServiceArgBuffer);
1827
1828 return dwError;
1829 }
1830
1831
1832 /* Function 20 */
1833 unsigned long
1834 ScmrGetServiceDisplayNameW(handle_t BindingHandle,
1835 unsigned int hSCManager,
1836 wchar_t *lpServiceName,
1837 wchar_t *lpDisplayName, /* [out, unique] */
1838 unsigned long *lpcchBuffer)
1839 {
1840 // PMANAGER_HANDLE hManager;
1841 PSERVICE lpService;
1842 DWORD dwLength;
1843 DWORD dwError;
1844
1845 DPRINT("ScmrGetServiceDisplayNameW() called\n");
1846 DPRINT("hSCManager = %x\n", hSCManager);
1847 DPRINT("lpServiceName: %S\n", lpServiceName);
1848 DPRINT("lpDisplayName: %p\n", lpDisplayName);
1849 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
1850
1851 // hManager = (PMANAGER_HANDLE)hSCManager;
1852 // if (hManager->Handle.Tag != MANAGER_TAG)
1853 // {
1854 // DPRINT1("Invalid manager handle!\n");
1855 // return ERROR_INVALID_HANDLE;
1856 // }
1857
1858 /* Get service database entry */
1859 lpService = ScmGetServiceEntryByName(lpServiceName);
1860 if (lpService == NULL)
1861 {
1862 DPRINT1("Could not find a service!\n");
1863 return ERROR_SERVICE_DOES_NOT_EXIST;
1864 }
1865
1866 dwLength = wcslen(lpService->lpDisplayName) + 1;
1867
1868 if (lpDisplayName != NULL &&
1869 *lpcchBuffer >= dwLength)
1870 {
1871 wcscpy(lpDisplayName, lpService->lpDisplayName);
1872 }
1873
1874 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
1875
1876 *lpcchBuffer = dwLength;
1877
1878 return dwError;
1879 }
1880
1881
1882 /* Function 21 */
1883 unsigned long
1884 ScmrGetServiceKeyNameW(handle_t BindingHandle,
1885 unsigned int hSCManager,
1886 wchar_t *lpDisplayName,
1887 wchar_t *lpServiceName, /* [out, unique] */
1888 unsigned long *lpcchBuffer)
1889 {
1890 // PMANAGER_HANDLE hManager;
1891 PSERVICE lpService;
1892 DWORD dwLength;
1893 DWORD dwError;
1894
1895 DPRINT("ScmrGetServiceKeyNameW() called\n");
1896 DPRINT("hSCManager = %x\n", hSCManager);
1897 DPRINT("lpDisplayName: %S\n", lpDisplayName);
1898 DPRINT("lpServiceName: %p\n", lpServiceName);
1899 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer);
1900
1901 // hManager = (PMANAGER_HANDLE)hSCManager;
1902 // if (hManager->Handle.Tag != MANAGER_TAG)
1903 // {
1904 // DPRINT1("Invalid manager handle!\n");
1905 // return ERROR_INVALID_HANDLE;
1906 // }
1907
1908 /* Get service database entry */
1909 lpService = ScmGetServiceEntryByDisplayName(lpDisplayName);
1910 if (lpService == NULL)
1911 {
1912 DPRINT1("Could not find a service!\n");
1913 return ERROR_SERVICE_DOES_NOT_EXIST;
1914 }
1915
1916 dwLength = wcslen(lpService->lpServiceName) + 1;
1917
1918 if (lpServiceName != NULL &&
1919 *lpcchBuffer >= dwLength)
1920 {
1921 wcscpy(lpServiceName, lpService->lpServiceName);
1922 }
1923
1924 dwError = (*lpcchBuffer > dwLength) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
1925
1926 *lpcchBuffer = dwLength;
1927
1928 return dwError;
1929 }
1930
1931
1932 /* Function 22 */
1933 unsigned long
1934 ScmrSetServiceBitsA(handle_t BindingHandle,
1935 unsigned long hServiceStatus,
1936 unsigned long dwServiceBits,
1937 unsigned long bSetBitsOn,
1938 unsigned long bUpdateImmediately,
1939 char *lpString)
1940 {
1941 DPRINT1("ScmrSetServiceBitsA() is unimplemented\n");
1942 return ERROR_CALL_NOT_IMPLEMENTED;
1943 }
1944
1945
1946 /* Function 23 */
1947 unsigned long
1948 ScmrChangeServiceConfigA(handle_t BiningHandle,
1949 unsigned int hService,
1950 unsigned long dwServiceType,
1951 unsigned long dwStartType,
1952 unsigned long dwErrorControl,
1953 char *lpBinaryPathName,
1954 char *lpLoadOrderGroup,
1955 unsigned long *lpdwTagId,
1956 char *lpDependencies,
1957 unsigned long dwDependenciesLength,
1958 char *lpServiceStartName,
1959 char *lpPassword,
1960 unsigned long dwPasswordLength,
1961 char *lpDisplayName)
1962 {
1963 DPRINT1("ScmrChangeServiceConfigA() is unimplemented\n");
1964 return ERROR_CALL_NOT_IMPLEMENTED;
1965 }
1966
1967
1968 /* Function 24 */
1969 unsigned long
1970 ScmrCreateServiceA(handle_t BindingHandle,
1971 unsigned int hSCManager,
1972 char *lpServiceName,
1973 char *lpDisplayName,
1974 unsigned long dwDesiredAccess,
1975 unsigned long dwServiceType,
1976 unsigned long dwStartType,
1977 unsigned long dwErrorControl,
1978 char *lpBinaryPathName,
1979 char *lpLoadOrderGroup,
1980 unsigned long *lpdwTagId, /* in, out */
1981 char *lpDependencies,
1982 unsigned long dwDependenciesLength,
1983 char *lpServiceStartName,
1984 char *lpPassword,
1985 unsigned long dwPasswordLength,
1986 unsigned int *hService) /* out */
1987 {
1988 DPRINT1("ScmrCreateServiceA() is unimplemented\n");
1989 return ERROR_CALL_NOT_IMPLEMENTED;
1990 }
1991
1992
1993 /* Function 25 */
1994 unsigned long
1995 ScmrEnumDependentServicesA(handle_t BindingHandle,
1996 unsigned int hService,
1997 unsigned long dwServiceState,
1998 unsigned char *lpServices,
1999 unsigned long cbBufSize,
2000 unsigned long *pcbBytesNeeded,
2001 unsigned long *lpServicesReturned)
2002 {
2003 DPRINT1("ScmrEnumDependentServicesA() is unimplemented\n");
2004 *pcbBytesNeeded = 0;
2005 *lpServicesReturned = 0;
2006 return ERROR_CALL_NOT_IMPLEMENTED;
2007 }
2008
2009
2010 /* Function 26 */
2011 unsigned long
2012 ScmrEnumServicesStatusA(handle_t BindingHandle,
2013 unsigned int hSCManager,
2014 unsigned long dwServiceType,
2015 unsigned long dwServiceState,
2016 unsigned char *lpServices,
2017 unsigned long dwBufSize,
2018 unsigned long *pcbBytesNeeded,
2019 unsigned long *lpServicesReturned,
2020 unsigned long *lpResumeHandle)
2021 {
2022 DPRINT1("ScmrEnumServicesAtatusA() is unimplemented\n");
2023 return ERROR_CALL_NOT_IMPLEMENTED;
2024 }
2025
2026
2027 /* Function 27 */
2028 unsigned long
2029 ScmrOpenSCManagerA(handle_t BindingHandle,
2030 char *lpMachineName,
2031 char *lpDatabaseName,
2032 unsigned long dwDesiredAccess,
2033 unsigned int *hScm)
2034 {
2035 UNICODE_STRING MachineName;
2036 UNICODE_STRING DatabaseName;
2037 DWORD dwError;
2038
2039 DPRINT("ScmrOpenSCManagerA() called\n");
2040
2041 if (lpMachineName)
2042 RtlCreateUnicodeStringFromAsciiz(&MachineName,
2043 lpMachineName);
2044
2045 if (lpDatabaseName)
2046 RtlCreateUnicodeStringFromAsciiz(&DatabaseName,
2047 lpDatabaseName);
2048
2049 dwError = ScmrOpenSCManagerW(BindingHandle,
2050 lpMachineName ? MachineName.Buffer : NULL,
2051 lpDatabaseName ? DatabaseName.Buffer : NULL,
2052 dwDesiredAccess,
2053 hScm);
2054
2055 if (lpMachineName)
2056 RtlFreeUnicodeString(&MachineName);
2057
2058 if (lpDatabaseName)
2059 RtlFreeUnicodeString(&DatabaseName);
2060
2061 return dwError;
2062 }
2063
2064
2065 /* Function 28 */
2066 unsigned int
2067 ScmrOpenServiceA(handle_t BindingHandle,
2068 unsigned int hSCManager,
2069 char *lpServiceName,
2070 unsigned long dwDesiredAccess,
2071 unsigned int *hService)
2072 {
2073 UNICODE_STRING ServiceName;
2074 DWORD dwError;
2075
2076 DPRINT("ScmrOpenServiceA() called\n");
2077
2078 RtlCreateUnicodeStringFromAsciiz(&ServiceName,
2079 lpServiceName);
2080
2081 dwError = ScmrOpenServiceW(BindingHandle,
2082 hSCManager,
2083 ServiceName.Buffer,
2084 dwDesiredAccess,
2085 hService);
2086
2087 RtlFreeUnicodeString(&ServiceName);
2088
2089 return dwError;
2090 }
2091
2092
2093 /* Function 29 */
2094 unsigned long
2095 ScmrQueryServiceConfigA(handle_t BindingHandle,
2096 unsigned int hService,
2097 unsigned char *lpServiceConfig,
2098 unsigned long cbBufSize,
2099 unsigned long *pcbBytesNeeded)
2100 {
2101 DPRINT1("ScmrQueryServiceConfigA() is unimplemented\n");
2102 return ERROR_CALL_NOT_IMPLEMENTED;
2103 }
2104
2105
2106 /* Function 30 */
2107 unsigned long
2108 ScmrQueryServiceLockStatusA(handle_t BindingHandle,
2109 unsigned int hSCManager,
2110 unsigned char *lpLockStatus, /* [out, unique, size_is(cbBufSize)] */
2111 unsigned long cbBufSize, /* [in] */
2112 unsigned long *pcbBytesNeeded) /* [out] */
2113 {
2114 DPRINT1("ScmrQueryServiceLockStatusA() called\n");
2115 return ERROR_CALL_NOT_IMPLEMENTED;
2116 }
2117
2118
2119 /* Function 31 */
2120 unsigned long
2121 ScmrStartServiceA(handle_t BindingHandle,
2122 unsigned int hService,
2123 unsigned long dwNumServiceArgs,
2124 unsigned char *lpServiceArgBuffer,
2125 unsigned long cbBufSize)
2126 {
2127 DWORD dwError = ERROR_SUCCESS;
2128 PSERVICE_HANDLE hSvc;
2129 PSERVICE lpService = NULL;
2130
2131 DPRINT1("ScmrStartServiceA() called\n");
2132
2133 if (ScmShutdown)
2134 return ERROR_SHUTDOWN_IN_PROGRESS;
2135
2136 hSvc = (PSERVICE_HANDLE)hService;
2137 if (hSvc->Handle.Tag != SERVICE_TAG)
2138 {
2139 DPRINT1("Invalid handle tag!\n");
2140 return ERROR_INVALID_HANDLE;
2141 }
2142
2143 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
2144 SERVICE_START))
2145 {
2146 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
2147 return ERROR_ACCESS_DENIED;
2148 }
2149
2150 lpService = hSvc->ServiceEntry;
2151 if (lpService == NULL)
2152 {
2153 DPRINT1("lpService == NULL!\n");
2154 return ERROR_INVALID_HANDLE;
2155 }
2156
2157 if (lpService->dwStartType == SERVICE_DISABLED)
2158 return ERROR_SERVICE_DISABLED;
2159
2160 if (lpService->bDeleted)
2161 return ERROR_SERVICE_MARKED_FOR_DELETE;
2162
2163 /* FIXME: Convert argument vector to Unicode */
2164
2165 /* Start the service */
2166 dwError = ScmStartService(lpService, NULL);
2167
2168 /* FIXME: Free argument vector */
2169
2170 return dwError;
2171 }
2172
2173
2174 /* Function 32 */
2175 unsigned long
2176 ScmrGetServiceDisplayNameA(handle_t BindingHandle,
2177 unsigned int hSCManager,
2178 char *lpServiceName,
2179 char *lpDisplayName, /* [out, unique] */
2180 unsigned long *lpcchBuffer)
2181 {
2182 DPRINT1("ScmrGetServiceDisplayNameA() is unimplemented\n");
2183 return ERROR_CALL_NOT_IMPLEMENTED;
2184 }
2185
2186
2187 /* Function 33 */
2188 unsigned long
2189 ScmrGetServiceKeyNameA(handle_t BindingHandle,
2190 unsigned int hSCManager,
2191 char *lpDisplayName,
2192 char *lpServiceName, /* [out, unique] */
2193 unsigned long *lpcchBuffer)
2194 {
2195 DPRINT1("ScmrGetServiceKeyNameA() is unimplemented\n");
2196 return ERROR_CALL_NOT_IMPLEMENTED;
2197 }
2198
2199
2200 /* Function 34 */
2201 unsigned long
2202 ScmrGetCurrentGroupStateW(handle_t BindingHandle)
2203 {
2204 DPRINT1("ScmrGetCurrentGroupStateW() is unimplemented\n");
2205 return ERROR_CALL_NOT_IMPLEMENTED;
2206 }
2207
2208
2209 /* Function 35 */
2210 unsigned long
2211 ScmrEnumServiceGroupW(handle_t BindingHandle)
2212 {
2213 DPRINT1("ScmrEnumServiceGroupW() is unimplemented\n");
2214 return ERROR_CALL_NOT_IMPLEMENTED;
2215 }
2216
2217
2218 /* Function 36 */
2219 unsigned long
2220 ScmrChangeServiceConfig2A(handle_t BindingHandle,
2221 unsigned int hService,
2222 unsigned long dwInfoLevel,
2223 unsigned char *lpInfo,
2224 unsigned long dwInfoSize)
2225 {
2226 DPRINT1("ScmrChangeServiceConfig2A() is unimplemented\n");
2227 return ERROR_CALL_NOT_IMPLEMENTED;
2228 }
2229
2230
2231 /* Function 37 */
2232 unsigned long
2233 ScmrChangeServiceConfig2W(handle_t BindingHandle,
2234 unsigned int hService,
2235 unsigned long dwInfoLevel,
2236 unsigned char *lpInfo,
2237 unsigned long dwInfoSize)
2238 {
2239 DWORD dwError = ERROR_SUCCESS;
2240 PSERVICE_HANDLE hSvc;
2241 PSERVICE lpService = NULL;
2242 HKEY hServiceKey = NULL;
2243
2244 DPRINT("ScmrChangeServiceConfig2W() called\n");
2245 DPRINT("dwInfoLevel = %lu\n", dwInfoLevel);
2246 DPRINT("dwInfoSize = %lu\n", dwInfoSize);
2247
2248 if (ScmShutdown)
2249 return ERROR_SHUTDOWN_IN_PROGRESS;
2250
2251 hSvc = (PSERVICE_HANDLE)hService;
2252 if (hSvc->Handle.Tag != SERVICE_TAG)
2253 {
2254 DPRINT1("Invalid handle tag!\n");
2255 return ERROR_INVALID_HANDLE;
2256 }
2257
2258 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
2259 SERVICE_CHANGE_CONFIG))
2260 {
2261 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
2262 return ERROR_ACCESS_DENIED;
2263 }
2264
2265 lpService = hSvc->ServiceEntry;
2266 if (lpService == NULL)
2267 {
2268 DPRINT1("lpService == NULL!\n");
2269 return ERROR_INVALID_HANDLE;
2270 }
2271
2272 /* FIXME: Lock database exclusively */
2273
2274 if (lpService->bDeleted)
2275 {
2276 /* FIXME: Unlock database */
2277 DPRINT1("The service has already been marked for delete!\n");
2278 return ERROR_SERVICE_MARKED_FOR_DELETE;
2279 }
2280
2281 /* Open the service key */
2282 dwError = ScmOpenServiceKey(lpService->szServiceName,
2283 KEY_SET_VALUE,
2284 &hServiceKey);
2285 if (dwError != ERROR_SUCCESS)
2286 goto done;
2287
2288 if (dwInfoLevel & SERVICE_CONFIG_DESCRIPTION)
2289 {
2290 LPSERVICE_DESCRIPTIONW lpServiceDescription = (LPSERVICE_DESCRIPTIONW)lpInfo;
2291
2292 if (dwInfoSize != sizeof(*lpServiceDescription))
2293 {
2294 dwError = ERROR_INVALID_PARAMETER;
2295 goto done;
2296 }
2297
2298 if (lpServiceDescription != NULL && lpServiceDescription->lpDescription != NULL)
2299 {
2300 RegSetValueExW(hServiceKey,
2301 L"Description",
2302 0,
2303 REG_SZ,
2304 (LPBYTE)lpServiceDescription->lpDescription,
2305 (wcslen(lpServiceDescription->lpDescription) + 1) * sizeof(WCHAR));
2306
2307 if (dwError != ERROR_SUCCESS)
2308 goto done;
2309 }
2310 }
2311 else if (dwInfoLevel & SERVICE_CONFIG_FAILURE_ACTIONS)
2312 {
2313 DPRINT1("SERVICE_CONFIG_FAILURE_ACTIONS not implemented\n");
2314 dwError = ERROR_CALL_NOT_IMPLEMENTED;
2315 goto done;
2316 }
2317
2318 done:
2319 /* FIXME: Unlock database */
2320 if (hServiceKey != NULL)
2321 RegCloseKey(hServiceKey);
2322
2323 DPRINT("ScmrChangeServiceConfigW() done (Error %lu)\n", dwError);
2324
2325 return dwError;
2326 }
2327
2328
2329 /* Function 38 */
2330 unsigned long
2331 ScmrQueryServiceConfig2A(handle_t BindingHandle,
2332 unsigned int hService,
2333 unsigned long dwInfoLevel,
2334 unsigned char *lpBuffer,
2335 unsigned long cbBufSize,
2336 unsigned long *pcbBytesNeeded)
2337 {
2338 DPRINT1("ScmrQueryServiceConfig2A() is unimplemented\n");
2339 return ERROR_CALL_NOT_IMPLEMENTED;
2340 }
2341
2342
2343 /* Function 39 */
2344 unsigned long
2345 ScmrQueryServiceConfig2W(handle_t BindingHandle,
2346 unsigned int hService,
2347 unsigned long dwInfoLevel,
2348 unsigned char *lpBuffer,
2349 unsigned long cbBufSize,
2350 unsigned long *pcbBytesNeeded)
2351 {
2352 DWORD dwError = ERROR_SUCCESS;
2353 PSERVICE_HANDLE hSvc;
2354 PSERVICE lpService = NULL;
2355 HKEY hServiceKey = NULL;
2356 DWORD dwRequiredSize;
2357 LPWSTR lpDescription = NULL;
2358
2359 DPRINT("ScmrQueryServiceConfig2W() called\n");
2360
2361 if (ScmShutdown)
2362 return ERROR_SHUTDOWN_IN_PROGRESS;
2363
2364 hSvc = (PSERVICE_HANDLE)hService;
2365 if (hSvc->Handle.Tag != SERVICE_TAG)
2366 {
2367 DPRINT1("Invalid handle tag!\n");
2368 return ERROR_INVALID_HANDLE;
2369 }
2370
2371 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
2372 SERVICE_QUERY_CONFIG))
2373 {
2374 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
2375 return ERROR_ACCESS_DENIED;
2376 }
2377
2378 lpService = hSvc->ServiceEntry;
2379 if (lpService == NULL)
2380 {
2381 DPRINT1("lpService == NULL!\n");
2382 return ERROR_INVALID_HANDLE;
2383 }
2384
2385 /* FIXME: Lock the service database shared */
2386
2387 dwError = ScmOpenServiceKey(lpService->lpServiceName,
2388 KEY_READ,
2389 &hServiceKey);
2390 if (dwError != ERROR_SUCCESS)
2391 goto done;
2392
2393 if (dwInfoLevel & SERVICE_CONFIG_DESCRIPTION)
2394 {
2395 LPSERVICE_DESCRIPTIONW lpServiceDescription = (LPSERVICE_DESCRIPTIONW)lpBuffer;
2396 LPWSTR lpStr;
2397
2398 dwError = ScmReadString(hServiceKey,
2399 L"Description",
2400 &lpDescription);
2401 if (dwError != ERROR_SUCCESS)
2402 goto done;
2403
2404 dwRequiredSize = sizeof(SERVICE_DESCRIPTIONW) + ((wcslen(lpDescription) + 1) * sizeof(WCHAR));
2405
2406 if (cbBufSize < dwRequiredSize)
2407 {
2408 *pcbBytesNeeded = dwRequiredSize;
2409 dwError = ERROR_INSUFFICIENT_BUFFER;
2410 goto done;
2411 }
2412 else
2413 {
2414 lpStr = (LPWSTR)(lpServiceDescription + 1);
2415 wcscpy(lpStr, lpDescription);
2416 lpServiceDescription->lpDescription = (LPWSTR)((ULONG_PTR)lpStr - (ULONG_PTR)lpServiceDescription);
2417 }
2418 }
2419 else if (dwInfoLevel & SERVICE_CONFIG_FAILURE_ACTIONS)
2420 {
2421 DPRINT1("SERVICE_CONFIG_FAILURE_ACTIONS not implemented\n");
2422 dwError = ERROR_CALL_NOT_IMPLEMENTED;
2423 goto done;
2424 }
2425
2426 done:
2427 if (lpDescription != NULL)
2428 HeapFree(GetProcessHeap(), 0, lpDescription);
2429
2430 if (hServiceKey != NULL)
2431 RegCloseKey(hServiceKey);
2432
2433 /* FIXME: Unlock database */
2434
2435 DPRINT("ScmrQueryServiceConfig2W() done (Error %lu)\n", dwError);
2436
2437 return dwError;
2438 }
2439
2440
2441 /* Function 40 */
2442 unsigned long
2443 ScmrQueryServiceStatusEx(handle_t BindingHandle,
2444 unsigned int hService,
2445 unsigned long InfoLevel,
2446 unsigned char *lpBuffer, /* out */
2447 unsigned long cbBufSize,
2448 unsigned long *pcbBytesNeeded) /* out */
2449 {
2450 LPSERVICE_STATUS_PROCESS lpStatus;
2451 PSERVICE_HANDLE hSvc;
2452 PSERVICE lpService;
2453
2454 DPRINT("ScmrQueryServiceStatusEx() called\n");
2455
2456 if (ScmShutdown)
2457 return ERROR_SHUTDOWN_IN_PROGRESS;
2458
2459 if (InfoLevel != SC_STATUS_PROCESS_INFO)
2460 return ERROR_INVALID_LEVEL;
2461
2462 *pcbBytesNeeded = sizeof(SERVICE_STATUS_PROCESS);
2463
2464 if (cbBufSize < sizeof(SERVICE_STATUS_PROCESS))
2465 return ERROR_INSUFFICIENT_BUFFER;
2466
2467 hSvc = (PSERVICE_HANDLE)hService;
2468 if (hSvc->Handle.Tag != SERVICE_TAG)
2469 {
2470 DPRINT1("Invalid handle tag!\n");
2471 return ERROR_INVALID_HANDLE;
2472 }
2473
2474 if (!RtlAreAllAccessesGranted(hSvc->Handle.DesiredAccess,
2475 SERVICE_QUERY_STATUS))
2476 {
2477 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc->Handle.DesiredAccess);
2478 return ERROR_ACCESS_DENIED;
2479 }
2480
2481 lpService = hSvc->ServiceEntry;
2482 if (lpService == NULL)
2483 {
2484 DPRINT1("lpService == NULL!\n");
2485 return ERROR_INVALID_HANDLE;
2486 }
2487
2488 lpStatus = (LPSERVICE_STATUS_PROCESS)lpBuffer;
2489
2490 /* Return service status information */
2491 RtlCopyMemory(lpStatus,
2492 &lpService->Status,
2493 sizeof(SERVICE_STATUS));
2494
2495 lpStatus->dwProcessId = lpService->ProcessId; /* FIXME */
2496 lpStatus->dwServiceFlags = 0; /* FIXME */
2497
2498 return ERROR_SUCCESS;
2499 }
2500
2501
2502 /* Function 41 */
2503 unsigned long
2504 ScmrEnumServicesStatusExA(handle_t BindingHandle,
2505 unsigned int hSCManager,
2506 unsigned long InfoLevel,
2507 unsigned long dwServiceType,
2508 unsigned long dwServiceState,
2509 unsigned char *lpServices,
2510 unsigned long dwBufSize,
2511 unsigned long *pcbBytesNeeded,
2512 unsigned long *lpServicesReturned,
2513 unsigned long *lpResumeHandle,
2514 char *pszGroupName)
2515 {
2516 DPRINT1("ScmrEnumServicesStatusExA() is unimplemented\n");
2517 *pcbBytesNeeded = 0;
2518 *lpServicesReturned = 0;
2519 return ERROR_CALL_NOT_IMPLEMENTED;
2520 }
2521
2522
2523 /* Function 42 */
2524 unsigned long
2525 ScmrEnumServicesStatusExW(handle_t BindingHandle,
2526 unsigned int hSCManager,
2527 unsigned long InfoLevel,
2528 unsigned long dwServiceType,
2529 unsigned long dwServiceState,
2530 unsigned char *lpServices,
2531 unsigned long dwBufSize,
2532 unsigned long *pcbBytesNeeded,
2533 unsigned long *lpServicesReturned,
2534 unsigned long *lpResumeHandle,
2535 wchar_t *pszGroupName)
2536 {
2537 PMANAGER_HANDLE hManager;
2538 PSERVICE lpService;
2539 DWORD dwError = ERROR_SUCCESS;
2540 PLIST_ENTRY ServiceEntry;
2541 PSERVICE CurrentService;
2542 DWORD dwState;
2543 DWORD dwRequiredSize;
2544 DWORD dwServiceCount;
2545 DWORD dwSize;
2546 DWORD dwLastResumeCount;
2547 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr;
2548 LPWSTR lpStringPtr;
2549
2550 DPRINT("ScmrEnumServicesStatusExW() called\n");
2551
2552 if (ScmShutdown)
2553 return ERROR_SHUTDOWN_IN_PROGRESS;
2554
2555 if (InfoLevel != SC_ENUM_PROCESS_INFO)
2556 return ERROR_INVALID_LEVEL;
2557
2558 hManager = (PMANAGER_HANDLE)hSCManager;
2559 if (hManager->Handle.Tag != MANAGER_TAG)
2560 {
2561 DPRINT1("Invalid manager handle!\n");
2562 return ERROR_INVALID_HANDLE;
2563 }
2564
2565 /* Check access rights */
2566 if (!RtlAreAllAccessesGranted(hManager->Handle.DesiredAccess,
2567 SC_MANAGER_ENUMERATE_SERVICE))
2568 {
2569 DPRINT1("Insufficient access rights! 0x%lx\n",
2570 hManager->Handle.DesiredAccess);
2571 return ERROR_ACCESS_DENIED;
2572 }
2573
2574 *pcbBytesNeeded = 0;
2575 *lpServicesReturned = 0;
2576
2577 dwLastResumeCount = *lpResumeHandle;
2578
2579 /* Lock the service list shared */
2580
2581 lpService = ScmGetServiceEntryByResumeCount(dwLastResumeCount);
2582 if (lpService == NULL)
2583 {
2584 dwError = ERROR_SUCCESS;
2585 goto Done;
2586 }
2587
2588 dwRequiredSize = 0;
2589 dwServiceCount = 0;
2590
2591 for (ServiceEntry = &lpService->ServiceListEntry;
2592 ServiceEntry != &ServiceListHead;
2593 ServiceEntry = ServiceEntry->Flink)
2594 {
2595 CurrentService = CONTAINING_RECORD(ServiceEntry,
2596 SERVICE,
2597 ServiceListEntry);
2598
2599 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2600 continue;
2601
2602 dwState = SERVICE_ACTIVE;
2603 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2604 dwState = SERVICE_INACTIVE;
2605
2606 if ((dwState & dwServiceState) == 0)
2607 continue;
2608
2609 if (pszGroupName)
2610 {
2611 if (*pszGroupName == 0)
2612 {
2613 if (CurrentService->lpGroup != NULL)
2614 continue;
2615 }
2616 else
2617 {
2618 if ((CurrentService->lpGroup == NULL) ||
2619 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
2620 continue;
2621 }
2622 }
2623
2624 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2625 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2626 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
2627
2628 if (dwRequiredSize + dwSize <= dwBufSize)
2629 {
2630 DPRINT("Service name: %S fit\n", CurrentService->lpServiceName);
2631 dwRequiredSize += dwSize;
2632 dwServiceCount++;
2633 dwLastResumeCount = CurrentService->dwResumeCount;
2634 }
2635 else
2636 {
2637 DPRINT("Service name: %S no fit\n", CurrentService->lpServiceName);
2638 break;
2639 }
2640
2641 }
2642
2643 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize);
2644 DPRINT("dwServiceCount: %lu\n", dwServiceCount);
2645
2646 for (;
2647 ServiceEntry != &ServiceListHead;
2648 ServiceEntry = ServiceEntry->Flink)
2649 {
2650 CurrentService = CONTAINING_RECORD(ServiceEntry,
2651 SERVICE,
2652 ServiceListEntry);
2653
2654 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2655 continue;
2656
2657 dwState = SERVICE_ACTIVE;
2658 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2659 dwState = SERVICE_INACTIVE;
2660
2661 if ((dwState & dwServiceState) == 0)
2662 continue;
2663
2664 if (pszGroupName)
2665 {
2666 if (*pszGroupName == 0)
2667 {
2668 if (CurrentService->lpGroup != NULL)
2669 continue;
2670 }
2671 else
2672 {
2673 if ((CurrentService->lpGroup == NULL) ||
2674 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
2675 continue;
2676 }
2677 }
2678
2679 dwRequiredSize += (sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2680 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2681 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR)));
2682
2683 dwError = ERROR_MORE_DATA;
2684 }
2685
2686 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize);
2687
2688 *lpResumeHandle = dwLastResumeCount;
2689 *lpServicesReturned = dwServiceCount;
2690 *pcbBytesNeeded = dwRequiredSize;
2691
2692 lpStatusPtr = (LPENUM_SERVICE_STATUS_PROCESSW)lpServices;
2693 lpStringPtr = (LPWSTR)((ULONG_PTR)lpServices +
2694 dwServiceCount * sizeof(ENUM_SERVICE_STATUS_PROCESSW));
2695
2696 dwRequiredSize = 0;
2697 for (ServiceEntry = &lpService->ServiceListEntry;
2698 ServiceEntry != &ServiceListHead;
2699 ServiceEntry = ServiceEntry->Flink)
2700 {
2701 CurrentService = CONTAINING_RECORD(ServiceEntry,
2702 SERVICE,
2703 ServiceListEntry);
2704
2705 if ((CurrentService->Status.dwServiceType & dwServiceType) == 0)
2706 continue;
2707
2708 dwState = SERVICE_ACTIVE;
2709 if (CurrentService->Status.dwCurrentState == SERVICE_STOPPED)
2710 dwState = SERVICE_INACTIVE;
2711
2712 if ((dwState & dwServiceState) == 0)
2713 continue;
2714
2715 if (pszGroupName)
2716 {
2717 if (*pszGroupName == 0)
2718 {
2719 if (CurrentService->lpGroup != NULL)
2720 continue;
2721 }
2722 else
2723 {
2724 if ((CurrentService->lpGroup == NULL) ||
2725 _wcsicmp(pszGroupName, CurrentService->lpGroup->lpGroupName))
2726 continue;
2727 }
2728 }
2729
2730 dwSize = sizeof(ENUM_SERVICE_STATUS_PROCESSW) +
2731 ((wcslen(CurrentService->lpServiceName) + 1) * sizeof(WCHAR)) +
2732 ((wcslen(CurrentService->lpDisplayName) + 1) * sizeof(WCHAR));
2733
2734 if (dwRequiredSize + dwSize <= dwBufSize)
2735 {
2736 /* Copy the service name */
2737 wcscpy(lpStringPtr,
2738 CurrentService->lpServiceName);
2739 lpStatusPtr->lpServiceName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
2740 lpStringPtr += (wcslen(CurrentService->lpServiceName) + 1);
2741
2742 /* Copy the display name */
2743 wcscpy(lpStringPtr,
2744 CurrentService->lpDisplayName);
2745 lpStatusPtr->lpDisplayName = (LPWSTR)((ULONG_PTR)lpStringPtr - (ULONG_PTR)lpServices);
2746 lpStringPtr += (wcslen(CurrentService->lpDisplayName) + 1);
2747
2748 /* Copy the status information */
2749 memcpy(&lpStatusPtr->ServiceStatusProcess,
2750 &CurrentService->Status,
2751 sizeof(SERVICE_STATUS));
2752 lpStatusPtr->ServiceStatusProcess.dwProcessId = CurrentService->ProcessId; /* FIXME */
2753 lpStatusPtr->ServiceStatusProcess.dwServiceFlags = 0; /* FIXME */
2754
2755 lpStatusPtr++;
2756 dwRequiredSize += dwSize;
2757 }
2758 else
2759 {
2760 break;
2761 }
2762
2763 }
2764
2765 Done:;
2766 /* Unlock the service list */
2767
2768 DPRINT("ScmrEnumServicesStatusExW() done (Error %lu)\n", dwError);
2769
2770 return dwError;
2771 }
2772
2773
2774 /* Function 43 */
2775 /* ScmrSendTSMessage */
2776
2777
2778 void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len)
2779 {
2780 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
2781 }
2782
2783
2784 void __RPC_USER midl_user_free(void __RPC_FAR * ptr)
2785 {
2786 HeapFree(GetProcessHeap(), 0, ptr);
2787 }
2788
2789 /* EOF */