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