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