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 ****************************************************************/
21 /* GLOBALS *****************************************************************/
23 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
24 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
26 typedef struct _SCMGR_HANDLE
34 typedef struct _MANAGER_HANDLE
38 /* FIXME: Insert more data here */
40 WCHAR DatabaseName
[1];
41 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
44 typedef struct _SERVICE_HANDLE
49 PSERVICE ServiceEntry
;
51 /* FIXME: Insert more data here */
53 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
56 #define SC_MANAGER_READ \
57 (STANDARD_RIGHTS_READ | \
58 SC_MANAGER_QUERY_LOCK_STATUS | \
59 SC_MANAGER_ENUMERATE_SERVICE)
61 #define SC_MANAGER_WRITE \
62 (STANDARD_RIGHTS_WRITE | \
63 SC_MANAGER_MODIFY_BOOT_CONFIG | \
64 SC_MANAGER_CREATE_SERVICE)
66 #define SC_MANAGER_EXECUTE \
67 (STANDARD_RIGHTS_EXECUTE | \
69 SC_MANAGER_ENUMERATE_SERVICE | \
70 SC_MANAGER_CONNECT | \
71 SC_MANAGER_CREATE_SERVICE)
74 #define SERVICE_READ \
75 (STANDARD_RIGHTS_READ | \
76 SERVICE_INTERROGATE | \
77 SERVICE_ENUMERATE_DEPENDENTS | \
78 SERVICE_QUERY_STATUS | \
81 #define SERVICE_WRITE \
82 (STANDARD_RIGHTS_WRITE | \
83 SERVICE_CHANGE_CONFIG)
85 #define SERVICE_EXECUTE \
86 (STANDARD_RIGHTS_EXECUTE | \
87 SERVICE_USER_DEFINED_CONTROL | \
88 SERVICE_PAUSE_CONTINUE | \
93 /* VARIABLES ***************************************************************/
95 static GENERIC_MAPPING
96 ScmManagerMapping
= {SC_MANAGER_READ
,
99 SC_MANAGER_ALL_ACCESS
};
101 static GENERIC_MAPPING
102 ScmServiceMapping
= {SERVICE_READ
,
105 SC_MANAGER_ALL_ACCESS
};
108 /* FUNCTIONS ***************************************************************/
111 ScmStartRpcServer(VOID
)
115 DPRINT("ScmStartRpcServer() called");
117 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
121 if (Status
!= RPC_S_OK
)
123 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
127 Status
= RpcServerRegisterIf(svcctl_ServerIfHandle
,
130 if (Status
!= RPC_S_OK
)
132 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
136 Status
= RpcServerListen(1, 20, TRUE
);
137 if (Status
!= RPC_S_OK
)
139 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
143 DPRINT("ScmStartRpcServer() done");
148 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
153 if (lpDatabaseName
== NULL
)
154 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
156 Ptr
= (MANAGER_HANDLE
*) HeapAlloc(GetProcessHeap(),
158 sizeof(MANAGER_HANDLE
) + wcslen(lpDatabaseName
) * sizeof(WCHAR
));
160 return ERROR_NOT_ENOUGH_MEMORY
;
162 Ptr
->Handle
.Tag
= MANAGER_TAG
;
163 Ptr
->Handle
.RefCount
= 1;
165 /* FIXME: initialize more data here */
167 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
169 *Handle
= (SC_HANDLE
)Ptr
;
171 return ERROR_SUCCESS
;
176 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
181 Ptr
= (SERVICE_HANDLE
*) HeapAlloc(GetProcessHeap(),
183 sizeof(SERVICE_HANDLE
));
185 return ERROR_NOT_ENOUGH_MEMORY
;
187 Ptr
->Handle
.Tag
= SERVICE_TAG
;
188 Ptr
->Handle
.RefCount
= 1;
190 /* FIXME: initialize more data here */
191 Ptr
->ServiceEntry
= lpServiceEntry
;
193 *Handle
= (SC_HANDLE
)Ptr
;
195 return ERROR_SUCCESS
;
200 ScmCheckAccess(SC_HANDLE Handle
,
201 DWORD dwDesiredAccess
)
203 PMANAGER_HANDLE hMgr
;
205 hMgr
= (PMANAGER_HANDLE
)Handle
;
206 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
208 RtlMapGenericMask(&dwDesiredAccess
,
211 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
213 return ERROR_SUCCESS
;
215 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
217 RtlMapGenericMask(&dwDesiredAccess
,
220 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
222 return ERROR_SUCCESS
;
225 return ERROR_INVALID_HANDLE
;
230 ScmAssignNewTag(PSERVICE lpService
)
233 DPRINT("Assigning new tag to service %S\n", lpService
->lpServiceName
);
234 lpService
->dwTag
= 0;
235 return ERROR_SUCCESS
;
241 ScmrCloseServiceHandle(handle_t BindingHandle
,
242 unsigned int hScObject
)
244 PMANAGER_HANDLE hManager
;
246 DPRINT("ScmrCloseServiceHandle() called\n");
248 DPRINT("hScObject = %X\n", hScObject
);
251 return ERROR_INVALID_HANDLE
;
253 hManager
= (PMANAGER_HANDLE
)hScObject
;
254 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
256 DPRINT("Found manager handle\n");
258 hManager
->Handle
.RefCount
--;
259 if (hManager
->Handle
.RefCount
== 0)
261 /* FIXME: add cleanup code */
263 HeapFree(GetProcessHeap(), 0, hManager
);
266 DPRINT("ScmrCloseServiceHandle() done\n");
267 return ERROR_SUCCESS
;
269 else if (hManager
->Handle
.Tag
== SERVICE_TAG
)
271 DPRINT("Found service handle\n");
273 hManager
->Handle
.RefCount
--;
274 if (hManager
->Handle
.RefCount
== 0)
276 /* FIXME: add cleanup code */
278 HeapFree(GetProcessHeap(), 0, hManager
);
281 DPRINT("ScmrCloseServiceHandle() done\n");
282 return ERROR_SUCCESS
;
285 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
287 return ERROR_INVALID_HANDLE
;
293 ScmrControlService(handle_t BindingHandle
,
294 unsigned int hService
,
295 unsigned long dwControl
,
296 LPSERVICE_STATUS lpServiceStatus
)
298 PSERVICE_HANDLE hSvc
;
300 ACCESS_MASK DesiredAccess
;
301 DWORD dwError
= ERROR_SUCCESS
;
303 DPRINT("ScmrControlService() called\n");
306 return ERROR_SHUTDOWN_IN_PROGRESS
;
308 /* Check the service handle */
309 hSvc
= (PSERVICE_HANDLE
)hService
;
310 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
312 DPRINT1("Invalid handle tag!\n");
313 return ERROR_INVALID_HANDLE
;
316 /* Check access rights */
319 case SERVICE_CONTROL_STOP
:
320 DesiredAccess
= SERVICE_STOP
;
323 case SERVICE_CONTROL_PAUSE
:
324 case SERVICE_CONTROL_CONTINUE
:
325 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
328 case SERVICE_INTERROGATE
:
329 DesiredAccess
= SERVICE_INTERROGATE
;
333 if (dwControl
>= 128 && dwControl
<= 255)
334 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
336 DesiredAccess
= SERVICE_QUERY_CONFIG
|
337 SERVICE_CHANGE_CONFIG
|
338 SERVICE_QUERY_STATUS
|
340 SERVICE_PAUSE_CONTINUE
;
344 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
346 return ERROR_ACCESS_DENIED
;
348 /* Check the service entry point */
349 lpService
= hSvc
->ServiceEntry
;
350 if (lpService
== NULL
)
352 DPRINT1("lpService == NULL!\n");
353 return ERROR_INVALID_HANDLE
;
356 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
358 /* Send control code to the driver */
359 dwError
= ScmControlDriver(lpService
,
365 /* Send control code to the service */
366 dwError
= ScmControlService(lpService
,
371 /* Return service status information */
372 RtlCopyMemory(lpServiceStatus
,
374 sizeof(SERVICE_STATUS
));
382 ScmrDeleteService(handle_t BindingHandle
,
383 unsigned int hService
)
385 PSERVICE_HANDLE hSvc
;
389 DPRINT("ScmrDeleteService() called\n");
392 return ERROR_SHUTDOWN_IN_PROGRESS
;
394 hSvc
= (PSERVICE_HANDLE
)hService
;
395 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
396 return ERROR_INVALID_HANDLE
;
398 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
399 STANDARD_RIGHTS_REQUIRED
))
400 return ERROR_ACCESS_DENIED
;
402 lpService
= hSvc
->ServiceEntry
;
403 if (lpService
== NULL
)
405 DPRINT1("lpService == NULL!\n");
406 return ERROR_INVALID_HANDLE
;
409 /* FIXME: Acquire service database lock exclusively */
411 if (lpService
->bDeleted
)
413 DPRINT1("The service has already been marked for delete!\n");
414 return ERROR_SERVICE_MARKED_FOR_DELETE
;
417 /* Mark service for delete */
418 lpService
->bDeleted
= TRUE
;
420 dwError
= ScmMarkServiceForDelete(lpService
);
422 /* FIXME: Release service database lock */
424 DPRINT("ScmrDeleteService() done\n");
432 ScmrLockServiceDatabase(handle_t BindingHandle
,
433 unsigned int hSCManager
,
436 PMANAGER_HANDLE hMgr
;
438 DPRINT("ScmrLockServiceDatabase() called\n");
442 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
443 if (hMgr
->Handle
.Tag
!= MANAGER_TAG
)
444 return ERROR_INVALID_HANDLE
;
446 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
448 return ERROR_ACCESS_DENIED
;
450 // return ScmLockDatabase(0, hMgr->0xC, hLock);
452 /* FIXME: Lock the database */
453 *hLock
= 0x12345678; /* Dummy! */
455 return ERROR_SUCCESS
;
461 ScmrQueryServiceObjectSecurity(handle_t BindingHandle
,
462 unsigned int hService
,
463 unsigned long dwSecurityInformation
,
464 unsigned char *lpSecurityDescriptor
,
465 unsigned long dwSecuityDescriptorSize
,
466 unsigned long *pcbBytesNeeded
)
469 PSERVICE_HANDLE hSvc
;
471 ULONG DesiredAccess
= 0;
476 DPRINT("ScmrQueryServiceObjectSecurity() called\n");
478 hSvc
= (PSERVICE_HANDLE
)hService
;
479 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
481 DPRINT1("Invalid handle tag!\n");
482 return ERROR_INVALID_HANDLE
;
485 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
486 GROUP_SECURITY_INFORMATION
||
487 OWNER_SECURITY_INFORMATION
))
488 DesiredAccess
|= READ_CONTROL
;
490 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
491 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
493 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
496 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
497 return ERROR_ACCESS_DENIED
;
500 lpService
= hSvc
->ServiceEntry
;
501 if (lpService
== NULL
)
503 DPRINT1("lpService == NULL!\n");
504 return ERROR_INVALID_HANDLE
;
507 /* FIXME: Lock the service list */
509 Status
= RtlQuerySecurityObject(lpService
->lpSecurityDescriptor
,
510 dwSecurityInformation
,
511 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
512 dwSecuityDescriptorSize
,
515 /* FIXME: Unlock the service list */
517 if (NT_SUCCESS(Status
))
519 *pcbBytesNeeded
= dwBytesNeeded
;
520 dwError
= STATUS_SUCCESS
;
522 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
524 *pcbBytesNeeded
= dwBytesNeeded
;
525 dwError
= ERROR_INSUFFICIENT_BUFFER
;
527 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
529 dwError
= ERROR_GEN_FAILURE
;
533 dwError
= RtlNtStatusToDosError(Status
);
538 DPRINT1("ScmrQueryServiceObjectSecurity() is unimplemented\n");
539 return ERROR_CALL_NOT_IMPLEMENTED
;
545 ScmrSetServiceObjectSecurity(handle_t BindingHandle
,
546 unsigned int hService
,
547 unsigned long dwSecurityInformation
,
548 unsigned char *lpSecurityDescriptor
,
549 unsigned long dwSecuityDescriptorSize
)
551 PSERVICE_HANDLE hSvc
;
553 ULONG DesiredAccess
= 0;
554 HANDLE hToken
= NULL
;
559 DPRINT1("ScmrSetServiceObjectSecurity() called\n");
561 hSvc
= (PSERVICE_HANDLE
)hService
;
562 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
564 DPRINT1("Invalid handle tag!\n");
565 return ERROR_INVALID_HANDLE
;
568 if (dwSecurityInformation
== 0 ||
569 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
570 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
571 return ERROR_INVALID_PARAMETER
;
573 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
574 return ERROR_INVALID_PARAMETER
;
576 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
577 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
579 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
580 DesiredAccess
|= WRITE_DAC
;
582 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
583 DesiredAccess
|= WRITE_OWNER
;
585 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
586 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
587 return ERROR_INVALID_PARAMETER
;
589 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
590 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
591 return ERROR_INVALID_PARAMETER
;
593 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
596 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
597 return ERROR_ACCESS_DENIED
;
600 lpService
= hSvc
->ServiceEntry
;
601 if (lpService
== NULL
)
603 DPRINT1("lpService == NULL!\n");
604 return ERROR_INVALID_HANDLE
;
607 if (lpService
->bDeleted
)
608 return ERROR_SERVICE_MARKED_FOR_DELETE
;
610 RpcImpersonateClient(NULL
);
612 Status
= NtOpenThreadToken(NtCurrentThread(),
616 if (!NT_SUCCESS(Status
))
617 return RtlNtStatusToDosError(Status
);
621 /* FIXME: Lock service database */
624 Status
= RtlSetSecurityObject(dwSecurityInformation
,
625 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
626 &lpService
->lpSecurityDescriptor
,
629 if (!NT_SUCCESS(Status
))
631 dwError
= RtlNtStatusToDosError(Status
);
636 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
637 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
639 if (dwError
!= ERROR_SUCCESS
)
642 DPRINT1("Stub: ScmrSetServiceObjectSecurity() is unimplemented\n");
643 dwError
= ERROR_SUCCESS
;
644 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
645 // lpService->lpSecurityDescriptor);
647 RegFlushKey(hServiceKey
);
648 RegCloseKey(hServiceKey
);
655 /* FIXME: Unlock service database */
657 DPRINT("ScmrSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
665 ScmrQueryServiceStatus(handle_t BindingHandle
,
666 unsigned int hService
,
667 LPSERVICE_STATUS lpServiceStatus
)
669 PSERVICE_HANDLE hSvc
;
672 DPRINT("ScmrQueryServiceStatus() called\n");
675 return ERROR_SHUTDOWN_IN_PROGRESS
;
677 hSvc
= (PSERVICE_HANDLE
)hService
;
678 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
680 DPRINT1("Invalid handle tag!\n");
681 return ERROR_INVALID_HANDLE
;
684 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
685 SERVICE_QUERY_STATUS
))
687 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
688 return ERROR_ACCESS_DENIED
;
691 lpService
= hSvc
->ServiceEntry
;
692 if (lpService
== NULL
)
694 DPRINT1("lpService == NULL!\n");
695 return ERROR_INVALID_HANDLE
;
698 /* Return service status information */
699 RtlCopyMemory(lpServiceStatus
,
701 sizeof(SERVICE_STATUS
));
703 return ERROR_SUCCESS
;
709 ScmrSetServiceStatus(handle_t BindingHandle
,
710 unsigned long hServiceStatus
,
711 LPSERVICE_STATUS lpServiceStatus
)
715 DPRINT("ScmrSetServiceStatus() called\n");
718 return ERROR_SHUTDOWN_IN_PROGRESS
;
720 lpService
= ScmGetServiceEntryByClientHandle((ULONG
)hServiceStatus
);
721 if (lpService
== NULL
)
723 DPRINT1("lpService == NULL!\n");
724 return ERROR_INVALID_HANDLE
;
727 RtlCopyMemory(&lpService
->Status
,
729 sizeof(SERVICE_STATUS
));
731 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
732 DPRINT("ScmrSetServiceStatus() done\n");
734 return ERROR_SUCCESS
;
740 ScmrUnlockServiceDatabase(handle_t BindingHandle
,
743 DPRINT1("ScmrUnlockServiceDatabase() called\n");
745 return ERROR_SUCCESS
;
751 ScmrNotifyBootConfigStatus(handle_t BindingHandle
,
752 unsigned long BootAcceptable
)
754 DPRINT1("ScmrNotifyBootConfigStatus() called\n");
756 return ERROR_CALL_NOT_IMPLEMENTED
;
762 ScmrSetServiceBitsW(handle_t BindingHandle
,
763 unsigned long hServiceStatus
,
764 unsigned long dwServiceBits
,
765 unsigned long bSetBitsOn
,
766 unsigned long bUpdateImmediately
,
769 DPRINT1("ScmrSetServiceBitsW() called\n");
771 return ERROR_CALL_NOT_IMPLEMENTED
;
777 ScmrChangeServiceConfigW(handle_t BiningHandle
,
778 unsigned int hService
,
779 unsigned long dwServiceType
,
780 unsigned long dwStartType
,
781 unsigned long dwErrorControl
,
782 wchar_t *lpBinaryPathName
,
783 wchar_t *lpLoadOrderGroup
,
784 unsigned long *lpdwTagId
, /* in, out, unique */
785 wchar_t *lpDependencies
,
786 unsigned long dwDependenciesLength
,
787 wchar_t *lpServiceStartName
,
789 unsigned long dwPasswordLength
,
790 wchar_t *lpDisplayName
)
792 DWORD dwError
= ERROR_SUCCESS
;
793 PSERVICE_HANDLE hSvc
;
794 PSERVICE lpService
= NULL
;
795 HKEY hServiceKey
= NULL
;
797 DPRINT("ScmrChangeServiceConfigW() called\n");
798 DPRINT("dwServiceType = %lu\n", dwServiceType
);
799 DPRINT("dwStartType = %lu\n", dwStartType
);
800 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
801 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
802 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
803 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
806 return ERROR_SHUTDOWN_IN_PROGRESS
;
808 hSvc
= (PSERVICE_HANDLE
)hService
;
809 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
811 DPRINT1("Invalid handle tag!\n");
812 return ERROR_INVALID_HANDLE
;
815 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
816 SERVICE_CHANGE_CONFIG
))
818 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
819 return ERROR_ACCESS_DENIED
;
822 lpService
= hSvc
->ServiceEntry
;
823 if (lpService
== NULL
)
825 DPRINT1("lpService == NULL!\n");
826 return ERROR_INVALID_HANDLE
;
829 /* FIXME: Lock database exclusively */
831 if (lpService
->bDeleted
)
833 /* FIXME: Unlock database */
834 DPRINT1("The service has already been marked for delete!\n");
835 return ERROR_SERVICE_MARKED_FOR_DELETE
;
838 /* Open the service key */
839 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
842 if (dwError
!= ERROR_SUCCESS
)
845 /* Write service data to the registry */
846 /* Set the display name */
847 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
849 RegSetValueExW(hServiceKey
,
853 (LPBYTE
)lpDisplayName
,
854 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
855 /* FIXME: update lpService->lpDisplayName */
858 if (dwServiceType
!= SERVICE_NO_CHANGE
)
860 /* Set the service type */
861 dwError
= RegSetValueExW(hServiceKey
,
865 (LPBYTE
)&dwServiceType
,
867 if (dwError
!= ERROR_SUCCESS
)
870 lpService
->Status
.dwServiceType
= dwServiceType
;
873 if (dwStartType
!= SERVICE_NO_CHANGE
)
875 /* Set the start value */
876 dwError
= RegSetValueExW(hServiceKey
,
880 (LPBYTE
)&dwStartType
,
882 if (dwError
!= ERROR_SUCCESS
)
885 lpService
->dwStartType
= dwStartType
;
888 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
890 /* Set the error control value */
891 dwError
= RegSetValueExW(hServiceKey
,
895 (LPBYTE
)&dwErrorControl
,
897 if (dwError
!= ERROR_SUCCESS
)
900 lpService
->dwErrorControl
= dwErrorControl
;
904 /* FIXME: set the new ImagePath value */
906 /* Set the image path */
907 if (dwServiceType
& SERVICE_WIN32
)
909 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
911 dwError
= RegSetValueExW(hServiceKey
,
915 (LPBYTE
)lpBinaryPathName
,
916 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
917 if (dwError
!= ERROR_SUCCESS
)
921 else if (dwServiceType
& SERVICE_DRIVER
)
923 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
925 dwError
= RegSetValueExW(hServiceKey
,
930 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
931 if (dwError
!= ERROR_SUCCESS
)
937 /* Set the group name */
938 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
940 dwError
= RegSetValueExW(hServiceKey
,
944 (LPBYTE
)lpLoadOrderGroup
,
945 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
946 if (dwError
!= ERROR_SUCCESS
)
948 /* FIXME: update lpService->lpServiceGroup */
951 if (lpdwTagId
!= NULL
)
953 dwError
= ScmAssignNewTag(lpService
);
954 if (dwError
!= ERROR_SUCCESS
)
957 dwError
= RegSetValueExW(hServiceKey
,
961 (LPBYTE
)&lpService
->dwTag
,
963 if (dwError
!= ERROR_SUCCESS
)
966 *lpdwTagId
= lpService
->dwTag
;
969 /* Write dependencies */
970 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
972 dwError
= ScmWriteDependencies(hServiceKey
,
974 dwDependenciesLength
);
975 if (dwError
!= ERROR_SUCCESS
)
979 if (lpPassword
!= NULL
)
981 /* FIXME: Write password */
984 /* FIXME: Unlock database */
987 if (hServiceKey
!= NULL
)
988 RegCloseKey(hServiceKey
);
990 DPRINT("ScmrChangeServiceConfigW() done (Error %lu)\n", dwError
);
998 ScmrCreateServiceW(handle_t BindingHandle
,
999 unsigned int hSCManager
,
1000 wchar_t *lpServiceName
,
1001 wchar_t *lpDisplayName
,
1002 unsigned long dwDesiredAccess
,
1003 unsigned long dwServiceType
,
1004 unsigned long dwStartType
,
1005 unsigned long dwErrorControl
,
1006 wchar_t *lpBinaryPathName
,
1007 wchar_t *lpLoadOrderGroup
,
1008 unsigned long *lpdwTagId
, /* in, out */
1009 wchar_t *lpDependencies
,
1010 unsigned long dwDependenciesLength
,
1011 wchar_t *lpServiceStartName
,
1012 wchar_t *lpPassword
,
1013 unsigned long dwPasswordLength
,
1014 unsigned int *hService
) /* out */
1016 PMANAGER_HANDLE hManager
;
1017 DWORD dwError
= ERROR_SUCCESS
;
1018 PSERVICE lpService
= NULL
;
1019 SC_HANDLE hServiceHandle
= NULL
;
1020 LPWSTR lpImagePath
= NULL
;
1021 HKEY hServiceKey
= NULL
;
1023 DPRINT("ScmrCreateServiceW() called\n");
1024 DPRINT("lpServiceName = %S\n", lpServiceName
);
1025 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1026 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1027 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1028 DPRINT("dwStartType = %lu\n", dwStartType
);
1029 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1030 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1031 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1034 return ERROR_SHUTDOWN_IN_PROGRESS
;
1036 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1037 if (hManager
->Handle
.Tag
!= MANAGER_TAG
)
1039 DPRINT1("Invalid manager handle!\n");
1040 return ERROR_INVALID_HANDLE
;
1043 /* Check access rights */
1044 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1045 SC_MANAGER_CREATE_SERVICE
))
1047 DPRINT1("Insufficient access rights! 0x%lx\n",
1048 hManager
->Handle
.DesiredAccess
);
1049 return ERROR_ACCESS_DENIED
;
1052 /* Fail if the service already exists! */
1053 if (ScmGetServiceEntryByName(lpServiceName
) != NULL
)
1054 return ERROR_SERVICE_EXISTS
;
1056 if (dwServiceType
& SERVICE_DRIVER
)
1058 /* FIXME: Adjust the image path
1059 * Following line is VERY BAD, because it assumes that the
1060 * first part of full file name is the OS directory */
1061 if (lpBinaryPathName
[1] == ':') lpBinaryPathName
+= GetWindowsDirectoryW(NULL
, 0);
1063 lpImagePath
= (WCHAR
*) HeapAlloc(GetProcessHeap(),
1065 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1066 if (lpImagePath
== NULL
)
1068 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1071 wcscpy(lpImagePath
, lpBinaryPathName
);
1074 /* Allocate a new service entry */
1075 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1077 if (dwError
!= ERROR_SUCCESS
)
1080 /* Fill the new service entry */
1081 lpService
->Status
.dwServiceType
= dwServiceType
;
1082 lpService
->dwStartType
= dwStartType
;
1083 lpService
->dwErrorControl
= dwErrorControl
;
1085 /* Fill the display name */
1086 if (lpDisplayName
!= NULL
&&
1087 *lpDisplayName
!= 0 &&
1088 wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1090 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1091 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1092 if (lpService
->lpDisplayName
== NULL
)
1094 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1097 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1100 /* Assign the service to a group */
1101 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1103 dwError
= ScmSetServiceGroup(lpService
,
1105 if (dwError
!= ERROR_SUCCESS
)
1109 /* Assign a new tag */
1110 if (lpdwTagId
!= NULL
)
1112 dwError
= ScmAssignNewTag(lpService
);
1113 if (dwError
!= ERROR_SUCCESS
)
1117 /* Write service data to the registry */
1118 /* Create the service key */
1119 dwError
= ScmCreateServiceKey(lpServiceName
,
1122 if (dwError
!= ERROR_SUCCESS
)
1125 /* Set the display name */
1126 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1128 RegSetValueExW(hServiceKey
,
1132 (LPBYTE
)lpDisplayName
,
1133 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1136 /* Set the service type */
1137 dwError
= RegSetValueExW(hServiceKey
,
1141 (LPBYTE
)&dwServiceType
,
1143 if (dwError
!= ERROR_SUCCESS
)
1146 /* Set the start value */
1147 dwError
= RegSetValueExW(hServiceKey
,
1151 (LPBYTE
)&dwStartType
,
1153 if (dwError
!= ERROR_SUCCESS
)
1156 /* Set the error control value */
1157 dwError
= RegSetValueExW(hServiceKey
,
1161 (LPBYTE
)&dwErrorControl
,
1163 if (dwError
!= ERROR_SUCCESS
)
1166 /* Set the image path */
1167 if (dwServiceType
& SERVICE_WIN32
)
1169 dwError
= RegSetValueExW(hServiceKey
,
1173 (LPBYTE
)lpBinaryPathName
,
1174 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1175 if (dwError
!= ERROR_SUCCESS
)
1178 else if (dwServiceType
& SERVICE_DRIVER
)
1180 dwError
= RegSetValueExW(hServiceKey
,
1184 (LPBYTE
)lpImagePath
,
1185 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1186 if (dwError
!= ERROR_SUCCESS
)
1190 /* Set the group name */
1191 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1193 dwError
= RegSetValueExW(hServiceKey
,
1197 (LPBYTE
)lpLoadOrderGroup
,
1198 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1199 if (dwError
!= ERROR_SUCCESS
)
1203 if (lpdwTagId
!= NULL
)
1205 dwError
= RegSetValueExW(hServiceKey
,
1209 (LPBYTE
)&lpService
->dwTag
,
1211 if (dwError
!= ERROR_SUCCESS
)
1215 /* Write dependencies */
1216 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1218 dwError
= ScmWriteDependencies(hServiceKey
,
1220 dwDependenciesLength
);
1221 if (dwError
!= ERROR_SUCCESS
)
1225 if (lpPassword
!= NULL
)
1227 /* FIXME: Write password */
1230 dwError
= ScmCreateServiceHandle(lpService
,
1232 if (dwError
!= ERROR_SUCCESS
)
1235 dwError
= ScmCheckAccess(hServiceHandle
,
1237 if (dwError
!= ERROR_SUCCESS
)
1241 if (hServiceKey
!= NULL
)
1242 RegCloseKey(hServiceKey
);
1244 if (dwError
== ERROR_SUCCESS
)
1246 DPRINT("hService %lx\n", hServiceHandle
);
1247 *hService
= (unsigned int)hServiceHandle
;
1249 if (lpdwTagId
!= NULL
)
1250 *lpdwTagId
= lpService
->dwTag
;
1254 /* Release the display name buffer */
1255 if (lpService
->lpServiceName
!= NULL
)
1256 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1258 if (hServiceHandle
!= NULL
)
1260 /* Remove the service handle */
1261 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
1264 if (lpService
!= NULL
)
1266 /* FIXME: remove the service entry */
1270 if (lpImagePath
!= NULL
)
1271 HeapFree(GetProcessHeap(), 0, lpImagePath
);
1273 DPRINT("ScmrCreateServiceW() done (Error %lu)\n", dwError
);
1281 ScmrEnumDependentServicesW(handle_t BindingHandle
,
1282 unsigned int hService
,
1283 unsigned long dwServiceState
,
1284 unsigned char *lpServices
,
1285 unsigned long cbBufSize
,
1286 unsigned long *pcbBytesNeeded
,
1287 unsigned long *lpServicesReturned
)
1289 DWORD dwError
= ERROR_SUCCESS
;
1291 DPRINT1("ScmrEnumDependentServicesW() called\n");
1292 *pcbBytesNeeded
= 0;
1293 *lpServicesReturned
= 0;
1295 DPRINT1("ScmrEnumDependentServicesW() done (Error %lu)\n", dwError
);
1303 ScmrEnumServicesStatusW(handle_t BindingHandle
,
1304 unsigned int hSCManager
,
1305 unsigned long dwServiceType
,
1306 unsigned long dwServiceState
,
1307 unsigned char *lpServices
,
1308 unsigned long dwBufSize
,
1309 unsigned long *pcbBytesNeeded
,
1310 unsigned long *lpServicesReturned
,
1311 unsigned long *lpResumeHandle
)
1313 PMANAGER_HANDLE hManager
;
1315 DWORD dwError
= ERROR_SUCCESS
;
1316 PLIST_ENTRY ServiceEntry
;
1317 PSERVICE CurrentService
;
1319 DWORD dwRequiredSize
;
1320 DWORD dwServiceCount
;
1322 DWORD dwLastResumeCount
;
1323 LPENUM_SERVICE_STATUSW lpStatusPtr
;
1326 DPRINT("ScmrEnumServicesStatusW() called\n");
1329 return ERROR_SHUTDOWN_IN_PROGRESS
;
1331 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1332 if (hManager
->Handle
.Tag
!= MANAGER_TAG
)
1334 DPRINT1("Invalid manager handle!\n");
1335 return ERROR_INVALID_HANDLE
;
1338 /* Check access rights */
1339 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1340 SC_MANAGER_ENUMERATE_SERVICE
))
1342 DPRINT1("Insufficient access rights! 0x%lx\n",
1343 hManager
->Handle
.DesiredAccess
);
1344 return ERROR_ACCESS_DENIED
;
1347 *pcbBytesNeeded
= 0;
1348 *lpServicesReturned
= 0;
1350 dwLastResumeCount
= *lpResumeHandle
;
1352 /* FIXME: Lock the service list shared */
1354 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
1355 if (lpService
== NULL
)
1357 dwError
= ERROR_SUCCESS
;
1364 for (ServiceEntry
= &lpService
->ServiceListEntry
;
1365 ServiceEntry
!= &ServiceListHead
;
1366 ServiceEntry
= ServiceEntry
->Flink
)
1368 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
1372 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
1375 dwState
= SERVICE_ACTIVE
;
1376 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
1377 dwState
= SERVICE_INACTIVE
;
1379 if ((dwState
& dwServiceState
) == 0)
1382 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
1383 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
1384 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
1386 if (dwRequiredSize
+ dwSize
<= dwBufSize
)
1388 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
1389 dwRequiredSize
+= dwSize
;
1391 dwLastResumeCount
= CurrentService
->dwResumeCount
;
1395 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
1401 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
1402 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
1405 ServiceEntry
!= &ServiceListHead
;
1406 ServiceEntry
= ServiceEntry
->Flink
)
1408 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
1412 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
1415 dwState
= SERVICE_ACTIVE
;
1416 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
1417 dwState
= SERVICE_INACTIVE
;
1419 if ((dwState
& dwServiceState
) == 0)
1422 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
1423 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
1424 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
1426 dwError
= ERROR_MORE_DATA
;
1429 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
1431 *lpResumeHandle
= dwLastResumeCount
;
1432 *lpServicesReturned
= dwServiceCount
;
1433 *pcbBytesNeeded
= dwRequiredSize
;
1435 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpServices
;
1436 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpServices
+
1437 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
1440 for (ServiceEntry
= &lpService
->ServiceListEntry
;
1441 ServiceEntry
!= &ServiceListHead
;
1442 ServiceEntry
= ServiceEntry
->Flink
)
1444 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
1448 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
1451 dwState
= SERVICE_ACTIVE
;
1452 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
1453 dwState
= SERVICE_INACTIVE
;
1455 if ((dwState
& dwServiceState
) == 0)
1458 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
1459 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
1460 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
1462 if (dwRequiredSize
+ dwSize
<= dwBufSize
)
1464 /* Copy the service name */
1466 CurrentService
->lpServiceName
);
1467 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpServices
);
1468 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
1470 /* Copy the display name */
1472 CurrentService
->lpDisplayName
);
1473 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpServices
);
1474 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
1476 /* Copy the status information */
1477 memcpy(&lpStatusPtr
->ServiceStatus
,
1478 &CurrentService
->Status
,
1479 sizeof(SERVICE_STATUS
));
1482 dwRequiredSize
+= dwSize
;
1492 /* FIXME: Unlock the service list */
1494 DPRINT("ScmrEnumServicesStatusW() done (Error %lu)\n", dwError
);
1502 ScmrOpenSCManagerW(handle_t BindingHandle
,
1503 wchar_t *lpMachineName
,
1504 wchar_t *lpDatabaseName
,
1505 unsigned long dwDesiredAccess
,
1511 DPRINT("ScmrOpenSCManagerW() called\n");
1512 DPRINT("lpMachineName = %p\n", lpMachineName
);
1513 DPRINT("lpMachineName: %S\n", lpMachineName
);
1514 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
1515 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
1516 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
1519 return ERROR_SHUTDOWN_IN_PROGRESS
;
1521 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
1523 if (dwError
!= ERROR_SUCCESS
)
1525 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
1529 /* Check the desired access */
1530 dwError
= ScmCheckAccess(hHandle
,
1531 dwDesiredAccess
| SC_MANAGER_CONNECT
);
1532 if (dwError
!= ERROR_SUCCESS
)
1534 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
1535 HeapFree(GetProcessHeap(), 0, hHandle
);
1539 *hScm
= (unsigned int)hHandle
;
1540 DPRINT("*hScm = %x\n", *hScm
);
1542 DPRINT("ScmrOpenSCManagerW() done\n");
1544 return ERROR_SUCCESS
;
1550 ScmrOpenServiceW(handle_t BindingHandle
,
1551 unsigned int hSCManager
,
1552 wchar_t *lpServiceName
,
1553 unsigned long dwDesiredAccess
,
1554 unsigned int *hService
)
1557 PMANAGER_HANDLE hManager
;
1561 DPRINT("ScmrOpenServiceW() called\n");
1562 DPRINT("hSCManager = %x\n", hSCManager
);
1563 DPRINT("lpServiceName = %p\n", lpServiceName
);
1564 DPRINT("lpServiceName: %S\n", lpServiceName
);
1565 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
1568 return ERROR_SHUTDOWN_IN_PROGRESS
;
1570 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1571 if (hManager
->Handle
.Tag
!= MANAGER_TAG
)
1573 DPRINT1("Invalid manager handle!\n");
1574 return ERROR_INVALID_HANDLE
;
1577 /* FIXME: Lock the service list */
1579 /* Get service database entry */
1580 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1581 if (lpService
== NULL
)
1583 DPRINT("Could not find a service!\n");
1584 return ERROR_SERVICE_DOES_NOT_EXIST
;
1587 /* Create a service handle */
1588 dwError
= ScmCreateServiceHandle(lpService
,
1590 if (dwError
!= ERROR_SUCCESS
)
1592 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
1596 /* Check the desired access */
1597 dwError
= ScmCheckAccess(hHandle
,
1599 if (dwError
!= ERROR_SUCCESS
)
1601 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
1602 HeapFree(GetProcessHeap(), 0, hHandle
);
1606 *hService
= (unsigned int)hHandle
;
1607 DPRINT("*hService = %x\n", *hService
);
1609 DPRINT("ScmrOpenServiceW() done\n");
1611 return ERROR_SUCCESS
;
1617 ScmrQueryServiceConfigW(handle_t BindingHandle
,
1618 unsigned int hService
,
1619 unsigned char *lpServiceConfig
,
1620 unsigned long cbBufSize
,
1621 unsigned long *pcbBytesNeeded
)
1623 DWORD dwError
= ERROR_SUCCESS
;
1624 PSERVICE_HANDLE hSvc
;
1625 PSERVICE lpService
= NULL
;
1626 HKEY hServiceKey
= NULL
;
1627 LPWSTR lpImagePath
= NULL
;
1628 LPWSTR lpServiceStartName
= NULL
;
1629 DWORD dwRequiredSize
;
1630 LPQUERY_SERVICE_CONFIGW lpConfig
;
1633 DPRINT("ScmrQueryServiceConfigW() called\n");
1636 return ERROR_SHUTDOWN_IN_PROGRESS
;
1638 hSvc
= (PSERVICE_HANDLE
)hService
;
1639 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1641 DPRINT1("Invalid handle tag!\n");
1642 return ERROR_INVALID_HANDLE
;
1645 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1646 SERVICE_QUERY_CONFIG
))
1648 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1649 return ERROR_ACCESS_DENIED
;
1652 lpService
= hSvc
->ServiceEntry
;
1653 if (lpService
== NULL
)
1655 DPRINT1("lpService == NULL!\n");
1656 return ERROR_INVALID_HANDLE
;
1659 /* FIXME: Lock the service database shared */
1661 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
1664 if (dwError
!= ERROR_SUCCESS
)
1667 dwError
= ScmReadString(hServiceKey
,
1670 if (dwError
!= ERROR_SUCCESS
)
1673 ScmReadString(hServiceKey
,
1675 &lpServiceStartName
);
1677 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
1679 if (lpImagePath
!= NULL
)
1680 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1682 if (lpService
->lpGroup
!= NULL
)
1683 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
1685 /* FIXME: Add Dependencies length*/
1687 if (lpServiceStartName
!= NULL
)
1688 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
1690 if (lpService
->lpDisplayName
!= NULL
)
1691 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
1693 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
1695 dwError
= ERROR_INSUFFICIENT_BUFFER
;
1699 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
1700 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
1701 lpConfig
->dwStartType
= lpService
->dwStartType
;
1702 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
1703 lpConfig
->dwTagId
= lpService
->dwTag
;
1705 lpStr
= (LPWSTR
)(lpConfig
+ 1);
1707 if (lpImagePath
!= NULL
)
1709 wcscpy(lpStr
, lpImagePath
);
1710 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
1711 lpStr
+= (wcslen(lpImagePath
) + 1);
1715 lpConfig
->lpBinaryPathName
= NULL
;
1718 if (lpService
->lpGroup
!= NULL
)
1720 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
1721 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
1722 lpStr
+= (wcslen(lpService
->lpGroup
->lpGroupName
) + 1);
1726 lpConfig
->lpLoadOrderGroup
= NULL
;
1729 /* FIXME: Append Dependencies */
1730 lpConfig
->lpDependencies
= NULL
;
1732 if (lpServiceStartName
!= NULL
)
1734 wcscpy(lpStr
, lpServiceStartName
);
1735 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
1736 lpStr
+= (wcslen(lpServiceStartName
) + 1);
1740 lpConfig
->lpServiceStartName
= NULL
;
1743 if (lpService
->lpDisplayName
!= NULL
)
1745 wcscpy(lpStr
, lpService
->lpDisplayName
);
1746 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
1750 lpConfig
->lpDisplayName
= NULL
;
1754 if (pcbBytesNeeded
!= NULL
)
1755 *pcbBytesNeeded
= dwRequiredSize
;
1758 if (lpImagePath
!= NULL
)
1759 HeapFree(GetProcessHeap(), 0, lpImagePath
);
1761 if (lpServiceStartName
!= NULL
)
1762 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
1764 if (hServiceKey
!= NULL
)
1765 RegCloseKey(hServiceKey
);
1767 /* FIXME: Unlock the service database */
1769 DPRINT("ScmrQueryServiceConfigW() done\n");
1777 ScmrQueryServiceLockStatusW(handle_t BindingHandle
,
1778 unsigned int hSCManager
,
1779 unsigned char *lpLockStatus
, /* [out, unique, size_is(cbBufSize)] */
1780 unsigned long cbBufSize
, /* [in] */
1781 unsigned long *pcbBytesNeeded
) /* [out] */
1783 DPRINT1("ScmrQueryServiceLockStatusW() called\n");
1784 return ERROR_CALL_NOT_IMPLEMENTED
;
1790 ScmrStartServiceW(handle_t BindingHandle
,
1791 unsigned int hService
,
1792 unsigned long dwNumServiceArgs
,
1793 unsigned char *lpServiceArgBuffer
,
1794 unsigned long cbBufSize
)
1796 DWORD dwError
= ERROR_SUCCESS
;
1797 PSERVICE_HANDLE hSvc
;
1798 PSERVICE lpService
= NULL
;
1800 DPRINT("ScmrStartServiceW() called\n");
1803 return ERROR_SHUTDOWN_IN_PROGRESS
;
1805 hSvc
= (PSERVICE_HANDLE
)hService
;
1806 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1808 DPRINT1("Invalid handle tag!\n");
1809 return ERROR_INVALID_HANDLE
;
1812 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1815 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1816 return ERROR_ACCESS_DENIED
;
1819 lpService
= hSvc
->ServiceEntry
;
1820 if (lpService
== NULL
)
1822 DPRINT1("lpService == NULL!\n");
1823 return ERROR_INVALID_HANDLE
;
1826 if (lpService
->dwStartType
== SERVICE_DISABLED
)
1827 return ERROR_SERVICE_DISABLED
;
1829 if (lpService
->bDeleted
)
1830 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1832 /* Start the service */
1833 dwError
= ScmStartService(lpService
, (LPWSTR
)lpServiceArgBuffer
);
1841 ScmrGetServiceDisplayNameW(handle_t BindingHandle
,
1842 unsigned int hSCManager
,
1843 wchar_t *lpServiceName
,
1844 wchar_t *lpDisplayName
, /* [out, unique] */
1845 unsigned long *lpcchBuffer
)
1847 // PMANAGER_HANDLE hManager;
1852 DPRINT("ScmrGetServiceDisplayNameW() called\n");
1853 DPRINT("hSCManager = %x\n", hSCManager
);
1854 DPRINT("lpServiceName: %S\n", lpServiceName
);
1855 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
1856 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
1858 // hManager = (PMANAGER_HANDLE)hSCManager;
1859 // if (hManager->Handle.Tag != MANAGER_TAG)
1861 // DPRINT1("Invalid manager handle!\n");
1862 // return ERROR_INVALID_HANDLE;
1865 /* Get service database entry */
1866 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1867 if (lpService
== NULL
)
1869 DPRINT1("Could not find a service!\n");
1870 return ERROR_SERVICE_DOES_NOT_EXIST
;
1873 dwLength
= wcslen(lpService
->lpDisplayName
) + 1;
1875 if (lpDisplayName
!= NULL
&&
1876 *lpcchBuffer
>= dwLength
)
1878 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
1881 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
1883 *lpcchBuffer
= dwLength
;
1891 ScmrGetServiceKeyNameW(handle_t BindingHandle
,
1892 unsigned int hSCManager
,
1893 wchar_t *lpDisplayName
,
1894 wchar_t *lpServiceName
, /* [out, unique] */
1895 unsigned long *lpcchBuffer
)
1897 // PMANAGER_HANDLE hManager;
1902 DPRINT("ScmrGetServiceKeyNameW() called\n");
1903 DPRINT("hSCManager = %x\n", hSCManager
);
1904 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
1905 DPRINT("lpServiceName: %p\n", lpServiceName
);
1906 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
1908 // hManager = (PMANAGER_HANDLE)hSCManager;
1909 // if (hManager->Handle.Tag != MANAGER_TAG)
1911 // DPRINT1("Invalid manager handle!\n");
1912 // return ERROR_INVALID_HANDLE;
1915 /* Get service database entry */
1916 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
1917 if (lpService
== NULL
)
1919 DPRINT1("Could not find a service!\n");
1920 return ERROR_SERVICE_DOES_NOT_EXIST
;
1923 dwLength
= wcslen(lpService
->lpServiceName
) + 1;
1925 if (lpServiceName
!= NULL
&&
1926 *lpcchBuffer
>= dwLength
)
1928 wcscpy(lpServiceName
, lpService
->lpServiceName
);
1931 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
1933 *lpcchBuffer
= dwLength
;
1941 ScmrSetServiceBitsA(handle_t BindingHandle
,
1942 unsigned long hServiceStatus
,
1943 unsigned long dwServiceBits
,
1944 unsigned long bSetBitsOn
,
1945 unsigned long bUpdateImmediately
,
1948 DPRINT1("ScmrSetServiceBitsA() is unimplemented\n");
1949 return ERROR_CALL_NOT_IMPLEMENTED
;
1955 ScmrChangeServiceConfigA(handle_t BiningHandle
,
1956 unsigned int hService
,
1957 unsigned long dwServiceType
,
1958 unsigned long dwStartType
,
1959 unsigned long dwErrorControl
,
1960 char *lpBinaryPathName
,
1961 char *lpLoadOrderGroup
,
1962 unsigned long *lpdwTagId
,
1963 char *lpDependencies
,
1964 unsigned long dwDependenciesLength
,
1965 char *lpServiceStartName
,
1967 unsigned long dwPasswordLength
,
1968 char *lpDisplayName
)
1970 DPRINT1("ScmrChangeServiceConfigA() is unimplemented\n");
1971 return ERROR_CALL_NOT_IMPLEMENTED
;
1977 ScmrCreateServiceA(handle_t BindingHandle
,
1978 unsigned int hSCManager
,
1979 char *lpServiceName
,
1980 char *lpDisplayName
,
1981 unsigned long dwDesiredAccess
,
1982 unsigned long dwServiceType
,
1983 unsigned long dwStartType
,
1984 unsigned long dwErrorControl
,
1985 char *lpBinaryPathName
,
1986 char *lpLoadOrderGroup
,
1987 unsigned long *lpdwTagId
, /* in, out */
1988 char *lpDependencies
,
1989 unsigned long dwDependenciesLength
,
1990 char *lpServiceStartName
,
1992 unsigned long dwPasswordLength
,
1993 unsigned int *hService
) /* out */
1995 DPRINT1("ScmrCreateServiceA() is unimplemented\n");
1996 return ERROR_CALL_NOT_IMPLEMENTED
;
2002 ScmrEnumDependentServicesA(handle_t BindingHandle
,
2003 unsigned int hService
,
2004 unsigned long dwServiceState
,
2005 unsigned char *lpServices
,
2006 unsigned long cbBufSize
,
2007 unsigned long *pcbBytesNeeded
,
2008 unsigned long *lpServicesReturned
)
2010 DPRINT1("ScmrEnumDependentServicesA() is unimplemented\n");
2011 *pcbBytesNeeded
= 0;
2012 *lpServicesReturned
= 0;
2013 return ERROR_CALL_NOT_IMPLEMENTED
;
2019 ScmrEnumServicesStatusA(handle_t BindingHandle
,
2020 unsigned int hSCManager
,
2021 unsigned long dwServiceType
,
2022 unsigned long dwServiceState
,
2023 unsigned char *lpServices
,
2024 unsigned long dwBufSize
,
2025 unsigned long *pcbBytesNeeded
,
2026 unsigned long *lpServicesReturned
,
2027 unsigned long *lpResumeHandle
)
2029 DPRINT1("ScmrEnumServicesAtatusA() is unimplemented\n");
2030 return ERROR_CALL_NOT_IMPLEMENTED
;
2036 ScmrOpenSCManagerA(handle_t BindingHandle
,
2037 char *lpMachineName
,
2038 char *lpDatabaseName
,
2039 unsigned long dwDesiredAccess
,
2042 UNICODE_STRING MachineName
;
2043 UNICODE_STRING DatabaseName
;
2046 DPRINT("ScmrOpenSCManagerA() called\n");
2049 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
2053 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
2056 dwError
= ScmrOpenSCManagerW(BindingHandle
,
2057 lpMachineName
? MachineName
.Buffer
: NULL
,
2058 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
2063 RtlFreeUnicodeString(&MachineName
);
2066 RtlFreeUnicodeString(&DatabaseName
);
2074 ScmrOpenServiceA(handle_t BindingHandle
,
2075 unsigned int hSCManager
,
2076 char *lpServiceName
,
2077 unsigned long dwDesiredAccess
,
2078 unsigned int *hService
)
2080 UNICODE_STRING ServiceName
;
2083 DPRINT("ScmrOpenServiceA() called\n");
2085 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
2088 dwError
= ScmrOpenServiceW(BindingHandle
,
2094 RtlFreeUnicodeString(&ServiceName
);
2102 ScmrQueryServiceConfigA(handle_t BindingHandle
,
2103 unsigned int hService
,
2104 unsigned char *lpServiceConfig
,
2105 unsigned long cbBufSize
,
2106 unsigned long *pcbBytesNeeded
)
2108 DPRINT1("ScmrQueryServiceConfigA() is unimplemented\n");
2109 return ERROR_CALL_NOT_IMPLEMENTED
;
2115 ScmrQueryServiceLockStatusA(handle_t BindingHandle
,
2116 unsigned int hSCManager
,
2117 unsigned char *lpLockStatus
, /* [out, unique, size_is(cbBufSize)] */
2118 unsigned long cbBufSize
, /* [in] */
2119 unsigned long *pcbBytesNeeded
) /* [out] */
2121 DPRINT1("ScmrQueryServiceLockStatusA() called\n");
2122 return ERROR_CALL_NOT_IMPLEMENTED
;
2128 ScmrStartServiceA(handle_t BindingHandle
,
2129 unsigned int hService
,
2130 unsigned long dwNumServiceArgs
,
2131 unsigned char *lpServiceArgBuffer
,
2132 unsigned long cbBufSize
)
2134 DWORD dwError
= ERROR_SUCCESS
;
2135 PSERVICE_HANDLE hSvc
;
2136 PSERVICE lpService
= NULL
;
2138 DPRINT1("ScmrStartServiceA() called\n");
2141 return ERROR_SHUTDOWN_IN_PROGRESS
;
2143 hSvc
= (PSERVICE_HANDLE
)hService
;
2144 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2146 DPRINT1("Invalid handle tag!\n");
2147 return ERROR_INVALID_HANDLE
;
2150 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2153 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2154 return ERROR_ACCESS_DENIED
;
2157 lpService
= hSvc
->ServiceEntry
;
2158 if (lpService
== NULL
)
2160 DPRINT1("lpService == NULL!\n");
2161 return ERROR_INVALID_HANDLE
;
2164 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2165 return ERROR_SERVICE_DISABLED
;
2167 if (lpService
->bDeleted
)
2168 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2170 /* FIXME: Convert argument vector to Unicode */
2172 /* Start the service */
2173 dwError
= ScmStartService(lpService
, NULL
);
2175 /* FIXME: Free argument vector */
2183 ScmrGetServiceDisplayNameA(handle_t BindingHandle
,
2184 unsigned int hSCManager
,
2185 char *lpServiceName
,
2186 char *lpDisplayName
, /* [out, unique] */
2187 unsigned long *lpcchBuffer
)
2189 DPRINT1("ScmrGetServiceDisplayNameA() is unimplemented\n");
2190 return ERROR_CALL_NOT_IMPLEMENTED
;
2196 ScmrGetServiceKeyNameA(handle_t BindingHandle
,
2197 unsigned int hSCManager
,
2198 char *lpDisplayName
,
2199 char *lpServiceName
, /* [out, unique] */
2200 unsigned long *lpcchBuffer
)
2202 DPRINT1("ScmrGetServiceKeyNameA() is unimplemented\n");
2203 return ERROR_CALL_NOT_IMPLEMENTED
;
2209 ScmrGetCurrentGroupStateW(handle_t BindingHandle
)
2211 DPRINT1("ScmrGetCurrentGroupStateW() is unimplemented\n");
2212 return ERROR_CALL_NOT_IMPLEMENTED
;
2218 ScmrEnumServiceGroupW(handle_t BindingHandle
)
2220 DPRINT1("ScmrEnumServiceGroupW() is unimplemented\n");
2221 return ERROR_CALL_NOT_IMPLEMENTED
;
2227 ScmrChangeServiceConfig2A(handle_t BindingHandle
,
2228 unsigned int hService
,
2229 unsigned long dwInfoLevel
,
2230 unsigned char *lpInfo
,
2231 unsigned long dwInfoSize
)
2233 DPRINT1("ScmrChangeServiceConfig2A() is unimplemented\n");
2234 return ERROR_CALL_NOT_IMPLEMENTED
;
2240 ScmrChangeServiceConfig2W(handle_t BindingHandle
,
2241 unsigned int hService
,
2242 unsigned long dwInfoLevel
,
2243 unsigned char *lpInfo
,
2244 unsigned long dwInfoSize
)
2246 DWORD dwError
= ERROR_SUCCESS
;
2247 PSERVICE_HANDLE hSvc
;
2248 PSERVICE lpService
= NULL
;
2249 HKEY hServiceKey
= NULL
;
2251 DPRINT("ScmrChangeServiceConfig2W() called\n");
2252 DPRINT("dwInfoLevel = %lu\n", dwInfoLevel
);
2253 DPRINT("dwInfoSize = %lu\n", dwInfoSize
);
2256 return ERROR_SHUTDOWN_IN_PROGRESS
;
2258 hSvc
= (PSERVICE_HANDLE
)hService
;
2259 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2261 DPRINT1("Invalid handle tag!\n");
2262 return ERROR_INVALID_HANDLE
;
2265 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2266 SERVICE_CHANGE_CONFIG
))
2268 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2269 return ERROR_ACCESS_DENIED
;
2272 lpService
= hSvc
->ServiceEntry
;
2273 if (lpService
== NULL
)
2275 DPRINT1("lpService == NULL!\n");
2276 return ERROR_INVALID_HANDLE
;
2279 /* FIXME: Lock database exclusively */
2281 if (lpService
->bDeleted
)
2283 /* FIXME: Unlock database */
2284 DPRINT1("The service has already been marked for delete!\n");
2285 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2288 /* Open the service key */
2289 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2292 if (dwError
!= ERROR_SUCCESS
)
2295 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
2297 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
2299 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpInfo
;
2300 lpServiceDescription
->lpDescription
= (LPWSTR
)(lpInfo
+ sizeof(LPSERVICE_DESCRIPTIONW
));
2302 if (lpServiceDescription
!= NULL
&&
2303 lpServiceDescription
->lpDescription
!= NULL
)
2305 RegSetValueExW(hServiceKey
,
2309 (LPBYTE
)lpServiceDescription
->lpDescription
,
2310 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
2312 if (dwError
!= ERROR_SUCCESS
)
2316 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
2318 DPRINT1("SERVICE_CONFIG_FAILURE_ACTIONS not implemented\n");
2319 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
2324 /* FIXME: Unlock database */
2325 if (hServiceKey
!= NULL
)
2326 RegCloseKey(hServiceKey
);
2328 DPRINT("ScmrChangeServiceConfig2W() done (Error %lu)\n", dwError
);
2336 ScmrQueryServiceConfig2A(handle_t BindingHandle
,
2337 unsigned int hService
,
2338 unsigned long dwInfoLevel
,
2339 unsigned char *lpBuffer
,
2340 unsigned long cbBufSize
,
2341 unsigned long *pcbBytesNeeded
)
2343 DPRINT1("ScmrQueryServiceConfig2A() is unimplemented\n");
2344 return ERROR_CALL_NOT_IMPLEMENTED
;
2350 ScmrQueryServiceConfig2W(handle_t BindingHandle
,
2351 unsigned int hService
,
2352 unsigned long dwInfoLevel
,
2353 unsigned char *lpBuffer
,
2354 unsigned long cbBufSize
,
2355 unsigned long *pcbBytesNeeded
)
2357 DWORD dwError
= ERROR_SUCCESS
;
2358 PSERVICE_HANDLE hSvc
;
2359 PSERVICE lpService
= NULL
;
2360 HKEY hServiceKey
= NULL
;
2361 DWORD dwRequiredSize
;
2362 LPWSTR lpDescription
= NULL
;
2364 DPRINT("ScmrQueryServiceConfig2W() called\n");
2367 return ERROR_SHUTDOWN_IN_PROGRESS
;
2369 hSvc
= (PSERVICE_HANDLE
)hService
;
2370 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2372 DPRINT1("Invalid handle tag!\n");
2373 return ERROR_INVALID_HANDLE
;
2376 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2377 SERVICE_QUERY_CONFIG
))
2379 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2380 return ERROR_ACCESS_DENIED
;
2383 lpService
= hSvc
->ServiceEntry
;
2384 if (lpService
== NULL
)
2386 DPRINT1("lpService == NULL!\n");
2387 return ERROR_INVALID_HANDLE
;
2390 /* FIXME: Lock the service database shared */
2392 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2395 if (dwError
!= ERROR_SUCCESS
)
2398 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
2400 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
2403 dwError
= ScmReadString(hServiceKey
,
2406 if (dwError
!= ERROR_SUCCESS
)
2409 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
2411 if (cbBufSize
< dwRequiredSize
)
2413 *pcbBytesNeeded
= dwRequiredSize
;
2414 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2419 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
2420 wcscpy(lpStr
, lpDescription
);
2421 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
2424 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
2426 DPRINT1("SERVICE_CONFIG_FAILURE_ACTIONS not implemented\n");
2427 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
2432 if (lpDescription
!= NULL
)
2433 HeapFree(GetProcessHeap(), 0, lpDescription
);
2435 if (hServiceKey
!= NULL
)
2436 RegCloseKey(hServiceKey
);
2438 /* FIXME: Unlock database */
2440 DPRINT("ScmrQueryServiceConfig2W() done (Error %lu)\n", dwError
);
2448 ScmrQueryServiceStatusEx(handle_t BindingHandle
,
2449 unsigned int hService
,
2450 unsigned long InfoLevel
,
2451 unsigned char *lpBuffer
, /* out */
2452 unsigned long cbBufSize
,
2453 unsigned long *pcbBytesNeeded
) /* out */
2455 LPSERVICE_STATUS_PROCESS lpStatus
;
2456 PSERVICE_HANDLE hSvc
;
2459 DPRINT("ScmrQueryServiceStatusEx() called\n");
2462 return ERROR_SHUTDOWN_IN_PROGRESS
;
2464 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
2465 return ERROR_INVALID_LEVEL
;
2467 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
2469 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
2470 return ERROR_INSUFFICIENT_BUFFER
;
2472 hSvc
= (PSERVICE_HANDLE
)hService
;
2473 if (hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2475 DPRINT1("Invalid handle tag!\n");
2476 return ERROR_INVALID_HANDLE
;
2479 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2480 SERVICE_QUERY_STATUS
))
2482 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2483 return ERROR_ACCESS_DENIED
;
2486 lpService
= hSvc
->ServiceEntry
;
2487 if (lpService
== NULL
)
2489 DPRINT1("lpService == NULL!\n");
2490 return ERROR_INVALID_HANDLE
;
2493 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
2495 /* Return service status information */
2496 RtlCopyMemory(lpStatus
,
2498 sizeof(SERVICE_STATUS
));
2500 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
2501 lpStatus
->dwServiceFlags
= 0; /* FIXME */
2503 return ERROR_SUCCESS
;
2509 ScmrEnumServicesStatusExA(handle_t BindingHandle
,
2510 unsigned int hSCManager
,
2511 unsigned long InfoLevel
,
2512 unsigned long dwServiceType
,
2513 unsigned long dwServiceState
,
2514 unsigned char *lpServices
,
2515 unsigned long dwBufSize
,
2516 unsigned long *pcbBytesNeeded
,
2517 unsigned long *lpServicesReturned
,
2518 unsigned long *lpResumeHandle
,
2521 DPRINT1("ScmrEnumServicesStatusExA() is unimplemented\n");
2522 *pcbBytesNeeded
= 0;
2523 *lpServicesReturned
= 0;
2524 return ERROR_CALL_NOT_IMPLEMENTED
;
2530 ScmrEnumServicesStatusExW(handle_t BindingHandle
,
2531 unsigned int hSCManager
,
2532 unsigned long InfoLevel
,
2533 unsigned long dwServiceType
,
2534 unsigned long dwServiceState
,
2535 unsigned char *lpServices
,
2536 unsigned long dwBufSize
,
2537 unsigned long *pcbBytesNeeded
,
2538 unsigned long *lpServicesReturned
,
2539 unsigned long *lpResumeHandle
,
2540 wchar_t *pszGroupName
)
2542 PMANAGER_HANDLE hManager
;
2544 DWORD dwError
= ERROR_SUCCESS
;
2545 PLIST_ENTRY ServiceEntry
;
2546 PSERVICE CurrentService
;
2548 DWORD dwRequiredSize
;
2549 DWORD dwServiceCount
;
2551 DWORD dwLastResumeCount
;
2552 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
2555 DPRINT("ScmrEnumServicesStatusExW() called\n");
2558 return ERROR_SHUTDOWN_IN_PROGRESS
;
2560 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
2561 return ERROR_INVALID_LEVEL
;
2563 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2564 if (hManager
->Handle
.Tag
!= MANAGER_TAG
)
2566 DPRINT1("Invalid manager handle!\n");
2567 return ERROR_INVALID_HANDLE
;
2570 /* Check access rights */
2571 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2572 SC_MANAGER_ENUMERATE_SERVICE
))
2574 DPRINT1("Insufficient access rights! 0x%lx\n",
2575 hManager
->Handle
.DesiredAccess
);
2576 return ERROR_ACCESS_DENIED
;
2579 *pcbBytesNeeded
= 0;
2580 *lpServicesReturned
= 0;
2582 dwLastResumeCount
= *lpResumeHandle
;
2584 /* Lock the service list shared */
2586 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2587 if (lpService
== NULL
)
2589 dwError
= ERROR_SUCCESS
;
2596 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2597 ServiceEntry
!= &ServiceListHead
;
2598 ServiceEntry
= ServiceEntry
->Flink
)
2600 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2604 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2607 dwState
= SERVICE_ACTIVE
;
2608 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2609 dwState
= SERVICE_INACTIVE
;
2611 if ((dwState
& dwServiceState
) == 0)
2616 if (*pszGroupName
== 0)
2618 if (CurrentService
->lpGroup
!= NULL
)
2623 if ((CurrentService
->lpGroup
== NULL
) ||
2624 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
2629 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
2630 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2631 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2633 if (dwRequiredSize
+ dwSize
<= dwBufSize
)
2635 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2636 dwRequiredSize
+= dwSize
;
2638 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2642 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2648 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2649 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2652 ServiceEntry
!= &ServiceListHead
;
2653 ServiceEntry
= ServiceEntry
->Flink
)
2655 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2659 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2662 dwState
= SERVICE_ACTIVE
;
2663 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2664 dwState
= SERVICE_INACTIVE
;
2666 if ((dwState
& dwServiceState
) == 0)
2671 if (*pszGroupName
== 0)
2673 if (CurrentService
->lpGroup
!= NULL
)
2678 if ((CurrentService
->lpGroup
== NULL
) ||
2679 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
2684 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
2685 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2686 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2688 dwError
= ERROR_MORE_DATA
;
2691 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2693 *lpResumeHandle
= dwLastResumeCount
;
2694 *lpServicesReturned
= dwServiceCount
;
2695 *pcbBytesNeeded
= dwRequiredSize
;
2697 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpServices
;
2698 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpServices
+
2699 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
2702 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2703 ServiceEntry
!= &ServiceListHead
;
2704 ServiceEntry
= ServiceEntry
->Flink
)
2706 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2710 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2713 dwState
= SERVICE_ACTIVE
;
2714 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2715 dwState
= SERVICE_INACTIVE
;
2717 if ((dwState
& dwServiceState
) == 0)
2722 if (*pszGroupName
== 0)
2724 if (CurrentService
->lpGroup
!= NULL
)
2729 if ((CurrentService
->lpGroup
== NULL
) ||
2730 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
2735 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
2736 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2737 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2739 if (dwRequiredSize
+ dwSize
<= dwBufSize
)
2741 /* Copy the service name */
2743 CurrentService
->lpServiceName
);
2744 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpServices
);
2745 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2747 /* Copy the display name */
2749 CurrentService
->lpDisplayName
);
2750 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpServices
);
2751 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2753 /* Copy the status information */
2754 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
2755 &CurrentService
->Status
,
2756 sizeof(SERVICE_STATUS
));
2757 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
2758 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
2761 dwRequiredSize
+= dwSize
;
2771 /* Unlock the service list */
2773 DPRINT("ScmrEnumServicesStatusExW() done (Error %lu)\n", dwError
);
2780 /* ScmrSendTSMessage */
2783 void __RPC_FAR
* __RPC_USER
midl_user_allocate(size_t len
)
2785 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
2789 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
2791 HeapFree(GetProcessHeap(), 0, ptr
);