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
) + 1) * 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
;
407 PSERVICE_HANDLE hService
;
411 DWORD pcbBytesNeeded
= 0;
412 DWORD dwServicesReturned
= 0;
414 DPRINT("RCloseServiceHandle() called\n");
416 DPRINT("hSCObject = %p\n", *hSCObject
);
419 return ERROR_INVALID_HANDLE
;
421 hManager
= (PMANAGER_HANDLE
)*hSCObject
;
422 hService
= (PSERVICE_HANDLE
)*hSCObject
;
423 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
425 DPRINT("Found manager handle\n");
427 hManager
->Handle
.RefCount
--;
428 if (hManager
->Handle
.RefCount
== 0)
430 /* FIXME: add handle cleanup code */
432 HeapFree(GetProcessHeap(), 0, hManager
);
436 DPRINT("RCloseServiceHandle() done\n");
437 return ERROR_SUCCESS
;
439 else if (hService
->Handle
.Tag
== SERVICE_TAG
)
441 DPRINT("Found service handle\n");
443 /* Get the pointer to the service record */
444 lpService
= hService
->ServiceEntry
;
446 ASSERT(hService
->Handle
.RefCount
> 0);
448 hService
->Handle
.RefCount
--;
449 if (hService
->Handle
.RefCount
== 0)
451 /* FIXME: add handle cleanup code */
453 /* Free the handle */
454 HeapFree(GetProcessHeap(), 0, hService
);
458 ASSERT(lpService
->dwRefCount
> 0);
460 lpService
->dwRefCount
--;
461 DPRINT1("CloseServiceHandle - lpService->dwRefCount %u\n",
462 lpService
->dwRefCount
);
464 if (lpService
->dwRefCount
== 0)
466 /* If this service has been marked for deletion */
467 if (lpService
->bDeleted
)
469 /* Open the Services Reg key */
470 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
471 L
"System\\CurrentControlSet\\Services",
473 KEY_SET_VALUE
| KEY_READ
,
475 if (dwError
!= ERROR_SUCCESS
)
477 DPRINT1("Failed to open services key\n");
481 /* Call the internal function with NULL, just to get bytes we need */
482 Int_EnumDependentServicesW(hServicesKey
,
487 &dwServicesReturned
);
489 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
492 DPRINT1("Deletion failed due to running dependencies.\n");
493 RegCloseKey(hServicesKey
);
494 return ERROR_SUCCESS
;
497 /* There are no references and no runnning dependencies,
498 it is now safe to delete the service */
500 /* Delete the Service Key */
501 dwError
= RegDeleteKey(hServicesKey
,
502 lpService
->lpServiceName
);
504 RegCloseKey(hServicesKey
);
506 if (dwError
!= ERROR_SUCCESS
)
508 DPRINT1("Failed to Delete the Service Registry key\n");
512 /* Delete the Service */
513 ScmDeleteServiceRecord(lpService
);
517 DPRINT("RCloseServiceHandle() done\n");
518 return ERROR_SUCCESS
;
521 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
523 return ERROR_INVALID_HANDLE
;
528 DWORD
RControlService(
529 handle_t BindingHandle
,
530 SC_RPC_HANDLE hService
,
532 LPSERVICE_STATUS lpServiceStatus
)
534 PSERVICE_HANDLE hSvc
;
536 ACCESS_MASK DesiredAccess
;
537 DWORD dwError
= ERROR_SUCCESS
;
538 DWORD pcbBytesNeeded
= 0;
539 DWORD dwServicesReturned
= 0;
540 HKEY hServicesKey
= NULL
;
542 DPRINT("RControlService() called\n");
545 return ERROR_SHUTDOWN_IN_PROGRESS
;
547 /* Check the service handle */
548 hSvc
= (PSERVICE_HANDLE
)hService
;
549 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
551 DPRINT1("Invalid handle tag!\n");
552 return ERROR_INVALID_HANDLE
;
555 /* Check the service entry point */
556 lpService
= hSvc
->ServiceEntry
;
557 if (lpService
== NULL
)
559 DPRINT1("lpService == NULL!\n");
560 return ERROR_INVALID_HANDLE
;
563 /* Check access rights */
566 case SERVICE_CONTROL_STOP
:
567 DesiredAccess
= SERVICE_STOP
;
570 case SERVICE_CONTROL_PAUSE
:
571 case SERVICE_CONTROL_CONTINUE
:
572 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
575 case SERVICE_INTERROGATE
:
576 DesiredAccess
= SERVICE_INTERROGATE
;
580 if (dwControl
>= 128 && dwControl
<= 255)
581 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
583 DesiredAccess
= SERVICE_QUERY_CONFIG
|
584 SERVICE_CHANGE_CONFIG
|
585 SERVICE_QUERY_STATUS
|
587 SERVICE_PAUSE_CONTINUE
;
591 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
593 return ERROR_ACCESS_DENIED
;
595 if (dwControl
== SERVICE_CONTROL_STOP
)
597 /* Check if the service has dependencies running as windows
598 doesn't stop a service that does */
600 /* Open the Services Reg key */
601 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
602 L
"System\\CurrentControlSet\\Services",
606 if (dwError
!= ERROR_SUCCESS
)
608 DPRINT1("Failed to open services key\n");
612 /* Call the internal function with NULL, just to get bytes we need */
613 Int_EnumDependentServicesW(hServicesKey
,
618 &dwServicesReturned
);
620 RegCloseKey(hServicesKey
);
622 /* If pcbBytesNeeded is not zero then there are services running that
623 are dependent on this service */
624 if (pcbBytesNeeded
!= 0)
626 DPRINT("Service has running dependencies. Failed to stop service.\n");
627 return ERROR_DEPENDENT_SERVICES_RUNNING
;
631 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
633 /* Send control code to the driver */
634 dwError
= ScmControlDriver(lpService
,
640 /* Send control code to the service */
641 dwError
= ScmControlService(lpService
,
646 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
647 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
649 /* Return service status information */
650 RtlCopyMemory(lpServiceStatus
,
652 sizeof(SERVICE_STATUS
));
659 DWORD
RDeleteService(
660 handle_t BindingHandle
,
661 SC_RPC_HANDLE hService
)
663 PSERVICE_HANDLE hSvc
;
667 DPRINT("RDeleteService() called\n");
670 return ERROR_SHUTDOWN_IN_PROGRESS
;
672 hSvc
= (PSERVICE_HANDLE
)hService
;
673 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
674 return ERROR_INVALID_HANDLE
;
676 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
678 return ERROR_ACCESS_DENIED
;
680 lpService
= hSvc
->ServiceEntry
;
681 if (lpService
== NULL
)
683 DPRINT1("lpService == NULL!\n");
684 return ERROR_INVALID_HANDLE
;
687 /* FIXME: Acquire service database lock exclusively */
689 if (lpService
->bDeleted
)
691 DPRINT1("The service has already been marked for delete!\n");
692 return ERROR_SERVICE_MARKED_FOR_DELETE
;
695 /* Mark service for delete */
696 lpService
->bDeleted
= TRUE
;
698 dwError
= ScmMarkServiceForDelete(lpService
);
700 /* FIXME: Release service database lock */
702 DPRINT("RDeleteService() done\n");
709 DWORD
RLockServiceDatabase(
710 handle_t BindingHandle
,
711 SC_RPC_HANDLE hSCManager
,
712 LPSC_RPC_LOCK lpLock
)
714 PMANAGER_HANDLE hMgr
;
716 DPRINT("RLockServiceDatabase() called\n");
720 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
721 if (!hMgr
|| hMgr
->Handle
.Tag
!= MANAGER_TAG
)
722 return ERROR_INVALID_HANDLE
;
724 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
726 return ERROR_ACCESS_DENIED
;
728 // return ScmLockDatabase(0, hMgr->0xC, hLock);
730 /* FIXME: Lock the database */
731 *lpLock
= (void *)0x12345678; /* Dummy! */
733 return ERROR_SUCCESS
;
738 DWORD
RQueryServiceObjectSecurity(
739 handle_t BindingHandle
,
740 SC_RPC_HANDLE hService
,
741 SECURITY_INFORMATION dwSecurityInformation
,
742 LPBYTE lpSecurityDescriptor
,
744 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
747 PSERVICE_HANDLE hSvc
;
749 ULONG DesiredAccess
= 0;
754 DPRINT("RQueryServiceObjectSecurity() called\n");
756 hSvc
= (PSERVICE_HANDLE
)hService
;
757 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
759 DPRINT1("Invalid handle tag!\n");
760 return ERROR_INVALID_HANDLE
;
763 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
764 GROUP_SECURITY_INFORMATION
||
765 OWNER_SECURITY_INFORMATION
))
766 DesiredAccess
|= READ_CONTROL
;
768 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
769 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
771 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
774 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
775 return ERROR_ACCESS_DENIED
;
778 lpService
= hSvc
->ServiceEntry
;
779 if (lpService
== NULL
)
781 DPRINT1("lpService == NULL!\n");
782 return ERROR_INVALID_HANDLE
;
785 /* FIXME: Lock the service list */
787 Status
= RtlQuerySecurityObject(lpService
->lpSecurityDescriptor
,
788 dwSecurityInformation
,
789 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
790 dwSecuityDescriptorSize
,
793 /* FIXME: Unlock the service list */
795 if (NT_SUCCESS(Status
))
797 *pcbBytesNeeded
= dwBytesNeeded
;
798 dwError
= STATUS_SUCCESS
;
800 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
802 *pcbBytesNeeded
= dwBytesNeeded
;
803 dwError
= ERROR_INSUFFICIENT_BUFFER
;
805 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
807 dwError
= ERROR_GEN_FAILURE
;
811 dwError
= RtlNtStatusToDosError(Status
);
817 return ERROR_CALL_NOT_IMPLEMENTED
;
822 DWORD
RSetServiceObjectSecurity(
823 handle_t BindingHandle
,
824 SC_RPC_HANDLE hService
,
825 DWORD dwSecurityInformation
,
826 LPBYTE lpSecurityDescriptor
,
827 DWORD dwSecuityDescriptorSize
)
829 PSERVICE_HANDLE hSvc
;
831 ULONG DesiredAccess
= 0;
832 HANDLE hToken
= NULL
;
837 DPRINT1("RSetServiceObjectSecurity() called\n");
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 (dwSecurityInformation
== 0 ||
847 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
848 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
849 return ERROR_INVALID_PARAMETER
;
851 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
852 return ERROR_INVALID_PARAMETER
;
854 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
855 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
857 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
858 DesiredAccess
|= WRITE_DAC
;
860 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
861 DesiredAccess
|= WRITE_OWNER
;
863 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
864 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
865 return ERROR_INVALID_PARAMETER
;
867 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
868 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
869 return ERROR_INVALID_PARAMETER
;
871 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
874 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
875 return ERROR_ACCESS_DENIED
;
878 lpService
= hSvc
->ServiceEntry
;
879 if (lpService
== NULL
)
881 DPRINT1("lpService == NULL!\n");
882 return ERROR_INVALID_HANDLE
;
885 if (lpService
->bDeleted
)
886 return ERROR_SERVICE_MARKED_FOR_DELETE
;
888 RpcImpersonateClient(NULL
);
890 Status
= NtOpenThreadToken(NtCurrentThread(),
894 if (!NT_SUCCESS(Status
))
895 return RtlNtStatusToDosError(Status
);
899 /* FIXME: Lock service database */
902 Status
= RtlSetSecurityObject(dwSecurityInformation
,
903 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
904 &lpService
->lpSecurityDescriptor
,
907 if (!NT_SUCCESS(Status
))
909 dwError
= RtlNtStatusToDosError(Status
);
914 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
915 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
917 if (dwError
!= ERROR_SUCCESS
)
921 dwError
= ERROR_SUCCESS
;
922 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
923 // lpService->lpSecurityDescriptor);
925 RegFlushKey(hServiceKey
);
926 RegCloseKey(hServiceKey
);
933 /* FIXME: Unlock service database */
935 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
942 DWORD
RQueryServiceStatus(
943 handle_t BindingHandle
,
944 SC_RPC_HANDLE hService
,
945 LPSERVICE_STATUS lpServiceStatus
)
947 PSERVICE_HANDLE hSvc
;
950 DPRINT("RQueryServiceStatus() called\n");
953 return ERROR_SHUTDOWN_IN_PROGRESS
;
955 hSvc
= (PSERVICE_HANDLE
)hService
;
956 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
958 DPRINT1("Invalid handle tag!\n");
959 return ERROR_INVALID_HANDLE
;
962 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
963 SERVICE_QUERY_STATUS
))
965 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
966 return ERROR_ACCESS_DENIED
;
969 lpService
= hSvc
->ServiceEntry
;
970 if (lpService
== NULL
)
972 DPRINT1("lpService == NULL!\n");
973 return ERROR_INVALID_HANDLE
;
976 /* Return service status information */
977 RtlCopyMemory(lpServiceStatus
,
979 sizeof(SERVICE_STATUS
));
981 return ERROR_SUCCESS
;
986 DWORD
RSetServiceStatus(
987 handle_t BindingHandle
,
988 SC_RPC_HANDLE hServiceStatus
,
989 LPSERVICE_STATUS lpServiceStatus
)
993 DPRINT("RSetServiceStatus() called\n");
996 return ERROR_SHUTDOWN_IN_PROGRESS
;
998 lpService
= ScmGetServiceEntryByClientHandle((ULONG
)hServiceStatus
);
999 if (lpService
== NULL
)
1001 DPRINT1("lpService == NULL!\n");
1002 return ERROR_INVALID_HANDLE
;
1005 RtlCopyMemory(&lpService
->Status
,
1007 sizeof(SERVICE_STATUS
));
1009 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1010 DPRINT("RSetServiceStatus() done\n");
1012 return ERROR_SUCCESS
;
1017 DWORD
RUnlockServiceDatabase(
1018 handle_t BindingHandle
,
1022 return ERROR_SUCCESS
;
1027 DWORD
RNotifyBootConfigStatus(
1028 handle_t BindingHandle
,
1029 SVCCTL_HANDLEW lpMachineName
,
1030 DWORD BootAcceptable
)
1033 return ERROR_CALL_NOT_IMPLEMENTED
;
1038 DWORD
RSetServiceBitsW(
1039 handle_t BindingHandle
,
1040 SC_RPC_HANDLE hServiceStatus
,
1041 DWORD dwServiceBits
,
1043 int bUpdateImmediately
,
1047 return ERROR_CALL_NOT_IMPLEMENTED
;
1052 DWORD
RChangeServiceConfigW(
1053 handle_t BindingHandle
,
1054 SC_RPC_HANDLE hService
,
1055 DWORD dwServiceType
,
1057 DWORD dwErrorControl
,
1058 LPWSTR lpBinaryPathName
,
1059 LPWSTR lpLoadOrderGroup
,
1061 LPBYTE lpDependencies
,
1063 LPWSTR lpServiceStartName
,
1066 LPWSTR lpDisplayName
)
1068 DWORD dwError
= ERROR_SUCCESS
;
1069 PSERVICE_HANDLE hSvc
;
1070 PSERVICE lpService
= NULL
;
1071 HKEY hServiceKey
= NULL
;
1072 LPWSTR lpDisplayNameW
= NULL
;
1074 DPRINT("RChangeServiceConfigW() called\n");
1075 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1076 DPRINT("dwStartType = %lu\n", dwStartType
);
1077 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1078 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1079 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1080 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1083 return ERROR_SHUTDOWN_IN_PROGRESS
;
1085 hSvc
= (PSERVICE_HANDLE
)hService
;
1086 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1088 DPRINT1("Invalid handle tag!\n");
1089 return ERROR_INVALID_HANDLE
;
1092 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1093 SERVICE_CHANGE_CONFIG
))
1095 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1096 return ERROR_ACCESS_DENIED
;
1099 lpService
= hSvc
->ServiceEntry
;
1100 if (lpService
== NULL
)
1102 DPRINT1("lpService == NULL!\n");
1103 return ERROR_INVALID_HANDLE
;
1106 /* FIXME: Lock database exclusively */
1108 if (lpService
->bDeleted
)
1110 /* FIXME: Unlock database */
1111 DPRINT1("The service has already been marked for delete!\n");
1112 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1115 /* Open the service key */
1116 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1119 if (dwError
!= ERROR_SUCCESS
)
1122 /* Write service data to the registry */
1123 /* Set the display name */
1124 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1126 RegSetValueExW(hServiceKey
,
1130 (LPBYTE
)lpDisplayName
,
1131 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1133 /* Update the display name */
1134 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1136 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1137 if (lpDisplayNameW
== NULL
)
1139 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1143 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1144 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1146 lpService
->lpDisplayName
= lpDisplayNameW
;
1149 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1151 /* Set the service type */
1152 dwError
= RegSetValueExW(hServiceKey
,
1156 (LPBYTE
)&dwServiceType
,
1158 if (dwError
!= ERROR_SUCCESS
)
1161 lpService
->Status
.dwServiceType
= dwServiceType
;
1164 if (dwStartType
!= SERVICE_NO_CHANGE
)
1166 /* Set the start value */
1167 dwError
= RegSetValueExW(hServiceKey
,
1171 (LPBYTE
)&dwStartType
,
1173 if (dwError
!= ERROR_SUCCESS
)
1176 lpService
->dwStartType
= dwStartType
;
1179 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1181 /* Set the error control value */
1182 dwError
= RegSetValueExW(hServiceKey
,
1186 (LPBYTE
)&dwErrorControl
,
1188 if (dwError
!= ERROR_SUCCESS
)
1191 lpService
->dwErrorControl
= dwErrorControl
;
1195 /* FIXME: set the new ImagePath value */
1197 /* Set the image path */
1198 if (dwServiceType
& SERVICE_WIN32
)
1200 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1202 dwError
= RegSetValueExW(hServiceKey
,
1206 (LPBYTE
)lpBinaryPathName
,
1207 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1208 if (dwError
!= ERROR_SUCCESS
)
1212 else if (dwServiceType
& SERVICE_DRIVER
)
1214 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1216 dwError
= RegSetValueExW(hServiceKey
,
1220 (LPBYTE
)lpImagePath
,
1221 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1222 if (dwError
!= ERROR_SUCCESS
)
1228 /* Set the group name */
1229 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1231 dwError
= RegSetValueExW(hServiceKey
,
1235 (LPBYTE
)lpLoadOrderGroup
,
1236 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1237 if (dwError
!= ERROR_SUCCESS
)
1239 /* FIXME: Update lpService->lpServiceGroup */
1242 if (lpdwTagId
!= NULL
)
1244 dwError
= ScmAssignNewTag(lpService
);
1245 if (dwError
!= ERROR_SUCCESS
)
1248 dwError
= RegSetValueExW(hServiceKey
,
1252 (LPBYTE
)&lpService
->dwTag
,
1254 if (dwError
!= ERROR_SUCCESS
)
1257 *lpdwTagId
= lpService
->dwTag
;
1260 /* Write dependencies */
1261 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1263 dwError
= ScmWriteDependencies(hServiceKey
,
1264 (LPWSTR
)lpDependencies
,
1266 if (dwError
!= ERROR_SUCCESS
)
1270 if (lpPassword
!= NULL
)
1272 /* FIXME: Write password */
1275 /* FIXME: Unlock database */
1278 if (hServiceKey
!= NULL
)
1279 RegCloseKey(hServiceKey
);
1281 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1287 /* Create a path suitable for the bootloader out of the full path */
1289 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1291 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1294 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1295 OBJECT_ATTRIBUTES ObjectAttributes
;
1297 HANDLE SymbolicLinkHandle
;
1299 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1301 ServiceNameLen
= wcslen(CanonName
);
1303 /* First check, if it's already good */
1304 if (ServiceNameLen
> 12 &&
1305 !wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1307 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1308 if (*RelativeName
== NULL
)
1310 DPRINT1("Error allocating memory for boot driver name!\n");
1311 return ERROR_NOT_ENOUGH_MEMORY
;
1315 wcscpy(*RelativeName
, CanonName
);
1317 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1318 return ERROR_SUCCESS
;
1321 /* If it has %SystemRoot% prefix, substitute it to \System*/
1322 if (ServiceNameLen
> 13 &&
1323 !wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1325 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1326 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1328 if (*RelativeName
== NULL
)
1330 DPRINT1("Error allocating memory for boot driver name!\n");
1331 return ERROR_NOT_ENOUGH_MEMORY
;
1335 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1336 wcscat(*RelativeName
, CanonName
+ 13);
1338 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1339 return ERROR_SUCCESS
;
1342 /* Get buffer size needed for expanding env strings */
1343 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1345 if (BufferSize
<= 1)
1347 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1348 return ERROR_INVALID_ENVIRONMENT
;
1351 /* Allocate memory, since the size is known now */
1352 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1355 DPRINT1("Error allocating memory for boot driver name!\n");
1356 return ERROR_NOT_ENOUGH_MEMORY
;
1360 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1363 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1364 LocalFree(Expanded
);
1365 return ERROR_NOT_ENOUGH_MEMORY
;
1368 /* Convert to NY-style path */
1369 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1371 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1372 return ERROR_INVALID_ENVIRONMENT
;
1375 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1377 /* No need to keep the dos-path anymore */
1378 LocalFree(Expanded
);
1380 /* Copy it to the allocated place */
1381 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1384 DPRINT1("Error allocating memory for boot driver name!\n");
1385 return ERROR_NOT_ENOUGH_MEMORY
;
1388 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1389 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1390 Expanded
[ExpandedLen
] = 0;
1392 if (ServiceNameLen
> ExpandedLen
&&
1393 !wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1395 /* Only \SystemRoot\ is missing */
1396 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1397 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1398 if (*RelativeName
== NULL
)
1400 DPRINT1("Error allocating memory for boot driver name!\n");
1401 LocalFree(Expanded
);
1402 return ERROR_NOT_ENOUGH_MEMORY
;
1405 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1406 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1408 RtlFreeUnicodeString(&NtPathName
);
1409 return ERROR_SUCCESS
;
1412 /* The most complex case starts here */
1413 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1414 InitializeObjectAttributes(&ObjectAttributes
,
1416 OBJ_CASE_INSENSITIVE
,
1420 /* Open this symlink */
1421 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1423 if (NT_SUCCESS(Status
))
1425 LinkTarget
.Length
= 0;
1426 LinkTarget
.MaximumLength
= 0;
1428 DPRINT("Opened symbolic link object\n");
1430 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1431 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1433 /* Check if required buffer size is sane */
1434 if (BufferSize
> 0xFFFD)
1436 DPRINT1("Too large buffer required\n");
1439 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1440 LocalFree(Expanded
);
1441 return ERROR_NOT_ENOUGH_MEMORY
;
1444 /* Alloc the string */
1445 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1446 if (!LinkTarget
.Buffer
)
1448 DPRINT1("Unable to alloc buffer\n");
1449 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1450 LocalFree(Expanded
);
1451 return ERROR_NOT_ENOUGH_MEMORY
;
1454 /* Do a real query now */
1455 LinkTarget
.Length
= BufferSize
;
1456 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1458 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1459 if (NT_SUCCESS(Status
))
1461 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1463 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1464 if ((ServiceNameLen
> ExpandedLen
) &&
1465 !wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1467 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1468 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1470 if (*RelativeName
== NULL
)
1472 DPRINT1("Unable to alloc buffer\n");
1473 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1474 LocalFree(Expanded
);
1475 RtlFreeUnicodeString(&NtPathName
);
1476 return ERROR_NOT_ENOUGH_MEMORY
;
1479 /* Copy it over, substituting the first part
1481 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1482 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1485 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1486 LocalFree(Expanded
);
1487 RtlFreeUnicodeString(&NtPathName
);
1489 /* Return success */
1490 return ERROR_SUCCESS
;
1494 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1495 LocalFree(Expanded
);
1496 RtlFreeUnicodeString(&NtPathName
);
1497 return ERROR_INVALID_PARAMETER
;
1502 DPRINT1("Error, Status = %08X\n", Status
);
1503 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1504 LocalFree(Expanded
);
1505 RtlFreeUnicodeString(&NtPathName
);
1506 return ERROR_INVALID_PARAMETER
;
1511 DPRINT1("Error, Status = %08X\n", Status
);
1512 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1513 LocalFree(Expanded
);
1514 RtlFreeUnicodeString(&NtPathName
);
1515 return ERROR_INVALID_PARAMETER
;
1520 DPRINT1("Error, Status = %08X\n", Status
);
1521 LocalFree(Expanded
);
1522 return ERROR_INVALID_PARAMETER
;
1526 *RelativeName
= NULL
;
1527 return ERROR_INVALID_PARAMETER
;
1531 ScmCanonDriverImagePath(DWORD dwStartType
,
1532 wchar_t *lpServiceName
,
1533 wchar_t **lpCanonName
)
1535 DWORD ServiceNameLen
, Result
;
1536 UNICODE_STRING NtServiceName
;
1537 WCHAR
*RelativeName
;
1538 WCHAR
*SourceName
= lpServiceName
;
1540 /* Calculate the length of the service's name */
1541 ServiceNameLen
= wcslen(lpServiceName
);
1543 /* 12 is wcslen(L"\\SystemRoot\\") */
1544 if (ServiceNameLen
> 12 &&
1545 !wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1547 /* SystemRoot prefix is already included */
1549 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1551 if (*lpCanonName
== NULL
)
1553 DPRINT1("Error allocating memory for canonized service name!\n");
1554 return ERROR_NOT_ENOUGH_MEMORY
;
1557 /* If it's a boot-time driver, it must be systemroot relative */
1558 if (dwStartType
== SERVICE_BOOT_START
)
1562 wcscpy(*lpCanonName
, SourceName
);
1564 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1568 /* Check if it has %SystemRoot% (len=13) */
1569 if (ServiceNameLen
> 13 &&
1570 !wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1572 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1573 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1575 if (*lpCanonName
== NULL
)
1577 DPRINT1("Error allocating memory for canonized service name!\n");
1578 return ERROR_NOT_ENOUGH_MEMORY
;
1581 /* If it's a boot-time driver, it must be systemroot relative */
1582 if (dwStartType
== SERVICE_BOOT_START
)
1583 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1585 wcscat(*lpCanonName
, lpServiceName
+ 13);
1587 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1591 /* Check if it's a relative path name */
1592 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1594 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1596 if (*lpCanonName
== NULL
)
1598 DPRINT1("Error allocating memory for canonized service name!\n");
1599 return ERROR_NOT_ENOUGH_MEMORY
;
1602 /* Just copy it over without changing */
1603 wcscpy(*lpCanonName
, lpServiceName
);
1608 /* It seems to be a DOS path, convert it */
1609 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1611 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1612 return ERROR_INVALID_PARAMETER
;
1615 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1617 if (*lpCanonName
== NULL
)
1619 DPRINT1("Error allocating memory for canonized service name!\n");
1620 RtlFreeUnicodeString(&NtServiceName
);
1621 return ERROR_NOT_ENOUGH_MEMORY
;
1624 /* Copy the string */
1625 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1627 /* The unicode string is not needed anymore */
1628 RtlFreeUnicodeString(&NtServiceName
);
1630 if (dwStartType
!= SERVICE_BOOT_START
)
1632 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1636 /* The service is boot-started, so must be relative */
1637 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1640 /* There is a problem, free name and return */
1641 LocalFree(*lpCanonName
);
1642 DPRINT1("Error converting named!\n");
1646 ASSERT(RelativeName
);
1648 /* Copy that string */
1649 wcscpy(*lpCanonName
, RelativeName
+ 12);
1651 /* Free the allocated buffer */
1652 LocalFree(RelativeName
);
1654 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1662 DWORD
RCreateServiceW(
1663 handle_t BindingHandle
,
1664 SC_RPC_HANDLE hSCManager
,
1665 LPWSTR lpServiceName
,
1666 LPWSTR lpDisplayName
,
1667 DWORD dwDesiredAccess
,
1668 DWORD dwServiceType
,
1670 DWORD dwErrorControl
,
1671 LPWSTR lpBinaryPathName
,
1672 LPWSTR lpLoadOrderGroup
,
1674 LPBYTE lpDependencies
,
1676 LPWSTR lpServiceStartName
,
1679 LPSC_RPC_HANDLE lpServiceHandle
)
1681 PMANAGER_HANDLE hManager
;
1682 DWORD dwError
= ERROR_SUCCESS
;
1683 PSERVICE lpService
= NULL
;
1684 SC_HANDLE hServiceHandle
= NULL
;
1685 LPWSTR lpImagePath
= NULL
;
1686 HKEY hServiceKey
= NULL
;
1688 DPRINT("RCreateServiceW() called\n");
1689 DPRINT("lpServiceName = %S\n", lpServiceName
);
1690 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1691 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1692 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1693 DPRINT("dwStartType = %lu\n", dwStartType
);
1694 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1695 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1696 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1699 return ERROR_SHUTDOWN_IN_PROGRESS
;
1701 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1702 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1704 DPRINT1("Invalid manager handle!\n");
1705 return ERROR_INVALID_HANDLE
;
1708 /* Check access rights */
1709 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1710 SC_MANAGER_CREATE_SERVICE
))
1712 DPRINT1("Insufficient access rights! 0x%lx\n",
1713 hManager
->Handle
.DesiredAccess
);
1714 return ERROR_ACCESS_DENIED
;
1717 if (wcslen(lpServiceName
) == 0)
1719 return ERROR_INVALID_NAME
;
1722 if (wcslen(lpBinaryPathName
) == 0)
1724 return ERROR_INVALID_PARAMETER
;
1727 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1728 (lpServiceStartName
))
1730 return ERROR_INVALID_PARAMETER
;
1733 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1734 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1735 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1737 return ERROR_INVALID_PARAMETER
;
1740 if (dwStartType
> SERVICE_DISABLED
)
1742 return ERROR_INVALID_PARAMETER
;
1745 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1748 /* check if it is marked for deletion */
1749 if (lpService
->bDeleted
)
1750 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1751 /* Return Error exist */
1752 return ERROR_SERVICE_EXISTS
;
1755 if (lpDisplayName
!= NULL
&&
1756 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1757 return ERROR_DUPLICATE_SERVICE_NAME
;
1759 if (dwServiceType
& SERVICE_DRIVER
)
1761 dwError
= ScmCanonDriverImagePath(dwStartType
,
1764 if (dwError
!= ERROR_SUCCESS
)
1769 if (dwStartType
== SERVICE_BOOT_START
||
1770 dwStartType
== SERVICE_SYSTEM_START
)
1772 return ERROR_INVALID_PARAMETER
;
1776 /* Allocate a new service entry */
1777 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1779 if (dwError
!= ERROR_SUCCESS
)
1782 /* Fill the new service entry */
1783 lpService
->Status
.dwServiceType
= dwServiceType
;
1784 lpService
->dwStartType
= dwStartType
;
1785 lpService
->dwErrorControl
= dwErrorControl
;
1787 /* Fill the display name */
1788 if (lpDisplayName
!= NULL
&&
1789 *lpDisplayName
!= 0 &&
1790 wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1792 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1793 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1794 if (lpService
->lpDisplayName
== NULL
)
1796 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1799 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1802 /* Assign the service to a group */
1803 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1805 dwError
= ScmSetServiceGroup(lpService
,
1807 if (dwError
!= ERROR_SUCCESS
)
1811 /* Assign a new tag */
1812 if (lpdwTagId
!= NULL
)
1814 dwError
= ScmAssignNewTag(lpService
);
1815 if (dwError
!= ERROR_SUCCESS
)
1819 /* Write service data to the registry */
1820 /* Create the service key */
1821 dwError
= ScmCreateServiceKey(lpServiceName
,
1824 if (dwError
!= ERROR_SUCCESS
)
1827 /* Set the display name */
1828 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1830 RegSetValueExW(hServiceKey
,
1834 (LPBYTE
)lpDisplayName
,
1835 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1838 /* Set the service type */
1839 dwError
= RegSetValueExW(hServiceKey
,
1843 (LPBYTE
)&dwServiceType
,
1845 if (dwError
!= ERROR_SUCCESS
)
1848 /* Set the start value */
1849 dwError
= RegSetValueExW(hServiceKey
,
1853 (LPBYTE
)&dwStartType
,
1855 if (dwError
!= ERROR_SUCCESS
)
1858 /* Set the error control value */
1859 dwError
= RegSetValueExW(hServiceKey
,
1863 (LPBYTE
)&dwErrorControl
,
1865 if (dwError
!= ERROR_SUCCESS
)
1868 /* Set the image path */
1869 if (dwServiceType
& SERVICE_WIN32
)
1871 dwError
= RegSetValueExW(hServiceKey
,
1875 (LPBYTE
)lpBinaryPathName
,
1876 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1877 if (dwError
!= ERROR_SUCCESS
)
1880 else if (dwServiceType
& SERVICE_DRIVER
)
1882 dwError
= RegSetValueExW(hServiceKey
,
1886 (LPBYTE
)lpImagePath
,
1887 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1888 if (dwError
!= ERROR_SUCCESS
)
1892 /* Set the group name */
1893 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1895 dwError
= RegSetValueExW(hServiceKey
,
1899 (LPBYTE
)lpLoadOrderGroup
,
1900 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1901 if (dwError
!= ERROR_SUCCESS
)
1905 if (lpdwTagId
!= NULL
)
1907 dwError
= RegSetValueExW(hServiceKey
,
1911 (LPBYTE
)&lpService
->dwTag
,
1913 if (dwError
!= ERROR_SUCCESS
)
1917 /* Write dependencies */
1918 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1920 dwError
= ScmWriteDependencies(hServiceKey
,
1921 (LPWSTR
)lpDependencies
,
1923 if (dwError
!= ERROR_SUCCESS
)
1927 /* If a non driver and NULL for lpServiceName, write ObjectName as LocalSystem */
1928 if ((dwServiceType
& SERVICE_WIN32
) && (!lpServiceName
))
1930 dwError
= RegSetValueExW(hServiceKey
,
1934 (LPBYTE
)L
"LocalSystem",
1936 if (dwError
!= ERROR_SUCCESS
)
1940 if (lpPassword
!= NULL
)
1942 /* FIXME: Write password */
1945 dwError
= ScmCreateServiceHandle(lpService
,
1947 if (dwError
!= ERROR_SUCCESS
)
1950 dwError
= ScmCheckAccess(hServiceHandle
,
1952 if (dwError
!= ERROR_SUCCESS
)
1955 lpService
->dwRefCount
= 1;
1956 DPRINT1("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
1959 if (hServiceKey
!= NULL
)
1960 RegCloseKey(hServiceKey
);
1962 if (dwError
== ERROR_SUCCESS
)
1964 DPRINT("hService %p\n", hServiceHandle
);
1965 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
1967 if (lpdwTagId
!= NULL
)
1968 *lpdwTagId
= lpService
->dwTag
;
1972 /* Release the display name buffer */
1973 if (lpService
->lpServiceName
!= NULL
)
1974 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1978 /* Remove the service handle */
1979 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
1982 if (lpService
!= NULL
)
1984 /* FIXME: remove the service entry */
1988 if (lpImagePath
!= NULL
)
1989 HeapFree(GetProcessHeap(), 0, lpImagePath
);
1991 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
1998 DWORD
REnumDependentServicesW(
1999 handle_t BindingHandle
,
2000 SC_RPC_HANDLE hService
,
2001 DWORD dwServiceState
,
2004 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2005 LPBOUNDED_DWORD_256K lpServicesReturned
)
2007 DWORD dwError
= ERROR_SUCCESS
;
2008 DWORD dwServicesReturned
= 0;
2009 DWORD dwServiceCount
;
2010 HKEY hServicesKey
= NULL
;
2011 LPSC_RPC_HANDLE hSCObject
;
2012 PSERVICE_HANDLE hSvc
;
2013 PSERVICE lpService
= NULL
;
2014 PSERVICE
*lpServicesArray
= NULL
;
2015 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2018 *pcbBytesNeeded
= 0;
2019 *lpServicesReturned
= 0;
2021 DPRINT("REnumDependentServicesW() called\n");
2023 hSCObject
= &hService
;
2024 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
2025 lpService
= hSvc
->ServiceEntry
;
2027 /* Check access rights */
2028 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2029 SC_MANAGER_ENUMERATE_SERVICE
))
2031 DPRINT1("Insufficient access rights! 0x%lx\n",
2032 hSvc
->Handle
.DesiredAccess
);
2033 return ERROR_ACCESS_DENIED
;
2036 /* Open the Services Reg key */
2037 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2038 L
"System\\CurrentControlSet\\Services",
2042 if (dwError
!= ERROR_SUCCESS
)
2045 /* First determine the bytes needed and get the number of dependent services */
2046 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2051 &dwServicesReturned
);
2052 if (dwError
!= ERROR_SUCCESS
)
2055 /* If buffer size is less than the bytes needed or pointer is null */
2056 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2058 dwError
= ERROR_MORE_DATA
;
2062 /* Allocate memory for array of service pointers */
2063 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2065 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2066 if (!lpServicesArray
)
2068 DPRINT1("Could not allocate a buffer!!\n");
2069 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2073 dwServicesReturned
= 0;
2074 *pcbBytesNeeded
= 0;
2076 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2081 &dwServicesReturned
);
2082 if (dwError
!= ERROR_SUCCESS
)
2087 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2088 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2090 /* Copy EnumDepenedentService to Buffer */
2091 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2093 lpService
= lpServicesArray
[dwServiceCount
];
2095 /* Copy status info */
2096 memcpy(&lpServicesPtr
->ServiceStatus
,
2098 sizeof(SERVICE_STATUS
));
2100 /* Copy display name */
2101 wcscpy(lpStr
, lpService
->lpDisplayName
);
2102 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2103 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2105 /* Copy service name */
2106 wcscpy(lpStr
, lpService
->lpServiceName
);
2107 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2108 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2113 *lpServicesReturned
= dwServicesReturned
;
2116 if (lpServicesArray
!= NULL
)
2117 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2119 RegCloseKey(hServicesKey
);
2121 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2128 DWORD
REnumServicesStatusW(
2129 handle_t BindingHandle
,
2130 SC_RPC_HANDLE hSCManager
,
2131 DWORD dwServiceType
,
2132 DWORD dwServiceState
,
2135 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2136 LPBOUNDED_DWORD_256K lpServicesReturned
,
2137 LPBOUNDED_DWORD_256K lpResumeHandle
)
2139 PMANAGER_HANDLE hManager
;
2141 DWORD dwError
= ERROR_SUCCESS
;
2142 PLIST_ENTRY ServiceEntry
;
2143 PSERVICE CurrentService
;
2145 DWORD dwRequiredSize
;
2146 DWORD dwServiceCount
;
2148 DWORD dwLastResumeCount
;
2149 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2152 DPRINT("REnumServicesStatusW() called\n");
2155 return ERROR_SHUTDOWN_IN_PROGRESS
;
2157 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2158 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2160 DPRINT1("Invalid manager handle!\n");
2161 return ERROR_INVALID_HANDLE
;
2164 /* Check access rights */
2165 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2166 SC_MANAGER_ENUMERATE_SERVICE
))
2168 DPRINT1("Insufficient access rights! 0x%lx\n",
2169 hManager
->Handle
.DesiredAccess
);
2170 return ERROR_ACCESS_DENIED
;
2173 *pcbBytesNeeded
= 0;
2174 *lpServicesReturned
= 0;
2176 dwLastResumeCount
= *lpResumeHandle
;
2178 /* FIXME: Lock the service list shared */
2180 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2181 if (lpService
== NULL
)
2183 dwError
= ERROR_SUCCESS
;
2190 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2191 ServiceEntry
!= &ServiceListHead
;
2192 ServiceEntry
= ServiceEntry
->Flink
)
2194 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2198 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2201 dwState
= SERVICE_ACTIVE
;
2202 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2203 dwState
= SERVICE_INACTIVE
;
2205 if ((dwState
& dwServiceState
) == 0)
2208 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2209 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2210 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2212 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2214 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2218 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2219 dwRequiredSize
+= dwSize
;
2221 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2224 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2225 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2228 ServiceEntry
!= &ServiceListHead
;
2229 ServiceEntry
= ServiceEntry
->Flink
)
2231 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2235 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2238 dwState
= SERVICE_ACTIVE
;
2239 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2240 dwState
= SERVICE_INACTIVE
;
2242 if ((dwState
& dwServiceState
) == 0)
2245 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2246 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2247 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2249 dwError
= ERROR_MORE_DATA
;
2252 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2254 *lpResumeHandle
= dwLastResumeCount
;
2255 *lpServicesReturned
= dwServiceCount
;
2256 *pcbBytesNeeded
= dwRequiredSize
;
2258 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2259 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2260 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2263 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2264 ServiceEntry
!= &ServiceListHead
;
2265 ServiceEntry
= ServiceEntry
->Flink
)
2267 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2271 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2274 dwState
= SERVICE_ACTIVE
;
2275 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2276 dwState
= SERVICE_INACTIVE
;
2278 if ((dwState
& dwServiceState
) == 0)
2281 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2282 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2283 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2285 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2288 /* Copy the service name */
2289 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2290 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2291 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2293 /* Copy the display name */
2294 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2295 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2296 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2298 /* Copy the status information */
2299 memcpy(&lpStatusPtr
->ServiceStatus
,
2300 &CurrentService
->Status
,
2301 sizeof(SERVICE_STATUS
));
2304 dwRequiredSize
+= dwSize
;
2308 /* FIXME: Unlock the service list */
2310 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2317 DWORD
ROpenSCManagerW(
2318 handle_t BindingHandle
,
2319 LPWSTR lpMachineName
,
2320 LPWSTR lpDatabaseName
,
2321 DWORD dwDesiredAccess
,
2322 LPSC_RPC_HANDLE lpScHandle
)
2327 DPRINT("ROpenSCManagerW() called\n");
2328 DPRINT("lpMachineName = %p\n", lpMachineName
);
2329 DPRINT("lpMachineName: %S\n", lpMachineName
);
2330 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2331 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2332 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2335 return ERROR_SHUTDOWN_IN_PROGRESS
;
2338 return ERROR_INVALID_PARAMETER
;
2340 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2342 if (dwError
!= ERROR_SUCCESS
)
2344 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2348 /* Check the desired access */
2349 dwError
= ScmCheckAccess(hHandle
,
2350 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2351 if (dwError
!= ERROR_SUCCESS
)
2353 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2354 HeapFree(GetProcessHeap(), 0, hHandle
);
2358 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2359 DPRINT("*hScm = %p\n", *lpScHandle
);
2361 DPRINT("ROpenSCManagerW() done\n");
2363 return ERROR_SUCCESS
;
2368 DWORD
ROpenServiceW(
2369 handle_t BindingHandle
,
2370 SC_RPC_HANDLE hSCManager
,
2371 LPWSTR lpServiceName
,
2372 DWORD dwDesiredAccess
,
2373 LPSC_RPC_HANDLE lpServiceHandle
)
2376 PMANAGER_HANDLE hManager
;
2380 DPRINT("ROpenServiceW() called\n");
2381 DPRINT("hSCManager = %p\n", hSCManager
);
2382 DPRINT("lpServiceName = %p\n", lpServiceName
);
2383 DPRINT("lpServiceName: %S\n", lpServiceName
);
2384 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2387 return ERROR_SHUTDOWN_IN_PROGRESS
;
2389 if (!lpServiceHandle
)
2390 return ERROR_INVALID_PARAMETER
;
2393 return ERROR_INVALID_ADDRESS
;
2395 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2396 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2398 DPRINT1("Invalid manager handle!\n");
2399 return ERROR_INVALID_HANDLE
;
2402 /* FIXME: Lock the service list */
2404 /* Get service database entry */
2405 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2406 if (lpService
== NULL
)
2408 DPRINT("Could not find a service!\n");
2409 return ERROR_SERVICE_DOES_NOT_EXIST
;
2412 /* Create a service handle */
2413 dwError
= ScmCreateServiceHandle(lpService
,
2415 if (dwError
!= ERROR_SUCCESS
)
2417 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2421 /* Check the desired access */
2422 dwError
= ScmCheckAccess(hHandle
,
2424 if (dwError
!= ERROR_SUCCESS
)
2426 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2427 HeapFree(GetProcessHeap(), 0, hHandle
);
2431 lpService
->dwRefCount
++;
2432 DPRINT1("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2434 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2435 DPRINT("*hService = %p\n", *lpServiceHandle
);
2437 DPRINT("ROpenServiceW() done\n");
2439 return ERROR_SUCCESS
;
2444 DWORD
RQueryServiceConfigW(
2445 handle_t BindingHandle
,
2446 SC_RPC_HANDLE hService
,
2447 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2449 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2451 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2452 DWORD dwError
= ERROR_SUCCESS
;
2453 PSERVICE_HANDLE hSvc
;
2454 PSERVICE lpService
= NULL
;
2455 HKEY hServiceKey
= NULL
;
2456 LPWSTR lpImagePath
= NULL
;
2457 LPWSTR lpServiceStartName
= NULL
;
2458 DWORD dwRequiredSize
;
2459 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2460 WCHAR lpEmptyString
[] = {0,0};
2463 DPRINT("RQueryServiceConfigW() called\n");
2466 return ERROR_SHUTDOWN_IN_PROGRESS
;
2468 hSvc
= (PSERVICE_HANDLE
)hService
;
2469 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2471 DPRINT1("Invalid handle tag!\n");
2472 return ERROR_INVALID_HANDLE
;
2475 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2476 SERVICE_QUERY_CONFIG
))
2478 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2479 return ERROR_ACCESS_DENIED
;
2482 lpService
= hSvc
->ServiceEntry
;
2483 if (lpService
== NULL
)
2485 DPRINT1("lpService == NULL!\n");
2486 return ERROR_INVALID_HANDLE
;
2489 /* FIXME: Lock the service database shared */
2491 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2494 if (dwError
!= ERROR_SUCCESS
)
2497 dwError
= ScmReadString(hServiceKey
,
2500 if (dwError
!= ERROR_SUCCESS
)
2503 ScmReadString(hServiceKey
,
2505 &lpServiceStartName
);
2507 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2509 if (lpImagePath
!= NULL
)
2510 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2512 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2514 if (lpService
->lpGroup
!= NULL
)
2515 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2517 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2519 /* FIXME: Add Dependencies length*/
2521 if (lpServiceStartName
!= NULL
)
2522 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2524 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2526 if (lpService
->lpDisplayName
!= NULL
)
2527 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2529 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2531 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2533 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2537 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2538 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2539 lpConfig
->dwStartType
= lpService
->dwStartType
;
2540 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2541 lpConfig
->dwTagId
= lpService
->dwTag
;
2543 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2545 if (lpImagePath
!= NULL
)
2547 wcscpy(lpStr
, lpImagePath
);
2551 wcscpy(lpStr
, lpEmptyString
);
2554 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2555 lpStr
+= (wcslen(lpStr
) + 1);
2557 if (lpService
->lpGroup
!= NULL
)
2559 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2563 wcscpy(lpStr
, lpEmptyString
);
2566 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2567 lpStr
+= (wcslen(lpStr
) + 1);
2569 /* FIXME: Append Dependencies */
2570 wcscpy(lpStr
, lpEmptyString
);
2572 lpStr
+= (wcslen(lpStr
) + 1);
2573 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2575 if (lpServiceStartName
!= NULL
)
2577 wcscpy(lpStr
, lpServiceStartName
);
2581 wcscpy(lpStr
, lpEmptyString
);
2584 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2585 lpStr
+= (wcslen(lpStr
) + 1);
2587 if (lpService
->lpDisplayName
!= NULL
)
2589 wcscpy(lpStr
, lpService
->lpDisplayName
);
2593 wcscpy(lpStr
, lpEmptyString
);
2596 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2599 if (pcbBytesNeeded
!= NULL
)
2600 *pcbBytesNeeded
= dwRequiredSize
;
2603 if (lpImagePath
!= NULL
)
2604 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2606 if (lpServiceStartName
!= NULL
)
2607 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2609 if (hServiceKey
!= NULL
)
2610 RegCloseKey(hServiceKey
);
2612 /* FIXME: Unlock the service database */
2614 DPRINT("RQueryServiceConfigW() done\n");
2621 DWORD
RQueryServiceLockStatusW(
2622 handle_t BindingHandle
,
2623 SC_RPC_HANDLE hSCManager
,
2624 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2626 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2629 return ERROR_CALL_NOT_IMPLEMENTED
;
2634 DWORD
RStartServiceW(
2635 handle_t BindingHandle
,
2636 SC_RPC_HANDLE hService
,
2638 LPSTRING_PTRSW argv
)
2640 DWORD dwError
= ERROR_SUCCESS
;
2641 PSERVICE_HANDLE hSvc
;
2642 PSERVICE lpService
= NULL
;
2644 DPRINT("RStartServiceW() called\n");
2647 return ERROR_SHUTDOWN_IN_PROGRESS
;
2649 hSvc
= (PSERVICE_HANDLE
)hService
;
2650 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2652 DPRINT1("Invalid handle tag!\n");
2653 return ERROR_INVALID_HANDLE
;
2656 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2659 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2660 return ERROR_ACCESS_DENIED
;
2663 lpService
= hSvc
->ServiceEntry
;
2664 if (lpService
== NULL
)
2666 DPRINT1("lpService == NULL!\n");
2667 return ERROR_INVALID_HANDLE
;
2670 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2671 return ERROR_SERVICE_DISABLED
;
2673 if (lpService
->bDeleted
)
2674 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2681 /* Start the service */
2682 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2689 DWORD
RGetServiceDisplayNameW(
2690 handle_t BindingHandle
,
2691 SC_RPC_HANDLE hSCManager
,
2692 LPWSTR lpServiceName
,
2693 LPWSTR lpDisplayName
,
2696 // PMANAGER_HANDLE hManager;
2701 DPRINT("RGetServiceDisplayNameW() called\n");
2702 DPRINT("hSCManager = %p\n", hSCManager
);
2703 DPRINT("lpServiceName: %S\n", lpServiceName
);
2704 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2705 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2707 // hManager = (PMANAGER_HANDLE)hSCManager;
2708 // if (hManager->Handle.Tag != MANAGER_TAG)
2710 // DPRINT1("Invalid manager handle!\n");
2711 // return ERROR_INVALID_HANDLE;
2714 /* Get service database entry */
2715 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2716 if (lpService
== NULL
)
2718 DPRINT1("Could not find a service!\n");
2720 /* If the service could not be found and lpcchBuffer is 0, windows
2721 puts null in lpDisplayName and puts 1 in lpcchBuffer */
2722 if (*lpcchBuffer
== 0)
2725 *lpDisplayName
= '\0';
2728 return ERROR_SERVICE_DOES_NOT_EXIST
;
2731 if (!lpService
->lpDisplayName
)
2733 dwLength
= wcslen(lpService
->lpServiceName
);
2735 if (lpServiceName
!= NULL
&&
2736 *lpcchBuffer
> dwLength
)
2738 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2743 dwLength
= wcslen(lpService
->lpDisplayName
);
2745 if (lpDisplayName
!= NULL
&&
2746 *lpcchBuffer
> dwLength
)
2748 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2752 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2754 *lpcchBuffer
= dwLength
;
2761 DWORD
RGetServiceKeyNameW(
2762 handle_t BindingHandle
,
2763 SC_RPC_HANDLE hSCManager
,
2764 LPWSTR lpDisplayName
,
2765 LPWSTR lpServiceName
,
2768 // PMANAGER_HANDLE hManager;
2773 DPRINT("RGetServiceKeyNameW() called\n");
2774 DPRINT("hSCManager = %p\n", hSCManager
);
2775 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2776 DPRINT("lpServiceName: %p\n", lpServiceName
);
2777 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2779 // hManager = (PMANAGER_HANDLE)hSCManager;
2780 // if (hManager->Handle.Tag != MANAGER_TAG)
2782 // DPRINT1("Invalid manager handle!\n");
2783 // return ERROR_INVALID_HANDLE;
2786 /* Get service database entry */
2787 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2788 if (lpService
== NULL
)
2790 DPRINT1("Could not find a service!\n");
2792 /* If the service could not be found and lpcchBuffer is 0, windows
2793 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2794 if (*lpcchBuffer
== 0)
2797 *lpServiceName
= '\0';
2800 return ERROR_SERVICE_DOES_NOT_EXIST
;
2803 dwLength
= wcslen(lpService
->lpServiceName
);
2805 if (lpServiceName
!= NULL
&&
2806 *lpcchBuffer
> dwLength
)
2808 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2809 *lpcchBuffer
= dwLength
;
2810 return ERROR_SUCCESS
;
2813 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2815 *lpcchBuffer
= dwLength
* 2;
2822 DWORD
RSetServiceBitsA(
2823 handle_t BindingHandle
,
2824 SC_RPC_HANDLE hServiceStatus
,
2825 DWORD dwServiceBits
,
2827 int bUpdateImmediately
,
2831 return ERROR_CALL_NOT_IMPLEMENTED
;
2836 DWORD
RChangeServiceConfigA(
2837 handle_t BindingHandle
,
2838 SC_RPC_HANDLE hService
,
2839 DWORD dwServiceType
,
2841 DWORD dwErrorControl
,
2842 LPSTR lpBinaryPathName
,
2843 LPSTR lpLoadOrderGroup
,
2845 LPSTR lpDependencies
,
2847 LPSTR lpServiceStartName
,
2850 LPSTR lpDisplayName
)
2852 DWORD dwError
= ERROR_SUCCESS
;
2853 PSERVICE_HANDLE hSvc
;
2854 PSERVICE lpService
= NULL
;
2855 HKEY hServiceKey
= NULL
;
2856 LPWSTR lpDisplayNameW
= NULL
;
2857 // LPWSTR lpBinaryPathNameW = NULL;
2858 LPWSTR lpLoadOrderGroupW
= NULL
;
2859 LPWSTR lpDependenciesW
= NULL
;
2860 // LPWSTR lpPasswordW = NULL;
2862 DPRINT("RChangeServiceConfigA() called\n");
2863 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2864 DPRINT("dwStartType = %lu\n", dwStartType
);
2865 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2866 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2867 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2868 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2871 return ERROR_SHUTDOWN_IN_PROGRESS
;
2873 hSvc
= (PSERVICE_HANDLE
)hService
;
2874 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2876 DPRINT1("Invalid handle tag!\n");
2877 return ERROR_INVALID_HANDLE
;
2880 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2881 SERVICE_CHANGE_CONFIG
))
2883 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2884 return ERROR_ACCESS_DENIED
;
2887 lpService
= hSvc
->ServiceEntry
;
2888 if (lpService
== NULL
)
2890 DPRINT1("lpService == NULL!\n");
2891 return ERROR_INVALID_HANDLE
;
2894 /* FIXME: Lock database exclusively */
2896 if (lpService
->bDeleted
)
2898 /* FIXME: Unlock database */
2899 DPRINT1("The service has already been marked for delete!\n");
2900 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2903 /* Open the service key */
2904 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2907 if (dwError
!= ERROR_SUCCESS
)
2910 /* Write service data to the registry */
2912 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2914 /* Set the display name */
2915 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2917 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2918 if (lpDisplayNameW
== NULL
)
2920 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2924 MultiByteToWideChar(CP_ACP
,
2929 wcslen(lpDisplayNameW
) + 1);
2931 RegSetValueExW(hServiceKey
,
2935 (LPBYTE
)lpDisplayNameW
,
2936 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2938 /* Update lpService->lpDisplayName */
2939 if (lpService
->lpDisplayName
)
2940 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2942 lpService
->lpDisplayName
= lpDisplayNameW
;
2945 if (dwServiceType
!= SERVICE_NO_CHANGE
)
2947 /* Set the service type */
2948 dwError
= RegSetValueExW(hServiceKey
,
2952 (LPBYTE
)&dwServiceType
,
2954 if (dwError
!= ERROR_SUCCESS
)
2957 lpService
->Status
.dwServiceType
= dwServiceType
;
2960 if (dwStartType
!= SERVICE_NO_CHANGE
)
2962 /* Set the start value */
2963 dwError
= RegSetValueExW(hServiceKey
,
2967 (LPBYTE
)&dwStartType
,
2969 if (dwError
!= ERROR_SUCCESS
)
2972 lpService
->dwStartType
= dwStartType
;
2975 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
2977 /* Set the error control value */
2978 dwError
= RegSetValueExW(hServiceKey
,
2982 (LPBYTE
)&dwErrorControl
,
2984 if (dwError
!= ERROR_SUCCESS
)
2987 lpService
->dwErrorControl
= dwErrorControl
;
2991 /* FIXME: set the new ImagePath value */
2993 /* Set the image path */
2994 if (dwServiceType
& SERVICE_WIN32
)
2996 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
2998 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
2999 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, wcslen(lpBinaryPathNameW
)+1);
3000 dwError
= RegSetValueExW(hServiceKey
,
3004 (LPBYTE
)lpBinaryPathNameW
,
3005 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3006 if (dwError
!= ERROR_SUCCESS
)
3010 else if (dwServiceType
& SERVICE_DRIVER
)
3012 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3014 dwError
= RegSetValueExW(hServiceKey
,
3018 (LPBYTE
)lpImagePath
,
3019 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3020 if (dwError
!= ERROR_SUCCESS
)
3026 /* Set the group name */
3027 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3029 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3031 (strlen(lpLoadOrderGroup
)+1) * sizeof(WCHAR
));
3032 if (lpLoadOrderGroupW
== NULL
)
3034 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3038 MultiByteToWideChar(CP_ACP
,
3043 wcslen(lpLoadOrderGroupW
) + 1);
3045 dwError
= RegSetValueExW(hServiceKey
,
3049 (LPBYTE
)lpLoadOrderGroupW
,
3050 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3051 if (dwError
!= ERROR_SUCCESS
)
3054 /* FIXME: Update lpService->lpServiceGroup */
3056 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3059 if (lpdwTagId
!= NULL
)
3061 dwError
= ScmAssignNewTag(lpService
);
3062 if (dwError
!= ERROR_SUCCESS
)
3065 dwError
= RegSetValueExW(hServiceKey
,
3069 (LPBYTE
)&lpService
->dwTag
,
3071 if (dwError
!= ERROR_SUCCESS
)
3074 *lpdwTagId
= lpService
->dwTag
;
3077 /* Write dependencies */
3078 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3080 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3082 (strlen(lpDependencies
)+1) * sizeof(WCHAR
));
3083 if (lpDependenciesW
== NULL
)
3085 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3089 MultiByteToWideChar(CP_ACP
,
3094 wcslen(lpDependenciesW
)+1);
3096 dwError
= ScmWriteDependencies(hServiceKey
,
3097 (LPWSTR
)lpDependenciesW
,
3100 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3103 if (lpPassword
!= NULL
)
3105 /* FIXME: Write password */
3108 /* FIXME: Unlock database */
3111 if (hServiceKey
!= NULL
)
3112 RegCloseKey(hServiceKey
);
3114 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3121 DWORD
RCreateServiceA(
3122 handle_t BindingHandle
,
3123 SC_RPC_HANDLE hSCManager
,
3124 LPSTR lpServiceName
,
3125 LPSTR lpDisplayName
,
3126 DWORD dwDesiredAccess
,
3127 DWORD dwServiceType
,
3129 DWORD dwErrorControl
,
3130 LPSTR lpBinaryPathName
,
3131 LPSTR lpLoadOrderGroup
,
3133 LPBYTE lpDependencies
,
3135 LPSTR lpServiceStartName
,
3138 LPSC_RPC_HANDLE lpServiceHandle
)
3141 return ERROR_CALL_NOT_IMPLEMENTED
;
3146 DWORD
REnumDependentServicesA(
3147 handle_t BindingHandle
,
3148 SC_RPC_HANDLE hService
,
3149 DWORD dwServiceState
,
3152 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3153 LPBOUNDED_DWORD_256K lpServicesReturned
)
3155 DWORD dwError
= ERROR_SUCCESS
;
3156 DWORD dwServicesReturned
= 0;
3157 DWORD dwServiceCount
;
3158 HKEY hServicesKey
= NULL
;
3159 LPSC_RPC_HANDLE hSCObject
;
3160 PSERVICE_HANDLE hSvc
;
3161 PSERVICE lpService
= NULL
;
3162 PSERVICE
*lpServicesArray
= NULL
;
3163 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3166 *pcbBytesNeeded
= 0;
3167 *lpServicesReturned
= 0;
3169 DPRINT("REnumDependentServicesA() called\n");
3171 hSCObject
= &hService
;
3172 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3173 lpService
= hSvc
->ServiceEntry
;
3175 /* Check access rights */
3176 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3177 SC_MANAGER_ENUMERATE_SERVICE
))
3179 DPRINT1("Insufficient access rights! 0x%lx\n",
3180 hSvc
->Handle
.DesiredAccess
);
3181 return ERROR_ACCESS_DENIED
;
3184 /* Open the Services Reg key */
3185 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3186 L
"System\\CurrentControlSet\\Services",
3191 if (dwError
!= ERROR_SUCCESS
) return dwError
;
3193 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3194 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3195 are the same for both. Verified in WINXP. */
3197 /* First determine the bytes needed and get the number of dependent services*/
3198 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3203 &dwServicesReturned
);
3204 if (dwError
!= ERROR_SUCCESS
)
3207 /* If buffer size is less than the bytes needed or pointer is null*/
3208 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3210 dwError
= ERROR_MORE_DATA
;
3214 /* Allocate memory for array of service pointers */
3215 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3217 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3218 if (!lpServicesArray
)
3220 DPRINT1("Could not allocate a buffer!!\n");
3221 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3225 dwServicesReturned
= 0;
3226 *pcbBytesNeeded
= 0;
3228 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3233 &dwServicesReturned
);
3234 if (dwError
!= ERROR_SUCCESS
)
3239 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3240 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3242 /* Copy EnumDepenedentService to Buffer */
3243 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3245 lpService
= lpServicesArray
[dwServiceCount
];
3247 /* Copy the status info */
3248 memcpy(&lpServicesPtr
->ServiceStatus
,
3250 sizeof(SERVICE_STATUS
));
3252 /* Copy display name */
3253 WideCharToMultiByte(CP_ACP
,
3255 lpService
->lpDisplayName
,
3258 wcslen(lpService
->lpDisplayName
),
3261 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3262 lpStr
+= strlen(lpStr
) + 1;
3264 /* Copy service name */
3265 WideCharToMultiByte(CP_ACP
,
3267 lpService
->lpServiceName
,