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>
12 /* INCLUDES ****************************************************************/
20 #define SC_LOCK unsigned int
21 #define SC_STATUS_TYPE unsigned long
22 #define SC_ENUM_TYPE unsigned long
24 /* GLOBALS *****************************************************************/
26 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
27 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
29 typedef struct _SCMGR_HANDLE
37 typedef struct _MANAGER_HANDLE
41 /* FIXME: Insert more data here */
43 WCHAR DatabaseName
[1];
44 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
47 typedef struct _SERVICE_HANDLE
52 PSERVICE ServiceEntry
;
54 /* FIXME: Insert more data here */
56 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
59 #define SC_MANAGER_READ \
60 (STANDARD_RIGHTS_READ | \
61 SC_MANAGER_QUERY_LOCK_STATUS | \
62 SC_MANAGER_ENUMERATE_SERVICE)
64 #define SC_MANAGER_WRITE \
65 (STANDARD_RIGHTS_WRITE | \
66 SC_MANAGER_MODIFY_BOOT_CONFIG | \
67 SC_MANAGER_CREATE_SERVICE)
69 #define SC_MANAGER_EXECUTE \
70 (STANDARD_RIGHTS_EXECUTE | \
72 SC_MANAGER_ENUMERATE_SERVICE | \
73 SC_MANAGER_CONNECT | \
74 SC_MANAGER_CREATE_SERVICE)
77 #define SERVICE_READ \
78 (STANDARD_RIGHTS_READ | \
79 SERVICE_INTERROGATE | \
80 SERVICE_ENUMERATE_DEPENDENTS | \
81 SERVICE_QUERY_STATUS | \
84 #define SERVICE_WRITE \
85 (STANDARD_RIGHTS_WRITE | \
86 SERVICE_CHANGE_CONFIG)
88 #define SERVICE_EXECUTE \
89 (STANDARD_RIGHTS_EXECUTE | \
90 SERVICE_USER_DEFINED_CONTROL | \
91 SERVICE_PAUSE_CONTINUE | \
96 /* VARIABLES ***************************************************************/
98 static GENERIC_MAPPING
99 ScmManagerMapping
= {SC_MANAGER_READ
,
102 SC_MANAGER_ALL_ACCESS
};
104 static GENERIC_MAPPING
105 ScmServiceMapping
= {SERVICE_READ
,
108 SC_MANAGER_ALL_ACCESS
};
111 /* FUNCTIONS ***************************************************************/
114 ScmStartRpcServer(VOID
)
118 DPRINT("ScmStartRpcServer() called");
120 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
124 if (Status
!= RPC_S_OK
)
126 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
130 Status
= RpcServerRegisterIf(svcctl_ServerIfHandle
,
133 if (Status
!= RPC_S_OK
)
135 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
139 Status
= RpcServerListen(1, 20, TRUE
);
140 if (Status
!= RPC_S_OK
)
142 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
146 DPRINT("ScmStartRpcServer() done");
151 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
156 if (lpDatabaseName
== NULL
)
157 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
159 Ptr
= (MANAGER_HANDLE
*) HeapAlloc(GetProcessHeap(),
161 sizeof(MANAGER_HANDLE
) + wcslen(lpDatabaseName
) * sizeof(WCHAR
));
163 return ERROR_NOT_ENOUGH_MEMORY
;
165 Ptr
->Handle
.Tag
= MANAGER_TAG
;
166 Ptr
->Handle
.RefCount
= 1;
168 /* FIXME: initialize more data here */
170 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
172 *Handle
= (SC_HANDLE
)Ptr
;
174 return ERROR_SUCCESS
;
179 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
184 Ptr
= (SERVICE_HANDLE
*) HeapAlloc(GetProcessHeap(),
186 sizeof(SERVICE_HANDLE
));
188 return ERROR_NOT_ENOUGH_MEMORY
;
190 Ptr
->Handle
.Tag
= SERVICE_TAG
;
191 Ptr
->Handle
.RefCount
= 1;
193 /* FIXME: initialize more data here */
194 Ptr
->ServiceEntry
= lpServiceEntry
;
196 *Handle
= (SC_HANDLE
)Ptr
;
198 return ERROR_SUCCESS
;
203 ScmCheckAccess(SC_HANDLE Handle
,
204 DWORD dwDesiredAccess
)
206 PMANAGER_HANDLE hMgr
;
208 hMgr
= (PMANAGER_HANDLE
)Handle
;
209 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
211 RtlMapGenericMask(&dwDesiredAccess
,
214 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
216 return ERROR_SUCCESS
;
218 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
220 RtlMapGenericMask(&dwDesiredAccess
,
223 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
225 return ERROR_SUCCESS
;
228 return ERROR_INVALID_HANDLE
;
233 ScmAssignNewTag(PSERVICE lpService
)
236 DPRINT("Assigning new tag to service %S\n", lpService
->lpServiceName
);
237 lpService
->dwTag
= 0;
238 return ERROR_SUCCESS
;
244 ScmrCloseServiceHandle(handle_t BindingHandle
,
245 unsigned long hScObject
)
247 PMANAGER_HANDLE hManager
;
249 DPRINT("ScmrCloseServiceHandle() called\n");
251 DPRINT("hScObject = %X\n", hScObject
);
254 return ERROR_INVALID_HANDLE
;
256 hManager
= (PMANAGER_HANDLE
)hScObject
;
257 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
259 DPRINT("Found manager handle\n");
261 hManager
->Handle
.RefCount
--;
262 if (hManager
->Handle
.RefCount
== 0)
264 /* FIXME: add cleanup code */
266 HeapFree(GetProcessHeap(), 0, hManager
);
269 DPRINT("ScmrCloseServiceHandle() done\n");
270 return ERROR_SUCCESS
;
272 else if (hManager
->Handle
.Tag
== SERVICE_TAG
)
274 DPRINT("Found service handle\n");
276 hManager
->Handle
.RefCount
--;
277 if (hManager
->Handle
.RefCount
== 0)
279 /* FIXME: add cleanup code */
281 HeapFree(GetProcessHeap(), 0, hManager
);
284 DPRINT("ScmrCloseServiceHandle() done\n");
285 return ERROR_SUCCESS
;
288 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
290 return ERROR_INVALID_HANDLE
;
296 ScmrControlService(handle_t BindingHandle
,
297 unsigned long hService
,
299 LPSERVICE_STATUS lpServiceStatus
)
301 PSERVICE_HANDLE hSvc
;
303 ACCESS_MASK DesiredAccess
;
304 DWORD dwError
= ERROR_SUCCESS
;
306 DPRINT("ScmrControlService() called\n");
309 return ERROR_SHUTDOWN_IN_PROGRESS
;
311 /* Check the service handle */
312 hSvc
= (PSERVICE_HANDLE
)hService
;
313 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
315 DPRINT1("Invalid handle tag!\n");
316 return ERROR_INVALID_HANDLE
;
319 /* Check access rights */
322 case SERVICE_CONTROL_STOP
:
323 DesiredAccess
= SERVICE_STOP
;
326 case SERVICE_CONTROL_PAUSE
:
327 case SERVICE_CONTROL_CONTINUE
:
328 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
331 case SERVICE_INTERROGATE
:
332 DesiredAccess
= SERVICE_INTERROGATE
;
336 if (dwControl
>= 128 && dwControl
<= 255)
337 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
339 DesiredAccess
= SERVICE_QUERY_CONFIG
|
340 SERVICE_CHANGE_CONFIG
|
341 SERVICE_QUERY_STATUS
|
343 SERVICE_PAUSE_CONTINUE
;
347 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
349 return ERROR_ACCESS_DENIED
;
351 /* Check the service entry point */
352 lpService
= hSvc
->ServiceEntry
;
353 if (lpService
== NULL
)
355 DPRINT1("lpService == NULL!\n");
356 return ERROR_INVALID_HANDLE
;
359 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
361 /* Send control code to the driver */
362 dwError
= ScmControlDriver(lpService
,
368 /* Send control code to the service */
369 dwError
= ScmControlService(lpService
,
374 /* Return service status information */
375 RtlCopyMemory(lpServiceStatus
,
377 sizeof(SERVICE_STATUS
));
385 ScmrDeleteService(handle_t BindingHandle
,
386 unsigned long hService
)
388 PSERVICE_HANDLE hSvc
;
392 DPRINT("ScmrDeleteService() called\n");
395 return ERROR_SHUTDOWN_IN_PROGRESS
;
397 hSvc
= (PSERVICE_HANDLE
)hService
;
398 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
399 return ERROR_INVALID_HANDLE
;
401 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
402 STANDARD_RIGHTS_REQUIRED
))
403 return ERROR_ACCESS_DENIED
;
405 lpService
= hSvc
->ServiceEntry
;
406 if (lpService
== NULL
)
408 DPRINT1("lpService == NULL!\n");
409 return ERROR_INVALID_HANDLE
;
412 /* FIXME: Acquire service database lock exclusively */
414 if (lpService
->bDeleted
)
416 DPRINT1("The service has already been marked for delete!\n");
417 return ERROR_SERVICE_MARKED_FOR_DELETE
;
420 /* Mark service for delete */
421 lpService
->bDeleted
= TRUE
;
423 dwError
= ScmMarkServiceForDelete(lpService
);
425 /* FIXME: Release service database lock */
427 DPRINT("ScmrDeleteService() done\n");
435 ScmrLockServiceDatabase(handle_t BindingHandle
,
436 unsigned long hSCManager
,
439 PMANAGER_HANDLE hMgr
;
441 DPRINT("ScmrLockServiceDatabase() called\n");
445 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
446 if (hMgr
->Handle
.Tag
!= MANAGER_TAG
)
447 return ERROR_INVALID_HANDLE
;
449 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
451 return ERROR_ACCESS_DENIED
;
453 // return ScmLockDatabase(0, hMgr->0xC, hLock);
455 /* FIXME: Lock the database */
456 *hLock
= 0x12345678; /* Dummy! */
458 return ERROR_SUCCESS
;
464 ScmrQueryServiceObjectSecurity(handle_t BindingHandle
,
465 unsigned long hService
,
466 DWORD dwSecurityInformation
,
467 unsigned char *lpSecurityDescriptor
,
468 DWORD dwSecuityDescriptorSize
,
469 DWORD
*pcbBytesNeeded
)
472 PSERVICE_HANDLE hSvc
;
474 ULONG DesiredAccess
= 0;
479 DPRINT("ScmrQueryServiceObjectSecurity() called\n");
481 hSvc
= (PSERVICE_HANDLE
)hService
;
482 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
484 DPRINT1("Invalid handle tag!\n");
485 return ERROR_INVALID_HANDLE
;
488 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
489 GROUP_SECURITY_INFORMATION
||
490 OWNER_SECURITY_INFORMATION
))
491 DesiredAccess
|= READ_CONTROL
;
493 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
494 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
496 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
499 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
500 return ERROR_ACCESS_DENIED
;
503 lpService
= hSvc
->ServiceEntry
;
504 if (lpService
== NULL
)
506 DPRINT1("lpService == NULL!\n");
507 return ERROR_INVALID_HANDLE
;
510 /* FIXME: Lock the service list */
512 Status
= RtlQuerySecurityObject(lpService
->lpSecurityDescriptor
,
513 dwSecurityInformation
,
514 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
515 dwSecuityDescriptorSize
,
518 /* FIXME: Unlock the service list */
520 if (NT_SUCCESS(Status
))
522 *pcbBytesNeeded
= dwBytesNeeded
;
523 dwError
= STATUS_SUCCESS
;
525 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
527 *pcbBytesNeeded
= dwBytesNeeded
;
528 dwError
= ERROR_INSUFFICIENT_BUFFER
;
530 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
532 dwError
= ERROR_GEN_FAILURE
;
536 dwError
= RtlNtStatusToDosError(Status
);
541 DPRINT1("ScmrQueryServiceObjectSecurity() is unimplemented\n");
542 return ERROR_CALL_NOT_IMPLEMENTED
;
548 ScmrSetServiceObjectSecurity(handle_t BindingHandle
,
549 unsigned long hService
,
550 DWORD dwSecurityInformation
,
551 unsigned char *lpSecurityDescriptor
,
552 DWORD dwSecuityDescriptorSize
)
554 PSERVICE_HANDLE hSvc
;
556 ULONG DesiredAccess
= 0;
557 HANDLE hToken
= NULL
;
562 DPRINT1("ScmrSetServiceObjectSecurity() called\n");
564 hSvc
= (PSERVICE_HANDLE
)hService
;
565 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
567 DPRINT1("Invalid handle tag!\n");
568 return ERROR_INVALID_HANDLE
;
571 if (dwSecurityInformation
== 0 ||
572 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
573 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
574 return ERROR_INVALID_PARAMETER
;
576 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
577 return ERROR_INVALID_PARAMETER
;
579 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
580 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
582 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
583 DesiredAccess
|= WRITE_DAC
;
585 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
586 DesiredAccess
|= WRITE_OWNER
;
588 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
589 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
590 return ERROR_INVALID_PARAMETER
;
592 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
593 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
594 return ERROR_INVALID_PARAMETER
;
596 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
599 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
600 return ERROR_ACCESS_DENIED
;
603 lpService
= hSvc
->ServiceEntry
;
604 if (lpService
== NULL
)
606 DPRINT1("lpService == NULL!\n");
607 return ERROR_INVALID_HANDLE
;
610 if (lpService
->bDeleted
)
611 return ERROR_SERVICE_MARKED_FOR_DELETE
;
613 RpcImpersonateClient(NULL
);
615 Status
= NtOpenThreadToken(NtCurrentThread(),
619 if (!NT_SUCCESS(Status
))
620 return RtlNtStatusToDosError(Status
);
624 /* FIXME: Lock service database */
627 Status
= RtlSetSecurityObject(dwSecurityInformation
,
628 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
629 &lpService
->lpSecurityDescriptor
,
632 if (!NT_SUCCESS(Status
))
634 dwError
= RtlNtStatusToDosError(Status
);
639 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
640 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
642 if (dwError
!= ERROR_SUCCESS
)
645 DPRINT1("Stub: ScmrSetServiceObjectSecurity() is unimplemented\n");
646 dwError
= ERROR_SUCCESS
;
647 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
648 // lpService->lpSecurityDescriptor);
650 RegFlushKey(hServiceKey
);
651 RegCloseKey(hServiceKey
);
658 /* FIXME: Unlock service database */
660 DPRINT("ScmrSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
668 ScmrQueryServiceStatus(handle_t BindingHandle
,
669 unsigned long hService
,
670 LPSERVICE_STATUS lpServiceStatus
)
672 PSERVICE_HANDLE hSvc
;
675 DPRINT("ScmrQueryServiceStatus() called\n");
678 return ERROR_SHUTDOWN_IN_PROGRESS
;
680 hSvc
= (PSERVICE_HANDLE
)hService
;
681 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
683 DPRINT1("Invalid handle tag!\n");
684 return ERROR_INVALID_HANDLE
;
687 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
688 SERVICE_QUERY_STATUS
))
690 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
691 return ERROR_ACCESS_DENIED
;
694 lpService
= hSvc
->ServiceEntry
;
695 if (lpService
== NULL
)
697 DPRINT1("lpService == NULL!\n");
698 return ERROR_INVALID_HANDLE
;
701 /* Return service status information */
702 RtlCopyMemory(lpServiceStatus
,
704 sizeof(SERVICE_STATUS
));
706 return ERROR_SUCCESS
;
712 ScmrSetServiceStatus(handle_t BindingHandle
,
713 SERVICE_STATUS_HANDLE hServiceStatus
,
714 LPSERVICE_STATUS lpServiceStatus
)
718 DPRINT("ScmrSetServiceStatus() called\n");
721 return ERROR_SHUTDOWN_IN_PROGRESS
;
723 lpService
= ScmGetServiceEntryByClientHandle((ULONG
)hServiceStatus
);
724 if (lpService
== NULL
)
726 DPRINT1("lpService == NULL!\n");
727 return ERROR_INVALID_HANDLE
;
730 RtlCopyMemory(&lpService
->Status
,
732 sizeof(SERVICE_STATUS
));
734 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
735 DPRINT("ScmrSetServiceStatus() done\n");
737 return ERROR_SUCCESS
;
743 ScmrUnlockServiceDatabase(handle_t BindingHandle
,
746 DPRINT1("ScmrUnlockServiceDatabase() called\n");
748 return ERROR_SUCCESS
;
754 ScmrNotifyBootConfigStatus(handle_t BindingHandle
,
757 DPRINT1("ScmrNotifyBootConfigStatus() called\n");
759 return ERROR_CALL_NOT_IMPLEMENTED
;
765 ScmrSetServiceBitsW(handle_t BindingHandle
,
766 SERVICE_STATUS_HANDLE hServiceStatus
,
769 BOOL bUpdateImmediately
,
772 DPRINT1("ScmrSetServiceBitsW() called\n");
774 return ERROR_CALL_NOT_IMPLEMENTED
;
780 ScmrChangeServiceConfigW(handle_t BiningHandle
,
781 unsigned long hService
,
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
,
792 DWORD dwPasswordLength
,
793 wchar_t *lpDisplayName
)
795 DWORD dwError
= ERROR_SUCCESS
;
796 PSERVICE_HANDLE hSvc
;
797 PSERVICE lpService
= NULL
;
798 HKEY hServiceKey
= NULL
;
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
);
809 return ERROR_SHUTDOWN_IN_PROGRESS
;
811 hSvc
= (PSERVICE_HANDLE
)hService
;
812 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
814 DPRINT1("Invalid handle tag!\n");
815 return ERROR_INVALID_HANDLE
;
818 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
819 SERVICE_CHANGE_CONFIG
))
821 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
822 return ERROR_ACCESS_DENIED
;
825 lpService
= hSvc
->ServiceEntry
;
826 if (lpService
== NULL
)
828 DPRINT1("lpService == NULL!\n");
829 return ERROR_INVALID_HANDLE
;
832 /* FIXME: Lock database exclusively */
834 if (lpService
->bDeleted
)
836 /* FIXME: Unlock database */
837 DPRINT1("The service has already been marked for delete!\n");
838 return ERROR_SERVICE_MARKED_FOR_DELETE
;
841 /* Open the service key */
842 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
845 if (dwError
!= ERROR_SUCCESS
)
848 /* Write service data to the registry */
849 /* Set the display name */
850 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
852 RegSetValueExW(hServiceKey
,
856 (LPBYTE
)lpDisplayName
,
857 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
858 /* FIXME: update lpService->lpDisplayName */
861 if (dwServiceType
!= SERVICE_NO_CHANGE
)
863 /* Set the service type */
864 dwError
= RegSetValueExW(hServiceKey
,
868 (LPBYTE
)&dwServiceType
,
870 if (dwError
!= ERROR_SUCCESS
)
873 lpService
->Status
.dwServiceType
= dwServiceType
;
876 if (dwStartType
!= SERVICE_NO_CHANGE
)
878 /* Set the start value */
879 dwError
= RegSetValueExW(hServiceKey
,
883 (LPBYTE
)&dwStartType
,
885 if (dwError
!= ERROR_SUCCESS
)
888 lpService
->dwStartType
= dwStartType
;
891 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
893 /* Set the error control value */
894 dwError
= RegSetValueExW(hServiceKey
,
898 (LPBYTE
)&dwErrorControl
,
900 if (dwError
!= ERROR_SUCCESS
)
903 lpService
->dwErrorControl
= dwErrorControl
;
907 /* FIXME: set the new ImagePath value */
909 /* Set the image path */
910 if (dwServiceType
& SERVICE_WIN32
)
912 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
914 dwError
= RegSetValueExW(hServiceKey
,
918 (LPBYTE
)lpBinaryPathName
,
919 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
920 if (dwError
!= ERROR_SUCCESS
)
924 else if (dwServiceType
& SERVICE_DRIVER
)
926 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
928 dwError
= RegSetValueExW(hServiceKey
,
933 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
934 if (dwError
!= ERROR_SUCCESS
)
940 /* Set the group name */
941 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
943 dwError
= RegSetValueExW(hServiceKey
,
947 (LPBYTE
)lpLoadOrderGroup
,
948 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
949 if (dwError
!= ERROR_SUCCESS
)
951 /* FIXME: update lpService->lpServiceGroup */
954 if (lpdwTagId
!= NULL
)
956 dwError
= ScmAssignNewTag(lpService
);
957 if (dwError
!= ERROR_SUCCESS
)
960 dwError
= RegSetValueExW(hServiceKey
,
964 (LPBYTE
)&lpService
->dwTag
,
966 if (dwError
!= ERROR_SUCCESS
)
969 *lpdwTagId
= lpService
->dwTag
;
972 /* Write dependencies */
973 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
975 dwError
= ScmWriteDependencies(hServiceKey
,
977 dwDependenciesLength
);
978 if (dwError
!= ERROR_SUCCESS
)
982 if (lpPassword
!= NULL
)
984 /* FIXME: Write password */
987 /* FIXME: Unlock database */
990 if (hServiceKey
!= NULL
)
991 RegCloseKey(hServiceKey
);
993 DPRINT("ScmrChangeServiceConfigW() done (Error %lu)\n", dwError
);
1001 ScmrCreateServiceW(handle_t BindingHandle
,
1002 unsigned long hSCManager
,
1003 wchar_t *lpServiceName
,
1004 wchar_t *lpDisplayName
,
1005 DWORD dwDesiredAccess
,
1006 DWORD dwServiceType
,
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 */
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
;
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
);
1037 return ERROR_SHUTDOWN_IN_PROGRESS
;
1039 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1040 if (hManager
->Handle
.Tag
!= MANAGER_TAG
)
1042 DPRINT1("Invalid manager handle!\n");
1043 return ERROR_INVALID_HANDLE
;
1046 /* Check access rights */
1047 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1048 SC_MANAGER_CREATE_SERVICE
))
1050 DPRINT1("Insufficient access rights! 0x%lx\n",
1051 hManager
->Handle
.DesiredAccess
);
1052 return ERROR_ACCESS_DENIED
;
1055 /* Fail if the service already exists! */
1056 if (ScmGetServiceEntryByName(lpServiceName
) != NULL
)
1057 return ERROR_SERVICE_EXISTS
;
1059 if (dwServiceType
& SERVICE_DRIVER
)
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);
1066 lpImagePath
= (WCHAR
*) HeapAlloc(GetProcessHeap(),
1068 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1069 if (lpImagePath
== NULL
)
1071 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1074 wcscpy(lpImagePath
, lpBinaryPathName
);
1077 /* Allocate a new service entry */
1078 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1080 if (dwError
!= ERROR_SUCCESS
)
1083 /* Fill the new service entry */
1084 lpService
->Status
.dwServiceType
= dwServiceType
;
1085 lpService
->dwStartType
= dwStartType
;
1086 lpService
->dwErrorControl
= dwErrorControl
;
1088 /* Fill the display name */
1089 if (lpDisplayName
!= NULL
&&
1090 *lpDisplayName
!= 0 &&
1091 wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1093 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1094 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1095 if (lpService
->lpDisplayName
== NULL
)
1097 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1100 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1103 /* Assign the service to a group */
1104 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1106 dwError
= ScmSetServiceGroup(lpService
,
1108 if (dwError
!= ERROR_SUCCESS
)
1112 /* Assign a new tag */
1113 if (lpdwTagId
!= NULL
)
1115 dwError
= ScmAssignNewTag(lpService
);
1116 if (dwError
!= ERROR_SUCCESS
)
1120 /* Write service data to the registry */
1121 /* Create the service key */
1122 dwError
= ScmCreateServiceKey(lpServiceName
,
1125 if (dwError
!= ERROR_SUCCESS
)
1128 /* Set the display name */
1129 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1131 RegSetValueExW(hServiceKey
,
1135 (LPBYTE
)lpDisplayName
,
1136 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1139 /* Set the service type */
1140 dwError
= RegSetValueExW(hServiceKey
,
1144 (LPBYTE
)&dwServiceType
,
1146 if (dwError
!= ERROR_SUCCESS
)
1149 /* Set the start value */
1150 dwError
= RegSetValueExW(hServiceKey
,
1154 (LPBYTE
)&dwStartType
,
1156 if (dwError
!= ERROR_SUCCESS
)
1159 /* Set the error control value */
1160 dwError
= RegSetValueExW(hServiceKey
,
1164 (LPBYTE
)&dwErrorControl
,
1166 if (dwError
!= ERROR_SUCCESS
)
1169 /* Set the image path */
1170 if (dwServiceType
& SERVICE_WIN32
)
1172 dwError
= RegSetValueExW(hServiceKey
,
1176 (LPBYTE
)lpBinaryPathName
,
1177 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1178 if (dwError
!= ERROR_SUCCESS
)
1181 else if (dwServiceType
& SERVICE_DRIVER
)
1183 dwError
= RegSetValueExW(hServiceKey
,
1187 (LPBYTE
)lpImagePath
,
1188 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1189 if (dwError
!= ERROR_SUCCESS
)
1193 /* Set the group name */
1194 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1196 dwError
= RegSetValueExW(hServiceKey
,
1200 (LPBYTE
)lpLoadOrderGroup
,
1201 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1202 if (dwError
!= ERROR_SUCCESS
)
1206 if (lpdwTagId
!= NULL
)
1208 dwError
= RegSetValueExW(hServiceKey
,
1212 (LPBYTE
)&lpService
->dwTag
,
1214 if (dwError
!= ERROR_SUCCESS
)
1218 /* Write dependencies */
1219 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1221 dwError
= ScmWriteDependencies(hServiceKey
,
1223 dwDependenciesLength
);
1224 if (dwError
!= ERROR_SUCCESS
)
1228 if (lpPassword
!= NULL
)
1230 /* FIXME: Write password */
1233 dwError
= ScmCreateServiceHandle(lpService
,
1235 if (dwError
!= ERROR_SUCCESS
)
1238 dwError
= ScmCheckAccess(hServiceHandle
,
1240 if (dwError
!= ERROR_SUCCESS
)
1244 if (hServiceKey
!= NULL
)
1245 RegCloseKey(hServiceKey
);
1247 if (dwError
== ERROR_SUCCESS
)
1249 DPRINT("hService %lx\n", hServiceHandle
);
1250 *hService
= (unsigned long)hServiceHandle
;
1252 if (lpdwTagId
!= NULL
)
1253 *lpdwTagId
= lpService
->dwTag
;
1257 /* Release the display name buffer */
1258 if (lpService
->lpServiceName
!= NULL
)
1259 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1263 /* Remove the service handle */
1264 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
1267 if (lpService
!= NULL
)
1269 /* FIXME: remove the service entry */
1273 if (lpImagePath
!= NULL
)
1274 HeapFree(GetProcessHeap(), 0, lpImagePath
);
1276 DPRINT("ScmrCreateServiceW() done (Error %lu)\n", dwError
);
1284 ScmrEnumDependentServicesW(handle_t BindingHandle
,
1285 unsigned long hService
,
1286 DWORD dwServiceState
,
1287 unsigned char *lpServices
,
1289 DWORD
*pcbBytesNeeded
,
1290 DWORD
*lpServicesReturned
)
1292 DWORD dwError
= ERROR_SUCCESS
;
1294 DPRINT1("ScmrEnumDependentServicesW() called\n");
1295 *pcbBytesNeeded
= 0;
1296 *lpServicesReturned
= 0;
1298 DPRINT1("ScmrEnumDependentServicesW() done (Error %lu)\n", dwError
);
1306 ScmrEnumServicesStatusW(handle_t BindingHandle
,
1307 unsigned long hSCManager
,
1308 DWORD dwServiceType
,
1309 DWORD dwServiceState
,
1310 unsigned char *lpServices
,
1312 DWORD
*pcbBytesNeeded
,
1313 DWORD
*lpServicesReturned
,
1314 DWORD
*lpResumeHandle
)
1316 PMANAGER_HANDLE hManager
;
1318 DWORD dwError
= ERROR_SUCCESS
;
1319 PLIST_ENTRY ServiceEntry
;
1320 PSERVICE CurrentService
;
1322 DWORD dwRequiredSize
;
1323 DWORD dwServiceCount
;
1325 DWORD dwLastResumeCount
;
1326 LPENUM_SERVICE_STATUSW lpStatusPtr
;
1329 DPRINT("ScmrEnumServicesStatusW() called\n");
1332 return ERROR_SHUTDOWN_IN_PROGRESS
;
1334 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1335 if (hManager
->Handle
.Tag
!= MANAGER_TAG
)
1337 DPRINT1("Invalid manager handle!\n");
1338 return ERROR_INVALID_HANDLE
;
1341 /* Check access rights */
1342 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1343 SC_MANAGER_ENUMERATE_SERVICE
))
1345 DPRINT1("Insufficient access rights! 0x%lx\n",
1346 hManager
->Handle
.DesiredAccess
);
1347 return ERROR_ACCESS_DENIED
;
1350 *pcbBytesNeeded
= 0;
1351 *lpServicesReturned
= 0;
1353 dwLastResumeCount
= *lpResumeHandle
;
1355 /* FIXME: Lock the service list shared */
1357 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
1358 if (lpService
== NULL
)
1360 dwError
= ERROR_SUCCESS
;
1367 for (ServiceEntry
= &lpService
->ServiceListEntry
;
1368 ServiceEntry
!= &ServiceListHead
;
1369 ServiceEntry
= ServiceEntry
->Flink
)
1371 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
1375 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
1378 dwState
= SERVICE_ACTIVE
;
1379 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
1380 dwState
= SERVICE_INACTIVE
;
1382 if ((dwState
& dwServiceState
) == 0)
1385 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
1386 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
1387 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
1389 if (dwRequiredSize
+ dwSize
<= dwBufSize
)
1391 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
1392 dwRequiredSize
+= dwSize
;
1394 dwLastResumeCount
= CurrentService
->dwResumeCount
;
1398 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
1404 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
1405 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
1408 ServiceEntry
!= &ServiceListHead
;
1409 ServiceEntry
= ServiceEntry
->Flink
)
1411 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
1415 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
1418 dwState
= SERVICE_ACTIVE
;
1419 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
1420 dwState
= SERVICE_INACTIVE
;
1422 if ((dwState
& dwServiceState
) == 0)
1425 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
1426 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
1427 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
1429 dwError
= ERROR_MORE_DATA
;
1432 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
1434 *lpResumeHandle
= dwLastResumeCount
;
1435 *lpServicesReturned
= dwServiceCount
;
1436 *pcbBytesNeeded
= dwRequiredSize
;
1438 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpServices
;
1439 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpServices
+
1440 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
1443 for (ServiceEntry
= &lpService
->ServiceListEntry
;
1444 ServiceEntry
!= &ServiceListHead
;
1445 ServiceEntry
= ServiceEntry
->Flink
)
1447 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
1451 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
1454 dwState
= SERVICE_ACTIVE
;
1455 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
1456 dwState
= SERVICE_INACTIVE
;
1458 if ((dwState
& dwServiceState
) == 0)
1461 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
1462 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
1463 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
1465 if (dwRequiredSize
+ dwSize
<= dwBufSize
)
1467 /* Copy the service name */
1469 CurrentService
->lpServiceName
);
1470 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpServices
);
1471 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
1473 /* Copy the display name */
1475 CurrentService
->lpDisplayName
);
1476 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpServices
);
1477 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
1479 /* Copy the status information */
1480 memcpy(&lpStatusPtr
->ServiceStatus
,
1481 &CurrentService
->Status
,
1482 sizeof(SERVICE_STATUS
));
1485 dwRequiredSize
+= dwSize
;
1495 /* FIXME: Unlock the service list */
1497 DPRINT("ScmrEnumServicesStatusW() done (Error %lu)\n", dwError
);
1505 ScmrOpenSCManagerW(handle_t BindingHandle
,
1506 wchar_t *lpMachineName
,
1507 wchar_t *lpDatabaseName
,
1508 DWORD dwDesiredAccess
,
1509 unsigned long *hScm
)
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
);
1522 return ERROR_SHUTDOWN_IN_PROGRESS
;
1524 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
1526 if (dwError
!= ERROR_SUCCESS
)
1528 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
1532 /* Check the desired access */
1533 dwError
= ScmCheckAccess(hHandle
,
1534 dwDesiredAccess
| SC_MANAGER_CONNECT
);
1535 if (dwError
!= ERROR_SUCCESS
)
1537 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
1538 HeapFree(GetProcessHeap(), 0, hHandle
);
1542 *hScm
= (unsigned long)hHandle
;
1543 DPRINT("*hScm = %x\n", *hScm
);
1545 DPRINT("ScmrOpenSCManagerW() done\n");
1547 return ERROR_SUCCESS
;
1553 ScmrOpenServiceW(handle_t BindingHandle
,
1554 unsigned long hSCManager
,
1555 wchar_t *lpServiceName
,
1556 DWORD dwDesiredAccess
,
1557 unsigned long *hService
)
1560 PMANAGER_HANDLE hManager
;
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
);
1571 return ERROR_SHUTDOWN_IN_PROGRESS
;
1573 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1574 if (hManager
->Handle
.Tag
!= MANAGER_TAG
)
1576 DPRINT1("Invalid manager handle!\n");
1577 return ERROR_INVALID_HANDLE
;
1580 /* FIXME: Lock the service list */
1582 /* Get service database entry */
1583 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1584 if (lpService
== NULL
)
1586 DPRINT("Could not find a service!\n");
1587 return ERROR_SERVICE_DOES_NOT_EXIST
;
1590 /* Create a service handle */
1591 dwError
= ScmCreateServiceHandle(lpService
,
1593 if (dwError
!= ERROR_SUCCESS
)
1595 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
1599 /* Check the desired access */
1600 dwError
= ScmCheckAccess(hHandle
,
1602 if (dwError
!= ERROR_SUCCESS
)
1604 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
1605 HeapFree(GetProcessHeap(), 0, hHandle
);
1609 *hService
= (unsigned long)hHandle
;
1610 DPRINT("*hService = %x\n", *hService
);
1612 DPRINT("ScmrOpenServiceW() done\n");
1614 return ERROR_SUCCESS
;
1620 ScmrQueryServiceConfigW(handle_t BindingHandle
,
1621 unsigned long hService
,
1622 unsigned char *lpServiceConfig
,
1624 DWORD
*pcbBytesNeeded
)
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
;
1636 DPRINT("ScmrQueryServiceConfigW() called\n");
1639 return ERROR_SHUTDOWN_IN_PROGRESS
;
1641 hSvc
= (PSERVICE_HANDLE
)hService
;
1642 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1644 DPRINT1("Invalid handle tag!\n");
1645 return ERROR_INVALID_HANDLE
;
1648 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1649 SERVICE_QUERY_CONFIG
))
1651 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1652 return ERROR_ACCESS_DENIED
;
1655 lpService
= hSvc
->ServiceEntry
;
1656 if (lpService
== NULL
)
1658 DPRINT1("lpService == NULL!\n");
1659 return ERROR_INVALID_HANDLE
;
1662 /* FIXME: Lock the service database shared */
1664 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
1667 if (dwError
!= ERROR_SUCCESS
)
1670 dwError
= ScmReadString(hServiceKey
,
1673 if (dwError
!= ERROR_SUCCESS
)
1676 ScmReadString(hServiceKey
,
1678 &lpServiceStartName
);
1680 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
1682 if (lpImagePath
!= NULL
)
1683 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1685 if (lpService
->lpGroup
!= NULL
)
1686 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
1688 /* FIXME: Add Dependencies length*/
1690 if (lpServiceStartName
!= NULL
)
1691 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
1693 if (lpService
->lpDisplayName
!= NULL
)
1694 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
1696 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
1698 dwError
= ERROR_INSUFFICIENT_BUFFER
;
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
;
1708 lpStr
= (LPWSTR
)(lpConfig
+ 1);
1710 if (lpImagePath
!= NULL
)
1712 wcscpy(lpStr
, lpImagePath
);
1713 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
1714 lpStr
+= (wcslen(lpImagePath
) + 1);
1718 lpConfig
->lpBinaryPathName
= NULL
;
1721 if (lpService
->lpGroup
!= NULL
)
1723 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
1724 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
1725 lpStr
+= (wcslen(lpService
->lpGroup
->lpGroupName
) + 1);
1729 lpConfig
->lpLoadOrderGroup
= NULL
;
1732 /* FIXME: Append Dependencies */
1733 lpConfig
->lpDependencies
= NULL
;
1735 if (lpServiceStartName
!= NULL
)
1737 wcscpy(lpStr
, lpServiceStartName
);
1738 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
1739 lpStr
+= (wcslen(lpServiceStartName
) + 1);
1743 lpConfig
->lpServiceStartName
= NULL
;
1746 if (lpService
->lpDisplayName
!= NULL
)
1748 wcscpy(lpStr
, lpService
->lpDisplayName
);
1749 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
1753 lpConfig
->lpDisplayName
= NULL
;
1757 if (pcbBytesNeeded
!= NULL
)
1758 *pcbBytesNeeded
= dwRequiredSize
;
1761 if (lpImagePath
!= NULL
)
1762 HeapFree(GetProcessHeap(), 0, lpImagePath
);
1764 if (lpServiceStartName
!= NULL
)
1765 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
1767 if (hServiceKey
!= NULL
)
1768 RegCloseKey(hServiceKey
);
1770 /* FIXME: Unlock the service database */
1772 DPRINT("ScmrQueryServiceConfigW() done\n");
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] */
1786 DPRINT1("ScmrQueryServiceLockStatusW() called\n");
1787 return ERROR_CALL_NOT_IMPLEMENTED
;
1793 ScmrStartServiceW(handle_t BindingHandle
,
1794 unsigned long hService
,
1795 DWORD dwNumServiceArgs
,
1796 unsigned char *lpServiceArgBuffer
,
1799 DWORD dwError
= ERROR_SUCCESS
;
1800 PSERVICE_HANDLE hSvc
;
1801 PSERVICE lpService
= NULL
;
1803 DPRINT("ScmrStartServiceW() called\n");
1806 return ERROR_SHUTDOWN_IN_PROGRESS
;
1808 hSvc
= (PSERVICE_HANDLE
)hService
;
1809 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1811 DPRINT1("Invalid handle tag!\n");
1812 return ERROR_INVALID_HANDLE
;
1815 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1818 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1819 return ERROR_ACCESS_DENIED
;
1822 lpService
= hSvc
->ServiceEntry
;
1823 if (lpService
== NULL
)
1825 DPRINT1("lpService == NULL!\n");
1826 return ERROR_INVALID_HANDLE
;
1829 if (lpService
->dwStartType
== SERVICE_DISABLED
)
1830 return ERROR_SERVICE_DISABLED
;
1832 if (lpService
->bDeleted
)
1833 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1835 /* Start the service */
1836 dwError
= ScmStartService(lpService
, (LPWSTR
)lpServiceArgBuffer
);
1844 ScmrGetServiceDisplayNameW(handle_t BindingHandle
,
1845 unsigned long hSCManager
,
1846 wchar_t *lpServiceName
,
1847 wchar_t *lpDisplayName
, /* [out, unique] */
1850 // PMANAGER_HANDLE hManager;
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
);
1861 // hManager = (PMANAGER_HANDLE)hSCManager;
1862 // if (hManager->Handle.Tag != MANAGER_TAG)
1864 // DPRINT1("Invalid manager handle!\n");
1865 // return ERROR_INVALID_HANDLE;
1868 /* Get service database entry */
1869 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1870 if (lpService
== NULL
)
1872 DPRINT1("Could not find a service!\n");
1873 return ERROR_SERVICE_DOES_NOT_EXIST
;
1876 dwLength
= wcslen(lpService
->lpDisplayName
) + 1;
1878 if (lpDisplayName
!= NULL
&&
1879 *lpcchBuffer
>= dwLength
)
1881 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
1884 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
1886 *lpcchBuffer
= dwLength
;
1894 ScmrGetServiceKeyNameW(handle_t BindingHandle
,
1895 unsigned long hSCManager
,
1896 wchar_t *lpDisplayName
,
1897 wchar_t *lpServiceName
, /* [out, unique] */
1900 // PMANAGER_HANDLE hManager;
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
);
1911 // hManager = (PMANAGER_HANDLE)hSCManager;
1912 // if (hManager->Handle.Tag != MANAGER_TAG)
1914 // DPRINT1("Invalid manager handle!\n");
1915 // return ERROR_INVALID_HANDLE;
1918 /* Get service database entry */
1919 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
1920 if (lpService
== NULL
)
1922 DPRINT1("Could not find a service!\n");
1923 return ERROR_SERVICE_DOES_NOT_EXIST
;
1926 dwLength
= wcslen(lpService
->lpServiceName
) + 1;
1928 if (lpServiceName
!= NULL
&&
1929 *lpcchBuffer
>= dwLength
)
1931 wcscpy(lpServiceName
, lpService
->lpServiceName
);
1934 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
1936 *lpcchBuffer
= dwLength
;
1944 ScmrSetServiceBitsA(handle_t BindingHandle
,
1945 SERVICE_STATUS_HANDLE hServiceStatus
,
1946 DWORD dwServiceBits
,
1948 BOOL bUpdateImmediately
,
1951 DPRINT1("ScmrSetServiceBitsA() is unimplemented\n");
1952 return ERROR_CALL_NOT_IMPLEMENTED
;
1958 ScmrChangeServiceConfigA(handle_t BiningHandle
,
1959 unsigned long hService
,
1960 DWORD dwServiceType
,
1962 DWORD dwErrorControl
,
1963 char *lpBinaryPathName
,
1964 char *lpLoadOrderGroup
,
1966 char *lpDependencies
,
1967 DWORD dwDependenciesLength
,
1968 char *lpServiceStartName
,
1970 DWORD dwPasswordLength
,
1971 char *lpDisplayName
)
1973 DPRINT1("ScmrChangeServiceConfigA() is unimplemented\n");
1974 return ERROR_CALL_NOT_IMPLEMENTED
;
1980 ScmrCreateServiceA(handle_t BindingHandle
,
1981 unsigned long hSCManager
,
1982 char *lpServiceName
,
1983 char *lpDisplayName
,
1984 DWORD dwDesiredAccess
,
1985 DWORD dwServiceType
,
1987 DWORD dwErrorControl
,
1988 char *lpBinaryPathName
,
1989 char *lpLoadOrderGroup
,
1990 DWORD
*lpdwTagId
, /* in, out */
1991 char *lpDependencies
,
1992 DWORD dwDependenciesLength
,
1993 char *lpServiceStartName
,
1995 DWORD dwPasswordLength
,
1996 unsigned long *hService
) /* out */
1998 DPRINT1("ScmrCreateServiceA() is unimplemented\n");
1999 return ERROR_CALL_NOT_IMPLEMENTED
;
2005 ScmrEnumDependentServicesA(handle_t BindingHandle
,
2006 unsigned long hService
,
2007 DWORD dwServiceState
,
2008 unsigned char *lpServices
,
2010 DWORD
*pcbBytesNeeded
,
2011 DWORD
*lpServicesReturned
)
2013 DPRINT1("ScmrEnumDependentServicesA() is unimplemented\n");
2014 *pcbBytesNeeded
= 0;
2015 *lpServicesReturned
= 0;
2016 return ERROR_CALL_NOT_IMPLEMENTED
;
2022 ScmrEnumServicesStatusA(handle_t BindingHandle
,
2023 unsigned long hSCManager
,
2024 DWORD dwServiceType
,
2025 DWORD dwServiceState
,
2026 unsigned char *lpServices
,
2028 DWORD
*pcbBytesNeeded
,
2029 DWORD
*lpServicesReturned
,
2030 unsigned long *lpResumeHandle
)
2032 DPRINT1("ScmrEnumServicesAtatusA() is unimplemented\n");
2033 return ERROR_CALL_NOT_IMPLEMENTED
;
2039 ScmrOpenSCManagerA(handle_t BindingHandle
,
2040 char *lpMachineName
,
2041 char *lpDatabaseName
,
2042 DWORD dwDesiredAccess
,
2043 unsigned long *hScm
)
2045 UNICODE_STRING MachineName
;
2046 UNICODE_STRING DatabaseName
;
2049 DPRINT("ScmrOpenSCManagerA() called\n");
2052 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
2056 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
2059 dwError
= ScmrOpenSCManagerW(BindingHandle
,
2060 lpMachineName
? MachineName
.Buffer
: NULL
,
2061 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
2066 RtlFreeUnicodeString(&MachineName
);
2069 RtlFreeUnicodeString(&DatabaseName
);
2077 ScmrOpenServiceA(handle_t BindingHandle
,
2078 unsigned long hSCManager
,
2079 char *lpServiceName
,
2080 DWORD dwDesiredAccess
,
2081 unsigned long *hService
)
2083 UNICODE_STRING ServiceName
;
2086 DPRINT("ScmrOpenServiceA() called\n");
2088 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
2091 dwError
= ScmrOpenServiceW(BindingHandle
,
2097 RtlFreeUnicodeString(&ServiceName
);
2105 ScmrQueryServiceConfigA(handle_t BindingHandle
,
2106 unsigned long hService
,
2107 unsigned char *lpServiceConfig
,
2109 DWORD
*pcbBytesNeeded
)
2111 DPRINT1("ScmrQueryServiceConfigA() is unimplemented\n");
2112 return ERROR_CALL_NOT_IMPLEMENTED
;
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] */
2124 DPRINT1("ScmrQueryServiceLockStatusA() called\n");
2125 return ERROR_CALL_NOT_IMPLEMENTED
;
2131 ScmrStartServiceA(handle_t BindingHandle
,
2132 unsigned long hService
,
2133 DWORD dwNumServiceArgs
,
2134 unsigned char *lpServiceArgBuffer
,
2137 DWORD dwError
= ERROR_SUCCESS
;
2138 PSERVICE_HANDLE hSvc
;
2139 PSERVICE lpService
= NULL
;
2141 DPRINT1("ScmrStartServiceA() called\n");
2144 return ERROR_SHUTDOWN_IN_PROGRESS
;
2146 hSvc
= (PSERVICE_HANDLE
)hService
;
2147 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2149 DPRINT1("Invalid handle tag!\n");
2150 return ERROR_INVALID_HANDLE
;
2153 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2156 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2157 return ERROR_ACCESS_DENIED
;
2160 lpService
= hSvc
->ServiceEntry
;
2161 if (lpService
== NULL
)
2163 DPRINT1("lpService == NULL!\n");
2164 return ERROR_INVALID_HANDLE
;
2167 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2168 return ERROR_SERVICE_DISABLED
;
2170 if (lpService
->bDeleted
)
2171 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2173 /* FIXME: Convert argument vector to Unicode */
2175 /* Start the service */
2176 dwError
= ScmStartService(lpService
, NULL
);
2178 /* FIXME: Free argument vector */
2186 ScmrGetServiceDisplayNameA(handle_t BindingHandle
,
2187 unsigned long hSCManager
,
2188 char *lpServiceName
,
2189 char *lpDisplayName
, /* [out, unique] */
2192 DPRINT1("ScmrGetServiceDisplayNameA() is unimplemented\n");
2193 return ERROR_CALL_NOT_IMPLEMENTED
;
2199 ScmrGetServiceKeyNameA(handle_t BindingHandle
,
2200 unsigned long hSCManager
,
2201 char *lpDisplayName
,
2202 char *lpServiceName
, /* [out, unique] */
2205 DPRINT1("ScmrGetServiceKeyNameA() is unimplemented\n");
2206 return ERROR_CALL_NOT_IMPLEMENTED
;
2212 ScmrGetCurrentGroupStateW(handle_t BindingHandle
)
2214 DPRINT1("ScmrGetCurrentGroupStateW() is unimplemented\n");
2215 return ERROR_CALL_NOT_IMPLEMENTED
;
2221 ScmrEnumServiceGroupW(handle_t BindingHandle
)
2223 DPRINT1("ScmrEnumServiceGroupW() is unimplemented\n");
2224 return ERROR_CALL_NOT_IMPLEMENTED
;
2230 ScmrChangeServiceConfig2A(handle_t BindingHandle
,
2231 unsigned long hService
,
2233 unsigned char *lpInfo
,
2236 DPRINT1("ScmrChangeServiceConfig2A() is unimplemented\n");
2237 return ERROR_CALL_NOT_IMPLEMENTED
;
2243 ScmrChangeServiceConfig2W(handle_t BindingHandle
,
2244 unsigned long hService
,
2246 unsigned char *lpInfo
,
2249 DWORD dwError
= ERROR_SUCCESS
;
2250 PSERVICE_HANDLE hSvc
;
2251 PSERVICE lpService
= NULL
;
2252 HKEY hServiceKey
= NULL
;
2254 DPRINT("ScmrChangeServiceConfig2W() called\n");
2255 DPRINT("dwInfoLevel = %lu\n", dwInfoLevel
);
2256 DPRINT("dwInfoSize = %lu\n", dwInfoSize
);
2259 return ERROR_SHUTDOWN_IN_PROGRESS
;
2261 hSvc
= (PSERVICE_HANDLE
)hService
;
2262 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2264 DPRINT1("Invalid handle tag!\n");
2265 return ERROR_INVALID_HANDLE
;
2268 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2269 SERVICE_CHANGE_CONFIG
))
2271 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2272 return ERROR_ACCESS_DENIED
;
2275 lpService
= hSvc
->ServiceEntry
;
2276 if (lpService
== NULL
)
2278 DPRINT1("lpService == NULL!\n");
2279 return ERROR_INVALID_HANDLE
;
2282 /* FIXME: Lock database exclusively */
2284 if (lpService
->bDeleted
)
2286 /* FIXME: Unlock database */
2287 DPRINT1("The service has already been marked for delete!\n");
2288 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2291 /* Open the service key */
2292 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2295 if (dwError
!= ERROR_SUCCESS
)
2298 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
2300 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
2302 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpInfo
;
2303 lpServiceDescription
->lpDescription
= (LPWSTR
)(lpInfo
+ sizeof(LPSERVICE_DESCRIPTIONW
));
2305 if (lpServiceDescription
!= NULL
&&
2306 lpServiceDescription
->lpDescription
!= NULL
)
2308 RegSetValueExW(hServiceKey
,
2312 (LPBYTE
)lpServiceDescription
->lpDescription
,
2313 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
2315 if (dwError
!= ERROR_SUCCESS
)
2319 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
2321 DPRINT1("SERVICE_CONFIG_FAILURE_ACTIONS not implemented\n");
2322 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
2327 /* FIXME: Unlock database */
2328 if (hServiceKey
!= NULL
)
2329 RegCloseKey(hServiceKey
);
2331 DPRINT("ScmrChangeServiceConfig2W() done (Error %lu)\n", dwError
);
2339 ScmrQueryServiceConfig2A(handle_t BindingHandle
,
2340 unsigned long hService
,
2342 unsigned char *lpBuffer
,
2344 DWORD
*pcbBytesNeeded
)
2346 DPRINT1("ScmrQueryServiceConfig2A() is unimplemented\n");
2347 return ERROR_CALL_NOT_IMPLEMENTED
;
2353 ScmrQueryServiceConfig2W(handle_t BindingHandle
,
2354 unsigned long hService
,
2356 unsigned char *lpBuffer
,
2358 DWORD
*pcbBytesNeeded
)
2360 DWORD dwError
= ERROR_SUCCESS
;
2361 PSERVICE_HANDLE hSvc
;
2362 PSERVICE lpService
= NULL
;
2363 HKEY hServiceKey
= NULL
;
2364 DWORD dwRequiredSize
;
2365 LPWSTR lpDescription
= NULL
;
2367 DPRINT("ScmrQueryServiceConfig2W() called\n");
2370 return ERROR_SHUTDOWN_IN_PROGRESS
;
2372 hSvc
= (PSERVICE_HANDLE
)hService
;
2373 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2375 DPRINT1("Invalid handle tag!\n");
2376 return ERROR_INVALID_HANDLE
;
2379 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2380 SERVICE_QUERY_CONFIG
))
2382 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2383 return ERROR_ACCESS_DENIED
;
2386 lpService
= hSvc
->ServiceEntry
;
2387 if (lpService
== NULL
)
2389 DPRINT1("lpService == NULL!\n");
2390 return ERROR_INVALID_HANDLE
;
2393 /* FIXME: Lock the service database shared */
2395 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2398 if (dwError
!= ERROR_SUCCESS
)
2401 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
2403 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
2406 dwError
= ScmReadString(hServiceKey
,
2409 if (dwError
!= ERROR_SUCCESS
)
2412 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
2414 if (cbBufSize
< dwRequiredSize
)
2416 *pcbBytesNeeded
= dwRequiredSize
;
2417 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2422 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
2423 wcscpy(lpStr
, lpDescription
);
2424 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
2427 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
2429 DPRINT1("SERVICE_CONFIG_FAILURE_ACTIONS not implemented\n");
2430 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
2435 if (lpDescription
!= NULL
)
2436 HeapFree(GetProcessHeap(), 0, lpDescription
);
2438 if (hServiceKey
!= NULL
)
2439 RegCloseKey(hServiceKey
);
2441 /* FIXME: Unlock database */
2443 DPRINT("ScmrQueryServiceConfig2W() done (Error %lu)\n", dwError
);
2451 ScmrQueryServiceStatusEx(handle_t BindingHandle
,
2452 unsigned long hService
,
2453 SC_STATUS_TYPE InfoLevel
,
2454 unsigned char *lpBuffer
, /* out */
2456 DWORD
*pcbBytesNeeded
) /* out */
2458 LPSERVICE_STATUS_PROCESS lpStatus
;
2459 PSERVICE_HANDLE hSvc
;
2462 DPRINT("ScmrQueryServiceStatusEx() called\n");
2465 return ERROR_SHUTDOWN_IN_PROGRESS
;
2467 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
2468 return ERROR_INVALID_LEVEL
;
2470 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
2472 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
2473 return ERROR_INSUFFICIENT_BUFFER
;
2475 hSvc
= (PSERVICE_HANDLE
)hService
;
2476 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2478 DPRINT1("Invalid handle tag!\n");
2479 return ERROR_INVALID_HANDLE
;
2482 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2483 SERVICE_QUERY_STATUS
))
2485 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2486 return ERROR_ACCESS_DENIED
;
2489 lpService
= hSvc
->ServiceEntry
;
2490 if (lpService
== NULL
)
2492 DPRINT1("lpService == NULL!\n");
2493 return ERROR_INVALID_HANDLE
;
2496 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
2498 /* Return service status information */
2499 RtlCopyMemory(lpStatus
,
2501 sizeof(SERVICE_STATUS
));
2503 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
2504 lpStatus
->dwServiceFlags
= 0; /* FIXME */
2506 return ERROR_SUCCESS
;
2512 ScmrEnumServicesStatusExA(handle_t BindingHandle
,
2513 unsigned long hSCManager
,
2514 SC_STATUS_TYPE InfoLevel
,
2515 DWORD dwServiceType
,
2516 DWORD dwServiceState
,
2517 unsigned char *lpServices
,
2519 DWORD
*pcbBytesNeeded
,
2520 DWORD
*lpServicesReturned
,
2521 unsigned long *lpResumeHandle
,
2524 DPRINT1("ScmrEnumServicesStatusExA() is unimplemented\n");
2525 *pcbBytesNeeded
= 0;
2526 *lpServicesReturned
= 0;
2527 return ERROR_CALL_NOT_IMPLEMENTED
;
2533 ScmrEnumServicesStatusExW(handle_t BindingHandle
,
2534 unsigned long hSCManager
,
2535 SC_ENUM_TYPE InfoLevel
,
2536 DWORD dwServiceType
,
2537 DWORD dwServiceState
,
2538 unsigned char *lpServices
,
2540 DWORD
*pcbBytesNeeded
,
2541 DWORD
*lpServicesReturned
,
2542 DWORD
*lpResumeHandle
,
2543 wchar_t *pszGroupName
)
2545 PMANAGER_HANDLE hManager
;
2547 DWORD dwError
= ERROR_SUCCESS
;
2548 PLIST_ENTRY ServiceEntry
;
2549 PSERVICE CurrentService
;
2551 DWORD dwRequiredSize
;
2552 DWORD dwServiceCount
;
2554 DWORD dwLastResumeCount
;
2555 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
2558 DPRINT("ScmrEnumServicesStatusExW() called\n");
2561 return ERROR_SHUTDOWN_IN_PROGRESS
;
2563 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
2564 return ERROR_INVALID_LEVEL
;
2566 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2567 if (hManager
->Handle
.Tag
!= MANAGER_TAG
)
2569 DPRINT1("Invalid manager handle!\n");
2570 return ERROR_INVALID_HANDLE
;
2573 /* Check access rights */
2574 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2575 SC_MANAGER_ENUMERATE_SERVICE
))
2577 DPRINT1("Insufficient access rights! 0x%lx\n",
2578 hManager
->Handle
.DesiredAccess
);
2579 return ERROR_ACCESS_DENIED
;
2582 *pcbBytesNeeded
= 0;
2583 *lpServicesReturned
= 0;
2585 dwLastResumeCount
= *lpResumeHandle
;
2587 /* Lock the service list shared */
2589 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2590 if (lpService
== NULL
)
2592 dwError
= ERROR_SUCCESS
;
2599 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2600 ServiceEntry
!= &ServiceListHead
;
2601 ServiceEntry
= ServiceEntry
->Flink
)
2603 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2607 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2610 dwState
= SERVICE_ACTIVE
;
2611 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2612 dwState
= SERVICE_INACTIVE
;
2614 if ((dwState
& dwServiceState
) == 0)
2619 if (*pszGroupName
== 0)
2621 if (CurrentService
->lpGroup
!= NULL
)
2626 if ((CurrentService
->lpGroup
== NULL
) ||
2627 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
2632 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
2633 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2634 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2636 if (dwRequiredSize
+ dwSize
<= dwBufSize
)
2638 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2639 dwRequiredSize
+= dwSize
;
2641 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2645 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2651 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2652 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2655 ServiceEntry
!= &ServiceListHead
;
2656 ServiceEntry
= ServiceEntry
->Flink
)
2658 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2662 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2665 dwState
= SERVICE_ACTIVE
;
2666 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2667 dwState
= SERVICE_INACTIVE
;
2669 if ((dwState
& dwServiceState
) == 0)
2674 if (*pszGroupName
== 0)
2676 if (CurrentService
->lpGroup
!= NULL
)
2681 if ((CurrentService
->lpGroup
== NULL
) ||
2682 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
2687 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
2688 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2689 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2691 dwError
= ERROR_MORE_DATA
;
2694 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2696 *lpResumeHandle
= dwLastResumeCount
;
2697 *lpServicesReturned
= dwServiceCount
;
2698 *pcbBytesNeeded
= dwRequiredSize
;
2700 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpServices
;
2701 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpServices
+
2702 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
2705 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2706 ServiceEntry
!= &ServiceListHead
;
2707 ServiceEntry
= ServiceEntry
->Flink
)
2709 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2713 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2716 dwState
= SERVICE_ACTIVE
;
2717 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2718 dwState
= SERVICE_INACTIVE
;
2720 if ((dwState
& dwServiceState
) == 0)
2725 if (*pszGroupName
== 0)
2727 if (CurrentService
->lpGroup
!= NULL
)
2732 if ((CurrentService
->lpGroup
== NULL
) ||
2733 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
2738 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
2739 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2740 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2742 if (dwRequiredSize
+ dwSize
<= dwBufSize
)
2744 /* Copy the service name */
2746 CurrentService
->lpServiceName
);
2747 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpServices
);
2748 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2750 /* Copy the display name */
2752 CurrentService
->lpDisplayName
);
2753 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpServices
);
2754 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
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 */
2764 dwRequiredSize
+= dwSize
;
2774 /* Unlock the service list */
2776 DPRINT("ScmrEnumServicesStatusExW() done (Error %lu)\n", dwError
);
2783 /* ScmrSendTSMessage */
2786 void __RPC_FAR
* __RPC_USER
midl_user_allocate(size_t len
)
2788 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
2792 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
2794 HeapFree(GetProcessHeap(), 0, ptr
);