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>
11 /* INCLUDES ****************************************************************/
19 /* GLOBALS *****************************************************************/
21 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
22 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
24 typedef struct _SCMGR_HANDLE
32 typedef struct _MANAGER_HANDLE
36 /* FIXME: Insert more data here */
38 WCHAR DatabaseName
[1];
39 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
42 typedef struct _SERVICE_HANDLE
47 PSERVICE ServiceEntry
;
49 /* FIXME: Insert more data here */
51 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
54 #define SC_MANAGER_READ \
55 (STANDARD_RIGHTS_READ | \
56 SC_MANAGER_QUERY_LOCK_STATUS | \
57 SC_MANAGER_ENUMERATE_SERVICE)
59 #define SC_MANAGER_WRITE \
60 (STANDARD_RIGHTS_WRITE | \
61 SC_MANAGER_MODIFY_BOOT_CONFIG | \
62 SC_MANAGER_CREATE_SERVICE)
64 #define SC_MANAGER_EXECUTE \
65 (STANDARD_RIGHTS_EXECUTE | \
67 SC_MANAGER_ENUMERATE_SERVICE | \
68 SC_MANAGER_CONNECT | \
69 SC_MANAGER_CREATE_SERVICE)
72 #define SERVICE_READ \
73 (STANDARD_RIGHTS_READ | \
74 SERVICE_INTERROGATE | \
75 SERVICE_ENUMERATE_DEPENDENTS | \
76 SERVICE_QUERY_STATUS | \
79 #define SERVICE_WRITE \
80 (STANDARD_RIGHTS_WRITE | \
81 SERVICE_CHANGE_CONFIG)
83 #define SERVICE_EXECUTE \
84 (STANDARD_RIGHTS_EXECUTE | \
85 SERVICE_USER_DEFINED_CONTROL | \
86 SERVICE_PAUSE_CONTINUE | \
91 /* VARIABLES ***************************************************************/
93 static GENERIC_MAPPING
94 ScmManagerMapping
= {SC_MANAGER_READ
,
97 SC_MANAGER_ALL_ACCESS
};
99 static GENERIC_MAPPING
100 ScmServiceMapping
= {SERVICE_READ
,
103 SC_MANAGER_ALL_ACCESS
};
106 /* FUNCTIONS ***************************************************************/
109 ScmStartRpcServer(VOID
)
113 DPRINT("ScmStartRpcServer() called\n");
115 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
119 if (Status
!= RPC_S_OK
)
121 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
125 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
128 if (Status
!= RPC_S_OK
)
130 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
134 Status
= RpcServerListen(1, 20, TRUE
);
135 if (Status
!= RPC_S_OK
)
137 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
141 DPRINT("ScmStartRpcServer() done\n");
146 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
151 if (lpDatabaseName
== NULL
)
152 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
154 if (wcsicmp(lpDatabaseName
,SERVICES_FAILED_DATABASEW
)==0)
156 DPRINT1("Database %S, does not exist\n",lpDatabaseName
);
157 return ERROR_DATABASE_DOES_NOT_EXIST
;
159 else if (wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
161 DPRINT1("Invalid Database name %S.\n",lpDatabaseName
);
162 return ERROR_INVALID_NAME
;
165 Ptr
= (MANAGER_HANDLE
*) HeapAlloc(GetProcessHeap(),
167 sizeof(MANAGER_HANDLE
) + wcslen(lpDatabaseName
) * sizeof(WCHAR
));
169 return ERROR_NOT_ENOUGH_MEMORY
;
171 Ptr
->Handle
.Tag
= MANAGER_TAG
;
172 Ptr
->Handle
.RefCount
= 1;
174 /* FIXME: initialize more data here */
176 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
178 *Handle
= (SC_HANDLE
)Ptr
;
180 return ERROR_SUCCESS
;
185 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
190 Ptr
= (SERVICE_HANDLE
*) HeapAlloc(GetProcessHeap(),
192 sizeof(SERVICE_HANDLE
));
194 return ERROR_NOT_ENOUGH_MEMORY
;
196 Ptr
->Handle
.Tag
= SERVICE_TAG
;
197 Ptr
->Handle
.RefCount
= 1;
199 /* FIXME: initialize more data here */
200 Ptr
->ServiceEntry
= lpServiceEntry
;
202 *Handle
= (SC_HANDLE
)Ptr
;
204 return ERROR_SUCCESS
;
209 ScmCheckAccess(SC_HANDLE Handle
,
210 DWORD dwDesiredAccess
)
212 PMANAGER_HANDLE hMgr
;
214 hMgr
= (PMANAGER_HANDLE
)Handle
;
215 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
217 RtlMapGenericMask(&dwDesiredAccess
,
220 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
222 return ERROR_SUCCESS
;
224 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
226 RtlMapGenericMask(&dwDesiredAccess
,
229 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
231 return ERROR_SUCCESS
;
234 return ERROR_INVALID_HANDLE
;
239 ScmAssignNewTag(PSERVICE lpService
)
242 DPRINT("Assigning new tag to service %S\n", lpService
->lpServiceName
);
243 lpService
->dwTag
= 0;
244 return ERROR_SUCCESS
;
248 /* Internal recursive function */
249 /* Need to search for every dependency on every service */
251 Int_EnumDependentServicesW(HKEY hServicesKey
,
253 DWORD dwServiceState
,
254 PSERVICE
*lpServices
,
255 LPDWORD pcbBytesNeeded
,
256 LPDWORD lpServicesReturned
)
258 DWORD dwError
= ERROR_SUCCESS
;
259 WCHAR szNameBuf
[MAX_PATH
];
260 WCHAR szValueBuf
[MAX_PATH
];
261 WCHAR
*lpszNameBuf
= szNameBuf
;
262 WCHAR
*lpszValueBuf
= szValueBuf
;
266 PSERVICE lpCurrentService
;
267 HKEY hServiceEnumKey
;
268 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
269 DWORD dwDependServiceStrPtr
= 0;
270 DWORD dwRequiredSize
= 0;
272 /* Get the number of service keys */
273 dwError
= RegQueryInfoKeyW(hServicesKey
,
285 if (dwError
!= ERROR_SUCCESS
)
287 DPRINT1("ERROR! Unable to get number of services keys.\n");
291 /* Iterate the service keys to see if another service depends on the this service */
292 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
295 dwError
= RegEnumKeyExW(hServicesKey
,
303 if (dwError
!= ERROR_SUCCESS
)
306 /* Open the Service key */
307 dwError
= RegOpenKeyExW(hServicesKey
,
312 if (dwError
!= ERROR_SUCCESS
)
317 /* Check for the DependOnService Value */
318 dwError
= RegQueryValueExW(hServiceEnumKey
,
322 (LPBYTE
)lpszValueBuf
,
325 /* FIXME: Handle load order. */
327 /* If the service found has a DependOnService value */
328 if (dwError
== ERROR_SUCCESS
)
330 dwDependServiceStrPtr
= 0;
332 /* Can be more than one Dependencies in the DependOnService string */
333 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
335 if (wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
337 /* Get the current enumed service pointer */
338 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
340 /* Check for valid Service */
341 if (!lpCurrentService
)
343 /* This should never happen! */
344 DPRINT1("This should not happen at this point, report to Developer\n");
345 return ERROR_NOT_FOUND
;
348 /* Determine state the service is in */
349 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
350 dwCurrentServiceState
= SERVICE_INACTIVE
;
352 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
353 if ((dwCurrentServiceState
== dwServiceState
) ||
354 (dwServiceState
== SERVICE_STATE_ALL
))
356 /* Calculate the required size */
357 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
358 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
359 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
361 /* Add the size for service name and display name pointers */
362 dwRequiredSize
+= (2 * sizeof(PVOID
));
364 /* increase the BytesNeeded size */
365 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
367 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
370 /* Recursive call to check for its dependencies */
371 Int_EnumDependentServicesW(hServicesKey
,
378 /* If the lpServices is valid set the service pointer */
380 lpServices
[*lpServicesReturned
] = lpCurrentService
;
382 *lpServicesReturned
= *lpServicesReturned
+ 1;
386 dwDependServiceStrPtr
+= (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
389 else if (*pcbBytesNeeded
)
391 dwError
= ERROR_SUCCESS
;
394 RegCloseKey(hServiceEnumKey
);
402 DWORD
RCloseServiceHandle(
403 handle_t BindingHandle
,
404 LPSC_RPC_HANDLE hSCObject
)
406 PMANAGER_HANDLE hManager
;
408 DPRINT("RCloseServiceHandle() called\n");
410 DPRINT("hSCObject = %p\n", *hSCObject
);
413 return ERROR_INVALID_HANDLE
;
415 hManager
= (PMANAGER_HANDLE
)*hSCObject
;
416 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
418 DPRINT("Found manager handle\n");
420 hManager
->Handle
.RefCount
--;
421 if (hManager
->Handle
.RefCount
== 0)
423 /* FIXME: add cleanup code */
425 HeapFree(GetProcessHeap(), 0, hManager
);
428 DPRINT("RCloseServiceHandle() done\n");
429 return ERROR_SUCCESS
;
431 else if (hManager
->Handle
.Tag
== SERVICE_TAG
)
433 DPRINT("Found service handle\n");
435 hManager
->Handle
.RefCount
--;
436 if (hManager
->Handle
.RefCount
== 0)
438 /* FIXME: add cleanup code */
440 HeapFree(GetProcessHeap(), 0, hManager
);
443 DPRINT("RCloseServiceHandle() done\n");
444 return ERROR_SUCCESS
;
447 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
449 return ERROR_INVALID_HANDLE
;
454 DWORD
RControlService(
455 handle_t BindingHandle
,
456 SC_RPC_HANDLE hService
,
458 LPSERVICE_STATUS lpServiceStatus
)
460 PSERVICE_HANDLE hSvc
;
462 ACCESS_MASK DesiredAccess
;
463 DWORD dwError
= ERROR_SUCCESS
;
465 DPRINT("RControlService() called\n");
468 return ERROR_SHUTDOWN_IN_PROGRESS
;
470 /* Check the service handle */
471 hSvc
= (PSERVICE_HANDLE
)hService
;
472 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
474 DPRINT1("Invalid handle tag!\n");
475 return ERROR_INVALID_HANDLE
;
478 /* Check access rights */
481 case SERVICE_CONTROL_STOP
:
482 DesiredAccess
= SERVICE_STOP
;
485 case SERVICE_CONTROL_PAUSE
:
486 case SERVICE_CONTROL_CONTINUE
:
487 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
490 case SERVICE_INTERROGATE
:
491 DesiredAccess
= SERVICE_INTERROGATE
;
495 if (dwControl
>= 128 && dwControl
<= 255)
496 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
498 DesiredAccess
= SERVICE_QUERY_CONFIG
|
499 SERVICE_CHANGE_CONFIG
|
500 SERVICE_QUERY_STATUS
|
502 SERVICE_PAUSE_CONTINUE
;
506 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
508 return ERROR_ACCESS_DENIED
;
510 /* Check the service entry point */
511 lpService
= hSvc
->ServiceEntry
;
512 if (lpService
== NULL
)
514 DPRINT1("lpService == NULL!\n");
515 return ERROR_INVALID_HANDLE
;
518 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
520 /* Send control code to the driver */
521 dwError
= ScmControlDriver(lpService
,
527 /* Send control code to the service */
528 dwError
= ScmControlService(lpService
,
533 /* Return service status information */
534 RtlCopyMemory(lpServiceStatus
,
536 sizeof(SERVICE_STATUS
));
543 DWORD
RDeleteService(
544 handle_t BindingHandle
,
545 SC_RPC_HANDLE hService
)
547 PSERVICE_HANDLE hSvc
;
551 DPRINT("RDeleteService() called\n");
554 return ERROR_SHUTDOWN_IN_PROGRESS
;
556 hSvc
= (PSERVICE_HANDLE
)hService
;
557 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
558 return ERROR_INVALID_HANDLE
;
560 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
562 return ERROR_ACCESS_DENIED
;
564 lpService
= hSvc
->ServiceEntry
;
565 if (lpService
== NULL
)
567 DPRINT1("lpService == NULL!\n");
568 return ERROR_INVALID_HANDLE
;
571 /* FIXME: Acquire service database lock exclusively */
573 if (lpService
->bDeleted
)
575 DPRINT1("The service has already been marked for delete!\n");
576 return ERROR_SERVICE_MARKED_FOR_DELETE
;
579 /* Mark service for delete */
580 lpService
->bDeleted
= TRUE
;
582 dwError
= ScmMarkServiceForDelete(lpService
);
584 /* FIXME: Release service database lock */
586 DPRINT("RDeleteService() done\n");
593 DWORD
RLockServiceDatabase(
594 handle_t BindingHandle
,
595 SC_RPC_HANDLE hSCManager
,
596 LPSC_RPC_LOCK lpLock
)
598 PMANAGER_HANDLE hMgr
;
600 DPRINT("RLockServiceDatabase() called\n");
604 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
605 if (!hMgr
|| hMgr
->Handle
.Tag
!= MANAGER_TAG
)
606 return ERROR_INVALID_HANDLE
;
608 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
610 return ERROR_ACCESS_DENIED
;
612 // return ScmLockDatabase(0, hMgr->0xC, hLock);
614 /* FIXME: Lock the database */
615 *lpLock
= (void *)0x12345678; /* Dummy! */
617 return ERROR_SUCCESS
;
622 DWORD
RQueryServiceObjectSecurity(
623 handle_t BindingHandle
,
624 SC_RPC_HANDLE hService
,
625 SECURITY_INFORMATION dwSecurityInformation
,
626 LPBYTE lpSecurityDescriptor
,
628 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
631 PSERVICE_HANDLE hSvc
;
633 ULONG DesiredAccess
= 0;
638 DPRINT("RQueryServiceObjectSecurity() called\n");
640 hSvc
= (PSERVICE_HANDLE
)hService
;
641 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
643 DPRINT1("Invalid handle tag!\n");
644 return ERROR_INVALID_HANDLE
;
647 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
648 GROUP_SECURITY_INFORMATION
||
649 OWNER_SECURITY_INFORMATION
))
650 DesiredAccess
|= READ_CONTROL
;
652 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
653 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
655 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
658 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
659 return ERROR_ACCESS_DENIED
;
662 lpService
= hSvc
->ServiceEntry
;
663 if (lpService
== NULL
)
665 DPRINT1("lpService == NULL!\n");
666 return ERROR_INVALID_HANDLE
;
669 /* FIXME: Lock the service list */
671 Status
= RtlQuerySecurityObject(lpService
->lpSecurityDescriptor
,
672 dwSecurityInformation
,
673 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
674 dwSecuityDescriptorSize
,
677 /* FIXME: Unlock the service list */
679 if (NT_SUCCESS(Status
))
681 *pcbBytesNeeded
= dwBytesNeeded
;
682 dwError
= STATUS_SUCCESS
;
684 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
686 *pcbBytesNeeded
= dwBytesNeeded
;
687 dwError
= ERROR_INSUFFICIENT_BUFFER
;
689 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
691 dwError
= ERROR_GEN_FAILURE
;
695 dwError
= RtlNtStatusToDosError(Status
);
701 return ERROR_CALL_NOT_IMPLEMENTED
;
706 DWORD
RSetServiceObjectSecurity(
707 handle_t BindingHandle
,
708 SC_RPC_HANDLE hService
,
709 DWORD dwSecurityInformation
,
710 LPBYTE lpSecurityDescriptor
,
711 DWORD dwSecuityDescriptorSize
)
713 PSERVICE_HANDLE hSvc
;
715 ULONG DesiredAccess
= 0;
716 HANDLE hToken
= NULL
;
721 DPRINT1("RSetServiceObjectSecurity() called\n");
723 hSvc
= (PSERVICE_HANDLE
)hService
;
724 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
726 DPRINT1("Invalid handle tag!\n");
727 return ERROR_INVALID_HANDLE
;
730 if (dwSecurityInformation
== 0 ||
731 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
732 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
733 return ERROR_INVALID_PARAMETER
;
735 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
736 return ERROR_INVALID_PARAMETER
;
738 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
739 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
741 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
742 DesiredAccess
|= WRITE_DAC
;
744 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
745 DesiredAccess
|= WRITE_OWNER
;
747 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
748 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
749 return ERROR_INVALID_PARAMETER
;
751 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
752 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
753 return ERROR_INVALID_PARAMETER
;
755 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
758 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
759 return ERROR_ACCESS_DENIED
;
762 lpService
= hSvc
->ServiceEntry
;
763 if (lpService
== NULL
)
765 DPRINT1("lpService == NULL!\n");
766 return ERROR_INVALID_HANDLE
;
769 if (lpService
->bDeleted
)
770 return ERROR_SERVICE_MARKED_FOR_DELETE
;
772 RpcImpersonateClient(NULL
);
774 Status
= NtOpenThreadToken(NtCurrentThread(),
778 if (!NT_SUCCESS(Status
))
779 return RtlNtStatusToDosError(Status
);
783 /* FIXME: Lock service database */
786 Status
= RtlSetSecurityObject(dwSecurityInformation
,
787 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
788 &lpService
->lpSecurityDescriptor
,
791 if (!NT_SUCCESS(Status
))
793 dwError
= RtlNtStatusToDosError(Status
);
798 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
799 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
801 if (dwError
!= ERROR_SUCCESS
)
805 dwError
= ERROR_SUCCESS
;
806 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
807 // lpService->lpSecurityDescriptor);
809 RegFlushKey(hServiceKey
);
810 RegCloseKey(hServiceKey
);
817 /* FIXME: Unlock service database */
819 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
826 DWORD
RQueryServiceStatus(
827 handle_t BindingHandle
,
828 SC_RPC_HANDLE hService
,
829 LPSERVICE_STATUS lpServiceStatus
)
831 PSERVICE_HANDLE hSvc
;
834 DPRINT("RQueryServiceStatus() called\n");
837 return ERROR_SHUTDOWN_IN_PROGRESS
;
839 hSvc
= (PSERVICE_HANDLE
)hService
;
840 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
842 DPRINT1("Invalid handle tag!\n");
843 return ERROR_INVALID_HANDLE
;
846 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
847 SERVICE_QUERY_STATUS
))
849 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
850 return ERROR_ACCESS_DENIED
;
853 lpService
= hSvc
->ServiceEntry
;
854 if (lpService
== NULL
)
856 DPRINT1("lpService == NULL!\n");
857 return ERROR_INVALID_HANDLE
;
860 /* Return service status information */
861 RtlCopyMemory(lpServiceStatus
,
863 sizeof(SERVICE_STATUS
));
865 return ERROR_SUCCESS
;
870 DWORD
RSetServiceStatus(
871 handle_t BindingHandle
,
872 SC_RPC_HANDLE hServiceStatus
,
873 LPSERVICE_STATUS lpServiceStatus
)
877 DPRINT("RSetServiceStatus() called\n");
880 return ERROR_SHUTDOWN_IN_PROGRESS
;
882 lpService
= ScmGetServiceEntryByClientHandle((ULONG
)hServiceStatus
);
883 if (lpService
== NULL
)
885 DPRINT1("lpService == NULL!\n");
886 return ERROR_INVALID_HANDLE
;
889 RtlCopyMemory(&lpService
->Status
,
891 sizeof(SERVICE_STATUS
));
893 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
894 DPRINT("RSetServiceStatus() done\n");
896 return ERROR_SUCCESS
;
901 DWORD
RUnlockServiceDatabase(
902 handle_t BindingHandle
,
906 return ERROR_SUCCESS
;
911 DWORD
RNotifyBootConfigStatus(
912 handle_t BindingHandle
,
913 SVCCTL_HANDLEW lpMachineName
,
914 DWORD BootAcceptable
)
917 return ERROR_CALL_NOT_IMPLEMENTED
;
922 DWORD
RSetServiceBitsW(
923 handle_t BindingHandle
,
924 SC_RPC_HANDLE hServiceStatus
,
927 int bUpdateImmediately
,
931 return ERROR_CALL_NOT_IMPLEMENTED
;
936 DWORD
RChangeServiceConfigW(
937 handle_t BindingHandle
,
938 SC_RPC_HANDLE hService
,
941 DWORD dwErrorControl
,
942 LPWSTR lpBinaryPathName
,
943 LPWSTR lpLoadOrderGroup
,
945 LPBYTE lpDependencies
,
947 LPWSTR lpServiceStartName
,
950 LPWSTR lpDisplayName
)
952 DWORD dwError
= ERROR_SUCCESS
;
953 PSERVICE_HANDLE hSvc
;
954 PSERVICE lpService
= NULL
;
955 HKEY hServiceKey
= NULL
;
956 LPWSTR lpDisplayNameW
= NULL
;
958 DPRINT("RChangeServiceConfigW() called\n");
959 DPRINT("dwServiceType = %lu\n", dwServiceType
);
960 DPRINT("dwStartType = %lu\n", dwStartType
);
961 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
962 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
963 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
964 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
967 return ERROR_SHUTDOWN_IN_PROGRESS
;
969 hSvc
= (PSERVICE_HANDLE
)hService
;
970 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
972 DPRINT1("Invalid handle tag!\n");
973 return ERROR_INVALID_HANDLE
;
976 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
977 SERVICE_CHANGE_CONFIG
))
979 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
980 return ERROR_ACCESS_DENIED
;
983 lpService
= hSvc
->ServiceEntry
;
984 if (lpService
== NULL
)
986 DPRINT1("lpService == NULL!\n");
987 return ERROR_INVALID_HANDLE
;
990 /* FIXME: Lock database exclusively */
992 if (lpService
->bDeleted
)
994 /* FIXME: Unlock database */
995 DPRINT1("The service has already been marked for delete!\n");
996 return ERROR_SERVICE_MARKED_FOR_DELETE
;
999 /* Open the service key */
1000 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1003 if (dwError
!= ERROR_SUCCESS
)
1006 /* Write service data to the registry */
1007 /* Set the display name */
1008 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1010 RegSetValueExW(hServiceKey
,
1014 (LPBYTE
)lpDisplayName
,
1015 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1017 /* Update the display name */
1018 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1020 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1021 if (lpDisplayNameW
== NULL
)
1023 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1027 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1028 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1030 lpService
->lpDisplayName
= lpDisplayNameW
;
1033 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1035 /* Set the service type */
1036 dwError
= RegSetValueExW(hServiceKey
,
1040 (LPBYTE
)&dwServiceType
,
1042 if (dwError
!= ERROR_SUCCESS
)
1045 lpService
->Status
.dwServiceType
= dwServiceType
;
1048 if (dwStartType
!= SERVICE_NO_CHANGE
)
1050 /* Set the start value */
1051 dwError
= RegSetValueExW(hServiceKey
,
1055 (LPBYTE
)&dwStartType
,
1057 if (dwError
!= ERROR_SUCCESS
)
1060 lpService
->dwStartType
= dwStartType
;
1063 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1065 /* Set the error control value */
1066 dwError
= RegSetValueExW(hServiceKey
,
1070 (LPBYTE
)&dwErrorControl
,
1072 if (dwError
!= ERROR_SUCCESS
)
1075 lpService
->dwErrorControl
= dwErrorControl
;
1079 /* FIXME: set the new ImagePath value */
1081 /* Set the image path */
1082 if (dwServiceType
& SERVICE_WIN32
)
1084 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1086 dwError
= RegSetValueExW(hServiceKey
,
1090 (LPBYTE
)lpBinaryPathName
,
1091 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1092 if (dwError
!= ERROR_SUCCESS
)
1096 else if (dwServiceType
& SERVICE_DRIVER
)
1098 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1100 dwError
= RegSetValueExW(hServiceKey
,
1104 (LPBYTE
)lpImagePath
,
1105 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1106 if (dwError
!= ERROR_SUCCESS
)
1112 /* Set the group name */
1113 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1115 dwError
= RegSetValueExW(hServiceKey
,
1119 (LPBYTE
)lpLoadOrderGroup
,
1120 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1121 if (dwError
!= ERROR_SUCCESS
)
1123 /* FIXME: update lpService->lpServiceGroup */
1126 if (lpdwTagId
!= NULL
)
1128 dwError
= ScmAssignNewTag(lpService
);
1129 if (dwError
!= ERROR_SUCCESS
)
1132 dwError
= RegSetValueExW(hServiceKey
,
1136 (LPBYTE
)&lpService
->dwTag
,
1138 if (dwError
!= ERROR_SUCCESS
)
1141 *lpdwTagId
= lpService
->dwTag
;
1144 /* Write dependencies */
1145 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1147 dwError
= ScmWriteDependencies(hServiceKey
,
1148 (LPWSTR
)lpDependencies
,
1150 if (dwError
!= ERROR_SUCCESS
)
1154 if (lpPassword
!= NULL
)
1156 /* FIXME: Write password */
1159 /* FIXME: Unlock database */
1162 if (hServiceKey
!= NULL
)
1163 RegCloseKey(hServiceKey
);
1165 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1171 /* Create a path suitable for the bootloader out of the full path */
1173 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1175 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1178 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1179 OBJECT_ATTRIBUTES ObjectAttributes
;
1181 HANDLE SymbolicLinkHandle
;
1183 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1185 ServiceNameLen
= wcslen(CanonName
);
1187 /* First check, if it's already good */
1188 if (ServiceNameLen
> 12 &&
1189 !wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1191 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1192 if (*RelativeName
== NULL
)
1194 DPRINT1("Error allocating memory for boot driver name!\n");
1195 return ERROR_NOT_ENOUGH_MEMORY
;
1199 wcscpy(*RelativeName
, CanonName
);
1201 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1202 return ERROR_SUCCESS
;
1205 /* If it has %SystemRoot% prefix, substitute it to \System*/
1206 if (ServiceNameLen
> 13 &&
1207 !wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1209 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1210 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1212 if (*RelativeName
== NULL
)
1214 DPRINT1("Error allocating memory for boot driver name!\n");
1215 return ERROR_NOT_ENOUGH_MEMORY
;
1219 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1220 wcscat(*RelativeName
, CanonName
+ 13);
1222 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1223 return ERROR_SUCCESS
;
1226 /* Get buffer size needed for expanding env strings */
1227 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1229 if (BufferSize
<= 1)
1231 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1232 return ERROR_INVALID_ENVIRONMENT
;
1235 /* Allocate memory, since the size is known now */
1236 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1239 DPRINT1("Error allocating memory for boot driver name!\n");
1240 return ERROR_NOT_ENOUGH_MEMORY
;
1244 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1247 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1248 LocalFree(Expanded
);
1249 return ERROR_NOT_ENOUGH_MEMORY
;
1252 /* Convert to NY-style path */
1253 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1255 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1256 return ERROR_INVALID_ENVIRONMENT
;
1259 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1261 /* No need to keep the dos-path anymore */
1262 LocalFree(Expanded
);
1264 /* Copy it to the allocated place */
1265 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1268 DPRINT1("Error allocating memory for boot driver name!\n");
1269 return ERROR_NOT_ENOUGH_MEMORY
;
1272 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1273 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1274 Expanded
[ExpandedLen
] = 0;
1276 if (ServiceNameLen
> ExpandedLen
&&
1277 !wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1279 /* Only \SystemRoot\ is missing */
1280 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1281 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1282 if (*RelativeName
== NULL
)
1284 DPRINT1("Error allocating memory for boot driver name!\n");
1285 LocalFree(Expanded
);
1286 return ERROR_NOT_ENOUGH_MEMORY
;
1289 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1290 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1292 RtlFreeUnicodeString(&NtPathName
);
1293 return ERROR_SUCCESS
;
1296 /* The most complex case starts here */
1297 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1298 InitializeObjectAttributes(&ObjectAttributes
,
1300 OBJ_CASE_INSENSITIVE
,
1304 /* Open this symlink */
1305 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1307 if (NT_SUCCESS(Status
))
1309 LinkTarget
.Length
= 0;
1310 LinkTarget
.MaximumLength
= 0;
1312 DPRINT("Opened symbolic link object\n");
1314 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1315 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1317 /* Check if required buffer size is sane */
1318 if (BufferSize
> 0xFFFD)
1320 DPRINT1("Too large buffer required\n");
1323 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1324 LocalFree(Expanded
);
1325 return ERROR_NOT_ENOUGH_MEMORY
;
1328 /* Alloc the string */
1329 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1330 if (!LinkTarget
.Buffer
)
1332 DPRINT1("Unable to alloc buffer\n");
1333 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1334 LocalFree(Expanded
);
1335 return ERROR_NOT_ENOUGH_MEMORY
;
1338 /* Do a real query now */
1339 LinkTarget
.Length
= BufferSize
;
1340 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1342 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1343 if (NT_SUCCESS(Status
))
1345 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1347 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1348 if ((ServiceNameLen
> ExpandedLen
) &&
1349 !wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1351 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1352 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1354 if (*RelativeName
== NULL
)
1356 DPRINT1("Unable to alloc buffer\n");
1357 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1358 LocalFree(Expanded
);
1359 RtlFreeUnicodeString(&NtPathName
);
1360 return ERROR_NOT_ENOUGH_MEMORY
;
1363 /* Copy it over, substituting the first part
1365 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1366 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1369 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1370 LocalFree(Expanded
);
1371 RtlFreeUnicodeString(&NtPathName
);
1373 /* Return success */
1374 return ERROR_SUCCESS
;
1378 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1379 LocalFree(Expanded
);
1380 RtlFreeUnicodeString(&NtPathName
);
1381 return ERROR_INVALID_PARAMETER
;
1386 DPRINT1("Error, Status = %08X\n", Status
);
1387 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1388 LocalFree(Expanded
);
1389 RtlFreeUnicodeString(&NtPathName
);
1390 return ERROR_INVALID_PARAMETER
;
1395 DPRINT1("Error, Status = %08X\n", Status
);
1396 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1397 LocalFree(Expanded
);
1398 RtlFreeUnicodeString(&NtPathName
);
1399 return ERROR_INVALID_PARAMETER
;
1404 DPRINT1("Error, Status = %08X\n", Status
);
1405 LocalFree(Expanded
);
1406 return ERROR_INVALID_PARAMETER
;
1410 *RelativeName
= NULL
;
1411 return ERROR_INVALID_PARAMETER
;
1415 ScmCanonDriverImagePath(DWORD dwStartType
,
1416 wchar_t *lpServiceName
,
1417 wchar_t **lpCanonName
)
1419 DWORD ServiceNameLen
, Result
;
1420 UNICODE_STRING NtServiceName
;
1421 WCHAR
*RelativeName
;
1422 WCHAR
*SourceName
= lpServiceName
;
1424 /* Calculate the length of the service's name */
1425 ServiceNameLen
= wcslen(lpServiceName
);
1427 /* 12 is wcslen(L"\\SystemRoot\\") */
1428 if (ServiceNameLen
> 12 &&
1429 !wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1431 /* SystemRoot prefix is already included */
1433 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1435 if (*lpCanonName
== NULL
)
1437 DPRINT1("Error allocating memory for canonized service name!\n");
1438 return ERROR_NOT_ENOUGH_MEMORY
;
1441 /* If it's a boot-time driver, it must be systemroot relative */
1442 if (dwStartType
== SERVICE_BOOT_START
)
1446 wcscpy(*lpCanonName
, SourceName
);
1448 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1452 /* Check if it has %SystemRoot% (len=13) */
1453 if (ServiceNameLen
> 13 &&
1454 !wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1456 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1457 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1459 if (*lpCanonName
== NULL
)
1461 DPRINT1("Error allocating memory for canonized service name!\n");
1462 return ERROR_NOT_ENOUGH_MEMORY
;
1465 /* If it's a boot-time driver, it must be systemroot relative */
1466 if (dwStartType
== SERVICE_BOOT_START
)
1467 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1469 wcscat(*lpCanonName
, lpServiceName
+ 13);
1471 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1475 /* Check if it's a relative path name */
1476 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1478 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1480 if (*lpCanonName
== NULL
)
1482 DPRINT1("Error allocating memory for canonized service name!\n");
1483 return ERROR_NOT_ENOUGH_MEMORY
;
1486 /* Just copy it over without changing */
1487 wcscpy(*lpCanonName
, lpServiceName
);
1492 /* It seems to be a DOS path, convert it */
1493 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1495 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1496 return ERROR_INVALID_PARAMETER
;
1499 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1501 if (*lpCanonName
== NULL
)
1503 DPRINT1("Error allocating memory for canonized service name!\n");
1504 RtlFreeUnicodeString(&NtServiceName
);
1505 return ERROR_NOT_ENOUGH_MEMORY
;
1508 /* Copy the string */
1509 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1511 /* The unicode string is not needed anymore */
1512 RtlFreeUnicodeString(&NtServiceName
);
1514 if (dwStartType
!= SERVICE_BOOT_START
)
1516 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1520 /* The service is boot-started, so must be relative */
1521 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1524 /* There is a problem, free name and return */
1525 LocalFree(*lpCanonName
);
1526 DPRINT1("Error converting named!\n");
1530 ASSERT(RelativeName
);
1532 /* Copy that string */
1533 wcscpy(*lpCanonName
, RelativeName
+ 12);
1535 /* Free the allocated buffer */
1536 LocalFree(RelativeName
);
1538 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1546 DWORD
RCreateServiceW(
1547 handle_t BindingHandle
,
1548 SC_RPC_HANDLE hSCManager
,
1549 LPWSTR lpServiceName
,
1550 LPWSTR lpDisplayName
,
1551 DWORD dwDesiredAccess
,
1552 DWORD dwServiceType
,
1554 DWORD dwErrorControl
,
1555 LPWSTR lpBinaryPathName
,
1556 LPWSTR lpLoadOrderGroup
,
1558 LPBYTE lpDependencies
,
1560 LPWSTR lpServiceStartName
,
1563 LPSC_RPC_HANDLE lpServiceHandle
)
1565 PMANAGER_HANDLE hManager
;
1566 DWORD dwError
= ERROR_SUCCESS
;
1567 PSERVICE lpService
= NULL
;
1568 SC_HANDLE hServiceHandle
= NULL
;
1569 LPWSTR lpImagePath
= NULL
;
1570 HKEY hServiceKey
= NULL
;
1572 DPRINT("RCreateServiceW() called\n");
1573 DPRINT("lpServiceName = %S\n", lpServiceName
);
1574 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1575 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1576 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1577 DPRINT("dwStartType = %lu\n", dwStartType
);
1578 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1579 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1580 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1583 return ERROR_SHUTDOWN_IN_PROGRESS
;
1585 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1586 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1588 DPRINT1("Invalid manager handle!\n");
1589 return ERROR_INVALID_HANDLE
;
1592 /* Check access rights */
1593 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1594 SC_MANAGER_CREATE_SERVICE
))
1596 DPRINT1("Insufficient access rights! 0x%lx\n",
1597 hManager
->Handle
.DesiredAccess
);
1598 return ERROR_ACCESS_DENIED
;
1601 if (wcslen(lpServiceName
) == 0)
1603 return ERROR_INVALID_NAME
;
1606 if (wcslen(lpBinaryPathName
) == 0)
1608 return ERROR_INVALID_PARAMETER
;
1611 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1612 (lpServiceStartName
))
1614 return ERROR_INVALID_PARAMETER
;
1617 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1618 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1619 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1621 return ERROR_INVALID_PARAMETER
;
1624 if (dwStartType
> SERVICE_DISABLED
)
1626 return ERROR_INVALID_PARAMETER
;
1629 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1632 /* check if it is marked for deletion */
1633 if (lpService
->bDeleted
)
1634 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1635 /* Return Error exist */
1636 return ERROR_SERVICE_EXISTS
;
1639 if (lpDisplayName
!= NULL
&&
1640 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1641 return ERROR_DUPLICATE_SERVICE_NAME
;
1643 if (dwServiceType
& SERVICE_DRIVER
)
1645 dwError
= ScmCanonDriverImagePath(dwStartType
,
1648 if (dwError
!= ERROR_SUCCESS
)
1653 if (dwStartType
== SERVICE_BOOT_START
||
1654 dwStartType
== SERVICE_SYSTEM_START
)
1656 return ERROR_INVALID_PARAMETER
;
1660 /* Allocate a new service entry */
1661 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1663 if (dwError
!= ERROR_SUCCESS
)
1666 /* Fill the new service entry */
1667 lpService
->Status
.dwServiceType
= dwServiceType
;
1668 lpService
->dwStartType
= dwStartType
;
1669 lpService
->dwErrorControl
= dwErrorControl
;
1671 /* Fill the display name */
1672 if (lpDisplayName
!= NULL
&&
1673 *lpDisplayName
!= 0 &&
1674 wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1676 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1677 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1678 if (lpService
->lpDisplayName
== NULL
)
1680 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1683 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1686 /* Assign the service to a group */
1687 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1689 dwError
= ScmSetServiceGroup(lpService
,
1691 if (dwError
!= ERROR_SUCCESS
)
1695 /* Assign a new tag */
1696 if (lpdwTagId
!= NULL
)
1698 dwError
= ScmAssignNewTag(lpService
);
1699 if (dwError
!= ERROR_SUCCESS
)
1703 /* Write service data to the registry */
1704 /* Create the service key */
1705 dwError
= ScmCreateServiceKey(lpServiceName
,
1708 if (dwError
!= ERROR_SUCCESS
)
1711 /* Set the display name */
1712 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1714 RegSetValueExW(hServiceKey
,
1718 (LPBYTE
)lpDisplayName
,
1719 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1722 /* Set the service type */
1723 dwError
= RegSetValueExW(hServiceKey
,
1727 (LPBYTE
)&dwServiceType
,
1729 if (dwError
!= ERROR_SUCCESS
)
1732 /* Set the start value */
1733 dwError
= RegSetValueExW(hServiceKey
,
1737 (LPBYTE
)&dwStartType
,
1739 if (dwError
!= ERROR_SUCCESS
)
1742 /* Set the error control value */
1743 dwError
= RegSetValueExW(hServiceKey
,
1747 (LPBYTE
)&dwErrorControl
,
1749 if (dwError
!= ERROR_SUCCESS
)
1752 /* Set the image path */
1753 if (dwServiceType
& SERVICE_WIN32
)
1755 dwError
= RegSetValueExW(hServiceKey
,
1759 (LPBYTE
)lpBinaryPathName
,
1760 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1761 if (dwError
!= ERROR_SUCCESS
)
1764 else if (dwServiceType
& SERVICE_DRIVER
)
1766 dwError
= RegSetValueExW(hServiceKey
,
1770 (LPBYTE
)lpImagePath
,
1771 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1772 if (dwError
!= ERROR_SUCCESS
)
1776 /* Set the group name */
1777 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1779 dwError
= RegSetValueExW(hServiceKey
,
1783 (LPBYTE
)lpLoadOrderGroup
,
1784 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1785 if (dwError
!= ERROR_SUCCESS
)
1789 if (lpdwTagId
!= NULL
)
1791 dwError
= RegSetValueExW(hServiceKey
,
1795 (LPBYTE
)&lpService
->dwTag
,
1797 if (dwError
!= ERROR_SUCCESS
)
1801 /* Write dependencies */
1802 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1804 dwError
= ScmWriteDependencies(hServiceKey
,
1805 (LPWSTR
)lpDependencies
,
1807 if (dwError
!= ERROR_SUCCESS
)
1811 /* If a non driver and NULL for lpServiceName, write ObjectName as LocalSystem */
1812 if ((dwServiceType
& SERVICE_WIN32
) && (!lpServiceName
))
1814 dwError
= RegSetValueExW(hServiceKey
,
1818 (LPBYTE
)L
"LocalSystem",
1820 if (dwError
!= ERROR_SUCCESS
)
1824 if (lpPassword
!= NULL
)
1826 /* FIXME: Write password */
1829 dwError
= ScmCreateServiceHandle(lpService
,
1831 if (dwError
!= ERROR_SUCCESS
)
1834 dwError
= ScmCheckAccess(hServiceHandle
,
1836 if (dwError
!= ERROR_SUCCESS
)
1840 if (hServiceKey
!= NULL
)
1841 RegCloseKey(hServiceKey
);
1843 if (dwError
== ERROR_SUCCESS
)
1845 DPRINT("hService %p\n", hServiceHandle
);
1846 *lpServiceHandle
= (unsigned long)hServiceHandle
; /* FIXME: 64 bit portability */
1848 if (lpdwTagId
!= NULL
)
1849 *lpdwTagId
= lpService
->dwTag
;
1853 /* Release the display name buffer */
1854 if (lpService
->lpServiceName
!= NULL
)
1855 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1859 /* Remove the service handle */
1860 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
1863 if (lpService
!= NULL
)
1865 /* FIXME: remove the service entry */
1869 if (lpImagePath
!= NULL
)
1870 HeapFree(GetProcessHeap(), 0, lpImagePath
);
1872 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
1879 DWORD
REnumDependentServicesW(
1880 handle_t BindingHandle
,
1881 SC_RPC_HANDLE hService
,
1882 DWORD dwServiceState
,
1885 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
1886 LPBOUNDED_DWORD_256K lpServicesReturned
)
1888 DWORD dwError
= ERROR_SUCCESS
;
1889 DWORD dwServicesReturned
= 0;
1890 DWORD dwServiceCount
;
1891 HKEY hServicesKey
= NULL
;
1892 LPSC_RPC_HANDLE hSCObject
;
1893 PSERVICE_HANDLE hSvc
;
1894 PSERVICE lpService
= NULL
;
1895 PSERVICE
*lpServicesArray
= NULL
;
1896 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
1899 *pcbBytesNeeded
= 0;
1900 *lpServicesReturned
= 0;
1902 DPRINT("REnumDependentServicesW() called\n");
1904 hSCObject
= &hService
;
1905 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
1906 lpService
= hSvc
->ServiceEntry
;
1908 /* Check access rights */
1909 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1910 SC_MANAGER_ENUMERATE_SERVICE
))
1912 DPRINT1("Insufficient access rights! 0x%lx\n",
1913 hSvc
->Handle
.DesiredAccess
);
1914 return ERROR_ACCESS_DENIED
;
1917 /* Open the Services Reg key */
1918 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
1919 L
"System\\CurrentControlSet\\Services",
1923 if (dwError
!= ERROR_SUCCESS
)
1926 /* First determine the bytes needed and get the number of dependent services */
1927 dwError
= Int_EnumDependentServicesW(hServicesKey
,
1932 &dwServicesReturned
);
1933 if (dwError
!= ERROR_SUCCESS
)
1936 /* If buffer size is less than the bytes needed or pointer is null */
1937 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
1939 dwError
= ERROR_MORE_DATA
;
1943 /* Allocate memory for array of service pointers */
1944 lpServicesArray
= HeapAlloc(GetProcessHeap(),
1946 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
1947 if (!lpServicesArray
)
1949 DPRINT1("Could not allocate a buffer!!\n");
1950 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1954 dwServicesReturned
= 0;
1955 *pcbBytesNeeded
= 0;
1957 dwError
= Int_EnumDependentServicesW(hServicesKey
,
1962 &dwServicesReturned
);
1963 if (dwError
!= ERROR_SUCCESS
)
1968 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
1969 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
1971 /* Copy EnumDepenedentService to Buffer */
1972 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
1974 lpService
= lpServicesArray
[dwServiceCount
];
1976 /* Copy status info */
1977 memcpy(&lpServicesPtr
->ServiceStatus
,
1979 sizeof(SERVICE_STATUS
));
1981 /* Copy display name */
1982 wcscpy(lpStr
, lpService
->lpDisplayName
);
1983 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
1984 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
1986 /* Copy service name */
1987 wcscpy(lpStr
, lpService
->lpServiceName
);
1988 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
1989 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
1994 *lpServicesReturned
= dwServicesReturned
;
1997 if (lpServicesArray
!= NULL
)
1998 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2000 RegCloseKey(hServicesKey
);
2002 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2009 DWORD
REnumServicesStatusW(
2010 handle_t BindingHandle
,
2011 SC_RPC_HANDLE hSCManager
,
2012 DWORD dwServiceType
,
2013 DWORD dwServiceState
,
2016 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2017 LPBOUNDED_DWORD_256K lpServicesReturned
,
2018 LPBOUNDED_DWORD_256K lpResumeHandle
)
2020 PMANAGER_HANDLE hManager
;
2022 DWORD dwError
= ERROR_SUCCESS
;
2023 PLIST_ENTRY ServiceEntry
;
2024 PSERVICE CurrentService
;
2026 DWORD dwRequiredSize
;
2027 DWORD dwServiceCount
;
2029 DWORD dwLastResumeCount
;
2030 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2033 DPRINT("REnumServicesStatusW() called\n");
2036 return ERROR_SHUTDOWN_IN_PROGRESS
;
2038 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2039 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2041 DPRINT1("Invalid manager handle!\n");
2042 return ERROR_INVALID_HANDLE
;
2045 /* Check access rights */
2046 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2047 SC_MANAGER_ENUMERATE_SERVICE
))
2049 DPRINT1("Insufficient access rights! 0x%lx\n",
2050 hManager
->Handle
.DesiredAccess
);
2051 return ERROR_ACCESS_DENIED
;
2054 *pcbBytesNeeded
= 0;
2055 *lpServicesReturned
= 0;
2057 dwLastResumeCount
= *lpResumeHandle
;
2059 /* FIXME: Lock the service list shared */
2061 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2062 if (lpService
== NULL
)
2064 dwError
= ERROR_SUCCESS
;
2071 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2072 ServiceEntry
!= &ServiceListHead
;
2073 ServiceEntry
= ServiceEntry
->Flink
)
2075 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2079 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2082 dwState
= SERVICE_ACTIVE
;
2083 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2084 dwState
= SERVICE_INACTIVE
;
2086 if ((dwState
& dwServiceState
) == 0)
2089 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2090 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2091 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2093 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2095 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2099 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2100 dwRequiredSize
+= dwSize
;
2102 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2105 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2106 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2109 ServiceEntry
!= &ServiceListHead
;
2110 ServiceEntry
= ServiceEntry
->Flink
)
2112 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2116 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2119 dwState
= SERVICE_ACTIVE
;
2120 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2121 dwState
= SERVICE_INACTIVE
;
2123 if ((dwState
& dwServiceState
) == 0)
2126 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2127 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2128 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2130 dwError
= ERROR_MORE_DATA
;
2133 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2135 *lpResumeHandle
= dwLastResumeCount
;
2136 *lpServicesReturned
= dwServiceCount
;
2137 *pcbBytesNeeded
= dwRequiredSize
;
2139 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2140 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2141 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2144 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2145 ServiceEntry
!= &ServiceListHead
;
2146 ServiceEntry
= ServiceEntry
->Flink
)
2148 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2152 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2155 dwState
= SERVICE_ACTIVE
;
2156 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2157 dwState
= SERVICE_INACTIVE
;
2159 if ((dwState
& dwServiceState
) == 0)
2162 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2163 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2164 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2166 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2169 /* Copy the service name */
2170 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2171 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2172 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2174 /* Copy the display name */
2175 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2176 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2177 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2179 /* Copy the status information */
2180 memcpy(&lpStatusPtr
->ServiceStatus
,
2181 &CurrentService
->Status
,
2182 sizeof(SERVICE_STATUS
));
2185 dwRequiredSize
+= dwSize
;
2189 /* FIXME: Unlock the service list */
2191 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2198 DWORD
ROpenSCManagerW(
2199 handle_t BindingHandle
,
2200 LPWSTR lpMachineName
,
2201 LPWSTR lpDatabaseName
,
2202 DWORD dwDesiredAccess
,
2203 LPSC_RPC_HANDLE lpScHandle
)
2208 DPRINT("ROpenSCManagerW() called\n");
2209 DPRINT("lpMachineName = %p\n", lpMachineName
);
2210 DPRINT("lpMachineName: %S\n", lpMachineName
);
2211 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2212 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2213 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2216 return ERROR_SHUTDOWN_IN_PROGRESS
;
2219 return ERROR_INVALID_PARAMETER
;
2221 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2223 if (dwError
!= ERROR_SUCCESS
)
2225 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2229 /* Check the desired access */
2230 dwError
= ScmCheckAccess(hHandle
,
2231 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2232 if (dwError
!= ERROR_SUCCESS
)
2234 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2235 HeapFree(GetProcessHeap(), 0, hHandle
);
2239 *lpScHandle
= (unsigned long)hHandle
; /* FIXME: 64 bit portability */
2240 DPRINT("*hScm = %p\n", *lpScHandle
);
2242 DPRINT("ROpenSCManagerW() done\n");
2244 return ERROR_SUCCESS
;
2249 DWORD
ROpenServiceW(
2250 handle_t BindingHandle
,
2251 SC_RPC_HANDLE hSCManager
,
2252 LPWSTR lpServiceName
,
2253 DWORD dwDesiredAccess
,
2254 LPSC_RPC_HANDLE lpServiceHandle
)
2257 PMANAGER_HANDLE hManager
;
2261 DPRINT("ROpenServiceW() called\n");
2262 DPRINT("hSCManager = %p\n", hSCManager
);
2263 DPRINT("lpServiceName = %p\n", lpServiceName
);
2264 DPRINT("lpServiceName: %S\n", lpServiceName
);
2265 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2268 return ERROR_SHUTDOWN_IN_PROGRESS
;
2270 if (!lpServiceHandle
)
2271 return ERROR_INVALID_PARAMETER
;
2274 return ERROR_INVALID_ADDRESS
;
2276 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2277 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2279 DPRINT1("Invalid manager handle!\n");
2280 return ERROR_INVALID_HANDLE
;
2283 /* FIXME: Lock the service list */
2285 /* Get service database entry */
2286 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2287 if (lpService
== NULL
)
2289 DPRINT("Could not find a service!\n");
2290 return ERROR_SERVICE_DOES_NOT_EXIST
;
2293 /* Create a service handle */
2294 dwError
= ScmCreateServiceHandle(lpService
,
2296 if (dwError
!= ERROR_SUCCESS
)
2298 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2302 /* Check the desired access */
2303 dwError
= ScmCheckAccess(hHandle
,
2305 if (dwError
!= ERROR_SUCCESS
)
2307 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2308 HeapFree(GetProcessHeap(), 0, hHandle
);
2312 *lpServiceHandle
= (unsigned long)hHandle
; /* FIXME: 64 bit portability */
2313 DPRINT("*hService = %p\n", *lpServiceHandle
);
2315 DPRINT("ROpenServiceW() done\n");
2317 return ERROR_SUCCESS
;
2322 DWORD
RQueryServiceConfigW(
2323 handle_t BindingHandle
,
2324 SC_RPC_HANDLE hService
,
2325 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2327 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2329 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2330 DWORD dwError
= ERROR_SUCCESS
;
2331 PSERVICE_HANDLE hSvc
;
2332 PSERVICE lpService
= NULL
;
2333 HKEY hServiceKey
= NULL
;
2334 LPWSTR lpImagePath
= NULL
;
2335 LPWSTR lpServiceStartName
= NULL
;
2336 DWORD dwRequiredSize
;
2337 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2338 WCHAR lpEmptyString
[] = {0,0};
2341 DPRINT("RQueryServiceConfigW() called\n");
2344 return ERROR_SHUTDOWN_IN_PROGRESS
;
2346 hSvc
= (PSERVICE_HANDLE
)hService
;
2347 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2349 DPRINT1("Invalid handle tag!\n");
2350 return ERROR_INVALID_HANDLE
;
2353 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2354 SERVICE_QUERY_CONFIG
))
2356 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2357 return ERROR_ACCESS_DENIED
;
2360 lpService
= hSvc
->ServiceEntry
;
2361 if (lpService
== NULL
)
2363 DPRINT1("lpService == NULL!\n");
2364 return ERROR_INVALID_HANDLE
;
2367 /* FIXME: Lock the service database shared */
2369 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2372 if (dwError
!= ERROR_SUCCESS
)
2375 dwError
= ScmReadString(hServiceKey
,
2378 if (dwError
!= ERROR_SUCCESS
)
2381 ScmReadString(hServiceKey
,
2383 &lpServiceStartName
);
2385 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2387 if (lpImagePath
!= NULL
)
2388 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2390 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2392 if (lpService
->lpGroup
!= NULL
)
2393 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2395 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2397 /* FIXME: Add Dependencies length*/
2399 if (lpServiceStartName
!= NULL
)
2400 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2402 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2404 if (lpService
->lpDisplayName
!= NULL
)
2405 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2407 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2409 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2411 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2415 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2416 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2417 lpConfig
->dwStartType
= lpService
->dwStartType
;
2418 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2419 lpConfig
->dwTagId
= lpService
->dwTag
;
2421 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2423 if (lpImagePath
!= NULL
)
2425 wcscpy(lpStr
, lpImagePath
);
2429 wcscpy(lpStr
, lpEmptyString
);
2432 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2433 lpStr
+= (wcslen(lpStr
) + 1);
2435 if (lpService
->lpGroup
!= NULL
)
2437 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2441 wcscpy(lpStr
, lpEmptyString
);
2444 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2445 lpStr
+= (wcslen(lpStr
) + 1);
2447 /* FIXME: Append Dependencies */
2448 wcscpy(lpStr
, lpEmptyString
);
2450 lpStr
+= (wcslen(lpStr
) + 1);
2451 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2453 if (lpServiceStartName
!= NULL
)
2455 wcscpy(lpStr
, lpServiceStartName
);
2459 wcscpy(lpStr
, lpEmptyString
);
2462 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2463 lpStr
+= (wcslen(lpStr
) + 1);
2465 if (lpService
->lpDisplayName
!= NULL
)
2467 wcscpy(lpStr
, lpService
->lpDisplayName
);
2471 wcscpy(lpStr
, lpEmptyString
);
2474 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2477 if (pcbBytesNeeded
!= NULL
)
2478 *pcbBytesNeeded
= dwRequiredSize
;
2481 if (lpImagePath
!= NULL
)
2482 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2484 if (lpServiceStartName
!= NULL
)
2485 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2487 if (hServiceKey
!= NULL
)
2488 RegCloseKey(hServiceKey
);
2490 /* FIXME: Unlock the service database */
2492 DPRINT("RQueryServiceConfigW() done\n");
2499 DWORD
RQueryServiceLockStatusW(
2500 handle_t BindingHandle
,
2501 SC_RPC_HANDLE hSCManager
,
2502 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2504 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2507 return ERROR_CALL_NOT_IMPLEMENTED
;
2512 DWORD
RStartServiceW(
2513 handle_t BindingHandle
,
2514 SC_RPC_HANDLE hService
,
2516 LPSTRING_PTRSW argv
)
2518 DWORD dwError
= ERROR_SUCCESS
;
2519 PSERVICE_HANDLE hSvc
;
2520 PSERVICE lpService
= NULL
;
2522 DPRINT("RStartServiceW() called\n");
2525 return ERROR_SHUTDOWN_IN_PROGRESS
;
2527 hSvc
= (PSERVICE_HANDLE
)hService
;
2528 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2530 DPRINT1("Invalid handle tag!\n");
2531 return ERROR_INVALID_HANDLE
;
2534 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2537 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2538 return ERROR_ACCESS_DENIED
;
2541 lpService
= hSvc
->ServiceEntry
;
2542 if (lpService
== NULL
)
2544 DPRINT1("lpService == NULL!\n");
2545 return ERROR_INVALID_HANDLE
;
2548 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2549 return ERROR_SERVICE_DISABLED
;
2551 if (lpService
->bDeleted
)
2552 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2559 /* Start the service */
2560 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2567 DWORD
RGetServiceDisplayNameW(
2568 handle_t BindingHandle
,
2569 SC_RPC_HANDLE hSCManager
,
2570 LPWSTR lpServiceName
,
2571 LPWSTR lpDisplayName
,
2574 // PMANAGER_HANDLE hManager;
2579 DPRINT("RGetServiceDisplayNameW() called\n");
2580 DPRINT("hSCManager = %p\n", hSCManager
);
2581 DPRINT("lpServiceName: %S\n", lpServiceName
);
2582 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2583 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2585 // hManager = (PMANAGER_HANDLE)hSCManager;
2586 // if (hManager->Handle.Tag != MANAGER_TAG)
2588 // DPRINT1("Invalid manager handle!\n");
2589 // return ERROR_INVALID_HANDLE;
2592 /* Get service database entry */
2593 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2594 if (lpService
== NULL
)
2596 DPRINT1("Could not find a service!\n");
2598 /* If the service could not be found and lpcchBuffer is 0, windows
2599 puts null in lpDisplayName and puts 1 in lpcchBuffer */
2600 if (*lpcchBuffer
== 0)
2603 *lpDisplayName
= '\0';
2606 return ERROR_SERVICE_DOES_NOT_EXIST
;
2609 if (!lpService
->lpDisplayName
)
2611 dwLength
= wcslen(lpService
->lpServiceName
);
2613 if (lpServiceName
!= NULL
&&
2614 *lpcchBuffer
> dwLength
)
2616 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2621 dwLength
= wcslen(lpService
->lpDisplayName
);
2623 if (lpDisplayName
!= NULL
&&
2624 *lpcchBuffer
> dwLength
)
2626 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2630 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2632 *lpcchBuffer
= dwLength
;
2639 DWORD
RGetServiceKeyNameW(
2640 handle_t BindingHandle
,
2641 SC_RPC_HANDLE hSCManager
,
2642 LPWSTR lpDisplayName
,
2643 LPWSTR lpServiceName
,
2646 // PMANAGER_HANDLE hManager;
2651 DPRINT("RGetServiceKeyNameW() called\n");
2652 DPRINT("hSCManager = %p\n", hSCManager
);
2653 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2654 DPRINT("lpServiceName: %p\n", lpServiceName
);
2655 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2657 // hManager = (PMANAGER_HANDLE)hSCManager;
2658 // if (hManager->Handle.Tag != MANAGER_TAG)
2660 // DPRINT1("Invalid manager handle!\n");
2661 // return ERROR_INVALID_HANDLE;
2664 /* Get service database entry */
2665 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2666 if (lpService
== NULL
)
2668 DPRINT1("Could not find a service!\n");
2670 /* If the service could not be found and lpcchBuffer is 0, windows
2671 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2672 if (*lpcchBuffer
== 0)
2675 *lpServiceName
= '\0';
2678 return ERROR_SERVICE_DOES_NOT_EXIST
;
2681 dwLength
= wcslen(lpService
->lpServiceName
);
2683 if (lpServiceName
!= NULL
&&
2684 *lpcchBuffer
> dwLength
)
2686 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2687 *lpcchBuffer
= dwLength
;
2688 return ERROR_SUCCESS
;
2691 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2693 *lpcchBuffer
= dwLength
* 2;
2700 DWORD
RSetServiceBitsA(
2701 handle_t BindingHandle
,
2702 SC_RPC_HANDLE hServiceStatus
,
2703 DWORD dwServiceBits
,
2705 int bUpdateImmediately
,
2709 return ERROR_CALL_NOT_IMPLEMENTED
;
2714 DWORD
RChangeServiceConfigA(
2715 handle_t BindingHandle
,
2716 SC_RPC_HANDLE hService
,
2717 DWORD dwServiceType
,
2719 DWORD dwErrorControl
,
2720 LPSTR lpBinaryPathName
,
2721 LPSTR lpLoadOrderGroup
,
2723 LPSTR lpDependencies
,
2725 LPSTR lpServiceStartName
,
2728 LPSTR lpDisplayName
)
2730 DWORD dwError
= ERROR_SUCCESS
;
2731 PSERVICE_HANDLE hSvc
;
2732 PSERVICE lpService
= NULL
;
2733 HKEY hServiceKey
= NULL
;
2734 LPWSTR lpDisplayNameW
= NULL
;
2735 // LPWSTR lpBinaryPathNameW = NULL;
2736 LPWSTR lpLoadOrderGroupW
= NULL
;
2737 LPWSTR lpDependenciesW
= NULL
;
2738 // LPWSTR lpPasswordW = NULL;
2740 DPRINT("RChangeServiceConfigA() called\n");
2741 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2742 DPRINT("dwStartType = %lu\n", dwStartType
);
2743 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2744 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2745 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2746 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2749 return ERROR_SHUTDOWN_IN_PROGRESS
;
2751 hSvc
= (PSERVICE_HANDLE
)hService
;
2752 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2754 DPRINT1("Invalid handle tag!\n");
2755 return ERROR_INVALID_HANDLE
;
2758 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2759 SERVICE_CHANGE_CONFIG
))
2761 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2762 return ERROR_ACCESS_DENIED
;
2765 lpService
= hSvc
->ServiceEntry
;
2766 if (lpService
== NULL
)
2768 DPRINT1("lpService == NULL!\n");
2769 return ERROR_INVALID_HANDLE
;
2772 /* FIXME: Lock database exclusively */
2774 if (lpService
->bDeleted
)
2776 /* FIXME: Unlock database */
2777 DPRINT1("The service has already been marked for delete!\n");
2778 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2781 /* Open the service key */
2782 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2785 if (dwError
!= ERROR_SUCCESS
)
2788 /* Write service data to the registry */
2790 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2792 /* Set the display name */
2793 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2795 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2796 if (lpDisplayNameW
== NULL
)
2798 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2802 MultiByteToWideChar(CP_ACP
,
2807 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2809 RegSetValueExW(hServiceKey
,
2813 (LPBYTE
)lpDisplayNameW
,
2814 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2816 /* Update lpService->lpDisplayName */
2817 if (lpService
->lpDisplayName
)
2818 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2820 lpService
->lpDisplayName
= lpDisplayNameW
;
2823 if (dwServiceType
!= SERVICE_NO_CHANGE
)
2825 /* Set the service type */
2826 dwError
= RegSetValueExW(hServiceKey
,
2830 (LPBYTE
)&dwServiceType
,
2832 if (dwError
!= ERROR_SUCCESS
)
2835 lpService
->Status
.dwServiceType
= dwServiceType
;
2838 if (dwStartType
!= SERVICE_NO_CHANGE
)
2840 /* Set the start value */
2841 dwError
= RegSetValueExW(hServiceKey
,
2845 (LPBYTE
)&dwStartType
,
2847 if (dwError
!= ERROR_SUCCESS
)
2850 lpService
->dwStartType
= dwStartType
;
2853 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
2855 /* Set the error control value */
2856 dwError
= RegSetValueExW(hServiceKey
,
2860 (LPBYTE
)&dwErrorControl
,
2862 if (dwError
!= ERROR_SUCCESS
)
2865 lpService
->dwErrorControl
= dwErrorControl
;
2869 /* FIXME: set the new ImagePath value */
2871 /* Set the image path */
2872 if (dwServiceType
& SERVICE_WIN32
)
2874 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
2876 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
2877 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, (wcslen(lpBinaryPathNameW
)+1) * sizeof(WCHAR
));
2878 dwError
= RegSetValueExW(hServiceKey
,
2882 (LPBYTE
)lpBinaryPathNameW
,
2883 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
2884 if (dwError
!= ERROR_SUCCESS
)
2888 else if (dwServiceType
& SERVICE_DRIVER
)
2890 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
2892 dwError
= RegSetValueExW(hServiceKey
,
2896 (LPBYTE
)lpImagePath
,
2897 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
2898 if (dwError
!= ERROR_SUCCESS
)
2904 /* Set the group name */
2905 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2907 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
2909 (strlen(lpLoadOrderGroup
)+1) * sizeof(WCHAR
));
2910 if (lpLoadOrderGroupW
== NULL
)
2912 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2916 MultiByteToWideChar(CP_ACP
,
2921 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
2923 dwError
= RegSetValueExW(hServiceKey
,
2927 (LPBYTE
)lpLoadOrderGroupW
,
2928 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
2929 if (dwError
!= ERROR_SUCCESS
)
2932 /* FIXME: Update lpService->lpServiceGroup */
2934 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
2937 if (lpdwTagId
!= NULL
)
2939 dwError
= ScmAssignNewTag(lpService
);
2940 if (dwError
!= ERROR_SUCCESS
)
2943 dwError
= RegSetValueExW(hServiceKey
,
2947 (LPBYTE
)&lpService
->dwTag
,
2949 if (dwError
!= ERROR_SUCCESS
)
2952 *lpdwTagId
= lpService
->dwTag
;
2955 /* Write dependencies */
2956 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2958 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
2960 (strlen(lpDependencies
)+1) * sizeof(WCHAR
));
2961 if (lpDependenciesW
== NULL
)
2963 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2967 MultiByteToWideChar(CP_ACP
,
2972 (wcslen(lpDependenciesW
)+1) * sizeof(WCHAR
));
2974 dwError
= ScmWriteDependencies(hServiceKey
,
2975 (LPWSTR
)lpDependenciesW
,
2978 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
2981 if (lpPassword
!= NULL
)
2983 /* FIXME: Write password */
2986 /* FIXME: Unlock database */
2989 if (hServiceKey
!= NULL
)
2990 RegCloseKey(hServiceKey
);
2992 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
2999 DWORD
RCreateServiceA(
3000 handle_t BindingHandle
,
3001 SC_RPC_HANDLE hSCManager
,
3002 LPSTR lpServiceName
,
3003 LPSTR lpDisplayName
,
3004 DWORD dwDesiredAccess
,
3005 DWORD dwServiceType
,
3007 DWORD dwErrorControl
,
3008 LPSTR lpBinaryPathName
,
3009 LPSTR lpLoadOrderGroup
,
3011 LPBYTE lpDependencies
,
3013 LPSTR lpServiceStartName
,
3016 LPSC_RPC_HANDLE lpServiceHandle
)
3019 return ERROR_CALL_NOT_IMPLEMENTED
;
3024 DWORD
REnumDependentServicesA(
3025 handle_t BindingHandle
,
3026 SC_RPC_HANDLE hService
,
3027 DWORD dwServiceState
,
3030 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3031 LPBOUNDED_DWORD_256K lpServicesReturned
)
3033 DWORD dwError
= ERROR_SUCCESS
;
3034 DWORD dwServicesReturned
= 0;
3035 DWORD dwServiceCount
;
3036 HKEY hServicesKey
= NULL
;
3037 LPSC_RPC_HANDLE hSCObject
;
3038 PSERVICE_HANDLE hSvc
;
3039 PSERVICE lpService
= NULL
;
3040 PSERVICE
*lpServicesArray
= NULL
;
3041 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3044 *pcbBytesNeeded
= 0;
3045 *lpServicesReturned
= 0;
3047 DPRINT("REnumDependentServicesA() called\n");
3049 hSCObject
= &hService
;
3050 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3051 lpService
= hSvc
->ServiceEntry
;
3053 /* Check access rights */
3054 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3055 SC_MANAGER_ENUMERATE_SERVICE
))
3057 DPRINT1("Insufficient access rights! 0x%lx\n",
3058 hSvc
->Handle
.DesiredAccess
);
3059 return ERROR_ACCESS_DENIED
;
3062 /* Open the Services Reg key */
3063 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3064 L
"System\\CurrentControlSet\\Services",
3069 if (dwError
!= ERROR_SUCCESS
) return dwError
;
3071 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3072 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3073 are the same for both. Verified in WINXP. */
3075 /* First determine the bytes needed and get the number of dependent services*/
3076 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3081 &dwServicesReturned
);
3082 if (dwError
!= ERROR_SUCCESS
)
3085 /* If buffer size is less than the bytes needed or pointer is null*/
3086 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3088 dwError
= ERROR_MORE_DATA
;
3092 /* Allocate memory for array of service pointers */
3093 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3095 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3096 if (!lpServicesArray
)
3098 DPRINT1("Could not allocate a buffer!!\n");
3099 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3103 dwServicesReturned
= 0;
3104 *pcbBytesNeeded
= 0;
3106 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3111 &dwServicesReturned
);
3112 if (dwError
!= ERROR_SUCCESS
)
3117 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3118 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3120 /* Copy EnumDepenedentService to Buffer */
3121 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3123 lpService
= lpServicesArray
[dwServiceCount
];
3125 /* Copy the status info */
3126 memcpy(&lpServicesPtr
->ServiceStatus
,
3128 sizeof(SERVICE_STATUS
));
3130 /* Copy display name */
3131 WideCharToMultiByte(CP_ACP
,
3133 lpService
->lpDisplayName
,
3136 wcslen(lpService
->lpDisplayName
),
3139 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3140 lpStr
+= strlen(lpStr
) + 1;
3142 /* Copy service name */
3143 WideCharToMultiByte(CP_ACP
,
3145 lpService
->lpServiceName
,
3148 wcslen(lpService
->lpServiceName
),
3151 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3152 lpStr
+= strlen(lpStr
) + 1;
3157 *lpServicesReturned
= dwServicesReturned
;
3160 if (lpServicesArray
)
3161 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3163 RegCloseKey(hServicesKey
);
3165 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3172 DWORD
REnumServicesStatusA(
3173 handle_t BindingHandle
,
3174 SC_RPC_HANDLE hSCManager
,
3175 DWORD dwServiceType
,
3176 DWORD dwServiceState
,
3179 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3180 LPBOUNDED_DWORD_256K lpServicesReturned
,
3181 LPBOUNDED_DWORD_256K lpResumeHandle
)
3184 return ERROR_CALL_NOT_IMPLEMENTED
;
3189 DWORD
ROpenSCManagerA(
3190 handle_t BindingHandle
,
3191 LPSTR lpMachineName
,
3192 LPSTR lpDatabaseName
,
3193 DWORD dwDesiredAccess
,
3194 LPSC_RPC_HANDLE lpScHandle
)
3196 UNICODE_STRING MachineName
;
3197 UNICODE_STRING DatabaseName
;
3200 DPRINT("ROpenSCManagerA() called\n");
3203 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3207 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3210 dwError
= ROpenSCManagerW(BindingHandle
,
3211 lpMachineName
? MachineName
.Buffer
: NULL
,
3212 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3217 RtlFreeUnicodeString(&MachineName
);
3220 RtlFreeUnicodeString(&DatabaseName
);
3227 DWORD
ROpenServiceA(
3228 handle_t BindingHandle
,
3229 SC_RPC_HANDLE hSCManager
,
3230 LPSTR lpServiceName
,
3231 DWORD dwDesiredAccess
,
3232 LPSC_RPC_HANDLE lpServiceHandle
)
3234 UNICODE_STRING ServiceName
;
3237 DPRINT("ROpenServiceA() called\n");
3240 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3243 dwError
= ROpenServiceW(BindingHandle
,
3245 lpServiceName
? ServiceName
.Buffer
: NULL
,
3250 RtlFreeUnicodeString(&ServiceName
);
3257 DWORD
RQueryServiceConfigA(
3258 handle_t BindingHandle
,
3259 SC_RPC_HANDLE hService
,
3260 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3262 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3264 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3265 DWORD dwError
= ERROR_SUCCESS
;
3266 PSERVICE_HANDLE hSvc
;
3267 PSERVICE lpService
= NULL
;
3268 HKEY hServiceKey
= NULL
;
3269 LPWSTR lpImagePath
= NULL
;
3270 LPWSTR lpServiceStartName
= NULL
;
3271 DWORD dwRequiredSize
;
3272 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3273 CHAR lpEmptyString
[]={0,0};
3276 DPRINT("RQueryServiceConfigA() called\n");
3279 return ERROR_SHUTDOWN_IN_PROGRESS
;
3281 hSvc
= (PSERVICE_HANDLE
)hService
;
3282 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3284 DPRINT1("Invalid handle tag!\n");
3285 return ERROR_INVALID_HANDLE
;
3288 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3289 SERVICE_QUERY_CONFIG
))
3291 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3292 return ERROR_ACCESS_DENIED
;
3295 lpService
= hSvc
->ServiceEntry
;
3296 if (lpService
== NULL
)
3298 DPRINT1("lpService == NULL!\n");
3299 return ERROR_INVALID_HANDLE
;
3302 /* FIXME: Lock the service database shared */
3304 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3307 if (dwError
!= ERROR_SUCCESS
)
3310 dwError
= ScmReadString(hServiceKey
,
3313 if (dwError
!= ERROR_SUCCESS
)
3316 ScmReadString(hServiceKey
,
3318 &lpServiceStartName
);
3320 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3322 if (lpImagePath
!= NULL
)
3323 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3325 dwRequiredSize
+= 2;
3327 if (lpService
->lpGroup
!= NULL
)
3328 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3330 dwRequiredSize
+= 2;
3332 /* FIXME: Add Dependencies length*/
3333 dwRequiredSize
+= 2;
3335 if (lpServiceStartName
!= NULL
)
3336 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3338 dwRequiredSize
+= 2;
3340 if (lpService
->lpDisplayName
!= NULL
)
3341 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3343 dwRequiredSize
+= 2;
3345 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3347 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3351 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3352 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3353 lpConfig
->dwStartType
= lpService
->dwStartType
;
3354 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3355 lpConfig
->dwTagId
= lpService
->dwTag
;
3357 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3359 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3364 WideCharToMultiByte(CP_ACP
,
3369 wcslen(lpImagePath
),
3375 strcpy(lpStr
, lpEmptyString
);
3378 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3379 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3381 if (lpService
->lpGroup
)
3383 WideCharToMultiByte(CP_ACP
,
3385 lpService
->lpGroup
->lpGroupName
,
3388 wcslen(lpService
->lpGroup
->lpGroupName
),
3394 strcpy(lpStr
, lpEmptyString
);
3397 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3398 lpStr
+= (strlen(lpStr
) + 1);
3400 /* FIXME: Append Dependencies */
3401 strcpy(lpStr
, lpEmptyString
);
3403 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3404 lpStr
+= (strlen(lpStr
) + 1);
3406 if (lpServiceStartName
)
3408 WideCharToMultiByte(CP_ACP
,
3413 wcslen(lpServiceStartName
),
3419 strcpy(lpStr
, lpEmptyString
);
3422 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3423 lpStr
+= (strlen(lpStr
) + 1);
3425 if (lpService
->lpDisplayName
)
3427 WideCharToMultiByte(CP_ACP
,
3429 lpService
->lpDisplayName
,
3432 wcslen(lpService
->lpDisplayName
),
3438 strcpy(lpStr
, lpEmptyString
);
3441 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3444 if (pcbBytesNeeded
!= NULL
)
3445 *pcbBytesNeeded
= dwRequiredSize
;
3448 if (lpImagePath
!= NULL
)
3449 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3451 if (lpServiceStartName
!= NULL
)
3452 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3454 if (hServiceKey
!= NULL
)
3455 RegCloseKey(hServiceKey
);
3457 /* FIXME: Unlock the service database */
3459 DPRINT("RQueryServiceConfigA() done\n");
3466 DWORD
RQueryServiceLockStatusA(
3467 handle_t BindingHandle
,
3468 SC_RPC_HANDLE hSCManager
,
3469 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
3471 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3474 return ERROR_CALL_NOT_IMPLEMENTED
;
3479 DWORD
RStartServiceA(
3480 handle_t BindingHandle
,
3481 SC_RPC_HANDLE hService
,
3483 LPSTRING_PTRSA argv
)
3485 DWORD dwError
= ERROR_SUCCESS
;
3486 PSERVICE_HANDLE hSvc
;
3487 PSERVICE lpService
= NULL
;
3489 DPRINT1("RStartServiceA() called\n");
3492 return ERROR_SHUTDOWN_IN_PROGRESS
;
3494 hSvc
= (PSERVICE_HANDLE
)hService
;
3495 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3497 DPRINT1("Invalid handle tag!\n");
3498 return ERROR_INVALID_HANDLE
;
3501 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3504 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3505 return ERROR_ACCESS_DENIED
;
3508 lpService
= hSvc
->ServiceEntry
;
3509 if (lpService
== NULL
)
3511 DPRINT1("lpService == NULL!\n");
3512 return ERROR_INVALID_HANDLE
;
3515 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3516 return ERROR_SERVICE_DISABLED
;
3518 if (lpService
->bDeleted
)
3519 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3521 /* FIXME: Convert argument vector to Unicode */
3523 /* Start the service */
3524 dwError
= ScmStartService(lpService
, 0, NULL
);
3526 /* FIXME: Free argument vector */
3533 DWORD
RGetServiceDisplayNameA(
3534 handle_t BindingHandle
,
3535 SC_RPC_HANDLE hSCManager
,
3536 LPSTR lpServiceName
,
3537 LPSTR lpDisplayName
,
3538 LPBOUNDED_DWORD_4K lpcchBuffer
)
3540 // PMANAGER_HANDLE hManager;
3544 LPWSTR lpServiceNameW
;
3546 DPRINT("RGetServiceDisplayNameA() called\n");
3547 DPRINT("hSCManager = %p\n", hSCManager
);
3548 DPRINT("lpServiceName: %s\n", lpServiceName
);
3549 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3550 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3552 // hManager = (PMANAGER_HANDLE)hSCManager;
3553 // if (hManager->Handle.Tag != MANAGER_TAG)
3555 // DPRINT1("Invalid manager handle!\n");
3556 // return ERROR_INVALID_HANDLE;
3559 dwLength
= strlen(lpServiceName
) + 1;
3560 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
3562 dwLength
* sizeof(WCHAR
));
3563 if (!lpServiceNameW
)
3564 return ERROR_NOT_ENOUGH_MEMORY
;
3566 MultiByteToWideChar(CP_ACP
,
3569 strlen(lpServiceName
),
3573 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
3575 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3577 if (lpService
== NULL
)
3579 DPRINT1("Could not find a service!\n");
3581 /* If the service could not be found and lpcchBuffer is 0, windows
3582 puts null in lpDisplayName and puts 1 in lpcchBuffer */
3583 if (*lpcchBuffer
== 0)
3586 *lpDisplayName
= '\0';
3588 return ERROR_SERVICE_DOES_NOT_EXIST
;
3591 if (!lpService
->lpDisplayName
)
3593 dwLength
= wcslen(lpService
->lpServiceName
);
3594 if (lpServiceName
!= NULL
&&
3595 *lpcchBuffer
> dwLength
)
3597 WideCharToMultiByte(CP_ACP
,
3599 lpService
->lpServiceName
,
3600 wcslen(lpService
->lpServiceName
),
3605 return ERROR_SUCCESS
;
3610 dwLength
= wcslen(lpService
->lpDisplayName
);
3611 if (lpDisplayName
!= NULL
&&
3612 *lpcchBuffer
> dwLength
)
3614 WideCharToMultiByte(CP_ACP
,
3616 lpService
->lpDisplayName
,
3617 wcslen(lpService
->lpDisplayName
),
3622 return ERROR_SUCCESS
;
3626 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3628 *lpcchBuffer
= dwLength
* 2;
3635 DWORD
RGetServiceKeyNameA(
3636 handle_t BindingHandle
,
3637 SC_RPC_HANDLE hSCManager
,
3638 LPSTR lpDisplayName
,
3639 LPSTR lpServiceName
,
3640 LPBOUNDED_DWORD_4K lpcchBuffer
)
3645 LPWSTR lpDisplayNameW
;
3647 DPRINT("RGetServiceKeyNameA() called\n");
3648 DPRINT("hSCManager = %p\n", hSCManager
);
3649 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
3650 DPRINT("lpServiceName: %p\n", lpServiceName
);
3651 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3653 dwLength
= strlen(lpDisplayName
) + 1;
3654 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3656 dwLength
* sizeof(WCHAR
));
3657 if (!lpDisplayNameW
)
3658 return ERROR_NOT_ENOUGH_MEMORY
;
3660 MultiByteToWideChar(CP_ACP
,
3663 strlen(lpDisplayName
),
3667 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
3669 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3671 if (lpService
== NULL
)
3673 DPRINT1("Could not find the service!\n");
3675 /* If the service could not be found and lpcchBuffer is 0,
3676 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
3677 if (*lpcchBuffer
== 0)
3680 *lpServiceName
= '\0';
3683 return ERROR_SERVICE_DOES_NOT_EXIST
;
3686 dwLength
= wcslen(lpService
->lpServiceName
);
3687 if (lpService
!= NULL
&&
3688 *lpcchBuffer
> dwLength
)
3690 WideCharToMultiByte(CP_ACP
,
3692 lpService
->lpServiceName
,
3693 wcslen(lpService
->lpServiceName
),
3698 return ERROR_SUCCESS
;
3701 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3703 *lpcchBuffer
= dwLength
* 2;
3710 DWORD
RGetCurrentGroupStateW(
3711 handle_t BindingHandle
)
3714 return ERROR_CALL_NOT_IMPLEMENTED
;
3719 DWORD
REnumServiceGroupW(
3720 handle_t BindingHandle
,
3721 SC_RPC_HANDLE hSCManager
,
3722 DWORD dwServiceType
,
3723 DWORD dwServiceState
,
3726 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3727 LPBOUNDED_DWORD_256K lpServicesReturned
,
3728 LPBOUNDED_DWORD_256K lpResumeIndex
,
3729 LPCWSTR pszGroupName
)
3732 return ERROR_CALL_NOT_IMPLEMENTED
;
3737 DWORD
RChangeServiceConfig2A(
3738 handle_t BindingHandle
,
3739 SC_RPC_HANDLE hService
,
3740 SC_RPC_CONFIG_INFOA Info
)
3743 return ERROR_CALL_NOT_IMPLEMENTED
;
3748 DWORD
RChangeServiceConfig2W(
3749 handle_t BindingHandle
,
3750 SC_RPC_HANDLE hService
,
3751 SC_RPC_CONFIG_INFOW Info
)
3753 DWORD dwError
= ERROR_SUCCESS
;
3754 PSERVICE_HANDLE hSvc
;
3755 PSERVICE lpService
= NULL
;
3756 HKEY hServiceKey
= NULL
;
3758 DPRINT("RChangeServiceConfig2W() called\n");
3759 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
3762 return ERROR_SHUTDOWN_IN_PROGRESS
;
3764 hSvc
= (PSERVICE_HANDLE
)hService
;
3765 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3767 DPRINT1("Invalid handle tag!\n");
3768 return ERROR_INVALID_HANDLE
;
3771 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3772 SERVICE_CHANGE_CONFIG
))
3774 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3775 return ERROR_ACCESS_DENIED
;
3778 lpService
= hSvc
->ServiceEntry
;
3779 if (lpService
== NULL
)
3781 DPRINT1("lpService == NULL!\n");
3782 return ERROR_INVALID_HANDLE
;
3785 /* FIXME: Lock database exclusively */
3787 if (lpService
->bDeleted
)
3789 /* FIXME: Unlock database */
3790 DPRINT1("The service has already been marked for delete!\n");
3791 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3794 /* Open the service key */
3795 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3798 if (dwError
!= ERROR_SUCCESS
)
3801 if (Info
.dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
3803 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
3805 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)&Info
;
3806 lpServiceDescription
->lpDescription
= (LPWSTR
)(&Info
+ sizeof(LPSERVICE_DESCRIPTIONW
));
3808 if (lpServiceDescription
!= NULL
&&
3809 lpServiceDescription
->lpDescription
!= NULL
)