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
;
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 lpService
->lpServiceName
);
494 RegCloseKey(hServicesKey
);
495 return ERROR_SUCCESS
;
498 /* There are no references and no runnning dependencies,
499 it is now safe to delete the service */
501 /* Delete the Service Key */
502 dwError
= RegDeleteKey(hServicesKey
,
503 lpService
->lpServiceName
);
505 RegCloseKey(hServicesKey
);
507 if (dwError
!= ERROR_SUCCESS
)
509 DPRINT1("Failed to Delete the Service Registry key\n");
513 /* Delete the Service */
514 ScmDeleteServiceRecord(lpService
);
518 DPRINT("RCloseServiceHandle() done\n");
519 return ERROR_SUCCESS
;
522 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
524 return ERROR_INVALID_HANDLE
;
529 DWORD
RControlService(
530 handle_t BindingHandle
,
531 SC_RPC_HANDLE hService
,
533 LPSERVICE_STATUS lpServiceStatus
)
535 PSERVICE_HANDLE hSvc
;
537 ACCESS_MASK DesiredAccess
;
538 DWORD dwError
= ERROR_SUCCESS
;
539 DWORD pcbBytesNeeded
= 0;
540 DWORD dwServicesReturned
= 0;
541 HKEY hServicesKey
= NULL
;
543 DPRINT("RControlService() called\n");
546 return ERROR_SHUTDOWN_IN_PROGRESS
;
548 /* Check the service handle */
549 hSvc
= (PSERVICE_HANDLE
)hService
;
550 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
552 DPRINT1("Invalid handle tag!\n");
553 return ERROR_INVALID_HANDLE
;
556 /* Check the service entry point */
557 lpService
= hSvc
->ServiceEntry
;
558 if (lpService
== NULL
)
560 DPRINT1("lpService == NULL!\n");
561 return ERROR_INVALID_HANDLE
;
564 /* Check access rights */
567 case SERVICE_CONTROL_STOP
:
568 DesiredAccess
= SERVICE_STOP
;
571 case SERVICE_CONTROL_PAUSE
:
572 case SERVICE_CONTROL_CONTINUE
:
573 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
576 case SERVICE_INTERROGATE
:
577 DesiredAccess
= SERVICE_INTERROGATE
;
581 if (dwControl
>= 128 && dwControl
<= 255)
582 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
584 DesiredAccess
= SERVICE_QUERY_CONFIG
|
585 SERVICE_CHANGE_CONFIG
|
586 SERVICE_QUERY_STATUS
|
588 SERVICE_PAUSE_CONTINUE
;
592 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
594 return ERROR_ACCESS_DENIED
;
596 if (dwControl
== SERVICE_CONTROL_STOP
)
598 /* Check if the service has dependencies running as windows
599 doesn't stop a service that does */
601 /* Open the Services Reg key */
602 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
603 L
"System\\CurrentControlSet\\Services",
607 if (dwError
!= ERROR_SUCCESS
)
609 DPRINT1("Failed to open services key\n");
613 /* Call the internal function with NULL, just to get bytes we need */
614 Int_EnumDependentServicesW(hServicesKey
,
619 &dwServicesReturned
);
621 RegCloseKey(hServicesKey
);
623 /* If pcbBytesNeeded is not zero then there are services running that
624 are dependent on this service */
625 if (pcbBytesNeeded
!= 0)
627 DPRINT("Service has running dependencies. Failed to stop service.\n");
628 return ERROR_DEPENDENT_SERVICES_RUNNING
;
632 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
634 /* Send control code to the driver */
635 dwError
= ScmControlDriver(lpService
,
641 /* Send control code to the service */
642 dwError
= ScmControlService(lpService
,
647 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
648 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
650 /* Return service status information */
651 RtlCopyMemory(lpServiceStatus
,
653 sizeof(SERVICE_STATUS
));
660 DWORD
RDeleteService(
661 handle_t BindingHandle
,
662 SC_RPC_HANDLE hService
)
664 PSERVICE_HANDLE hSvc
;
668 DPRINT("RDeleteService() called\n");
671 return ERROR_SHUTDOWN_IN_PROGRESS
;
673 hSvc
= (PSERVICE_HANDLE
)hService
;
674 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
675 return ERROR_INVALID_HANDLE
;
677 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
679 return ERROR_ACCESS_DENIED
;
681 lpService
= hSvc
->ServiceEntry
;
682 if (lpService
== NULL
)
684 DPRINT1("lpService == NULL!\n");
685 return ERROR_INVALID_HANDLE
;
688 /* FIXME: Acquire service database lock exclusively */
690 if (lpService
->bDeleted
)
692 DPRINT1("The service has already been marked for delete!\n");
693 return ERROR_SERVICE_MARKED_FOR_DELETE
;
696 /* Mark service for delete */
697 lpService
->bDeleted
= TRUE
;
699 dwError
= ScmMarkServiceForDelete(lpService
);
701 /* FIXME: Release service database lock */
703 DPRINT("RDeleteService() done\n");
710 DWORD
RLockServiceDatabase(
711 handle_t BindingHandle
,
712 SC_RPC_HANDLE hSCManager
,
713 LPSC_RPC_LOCK lpLock
)
715 PMANAGER_HANDLE hMgr
;
717 DPRINT("RLockServiceDatabase() called\n");
721 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
722 if (!hMgr
|| hMgr
->Handle
.Tag
!= MANAGER_TAG
)
723 return ERROR_INVALID_HANDLE
;
725 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
727 return ERROR_ACCESS_DENIED
;
729 // return ScmLockDatabase(0, hMgr->0xC, hLock);
731 /* FIXME: Lock the database */
732 *lpLock
= (void *)0x12345678; /* Dummy! */
734 return ERROR_SUCCESS
;
739 DWORD
RQueryServiceObjectSecurity(
740 handle_t BindingHandle
,
741 SC_RPC_HANDLE hService
,
742 SECURITY_INFORMATION dwSecurityInformation
,
743 LPBYTE lpSecurityDescriptor
,
745 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
748 PSERVICE_HANDLE hSvc
;
750 ULONG DesiredAccess
= 0;
755 DPRINT("RQueryServiceObjectSecurity() called\n");
757 hSvc
= (PSERVICE_HANDLE
)hService
;
758 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
760 DPRINT1("Invalid handle tag!\n");
761 return ERROR_INVALID_HANDLE
;
764 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
765 GROUP_SECURITY_INFORMATION
||
766 OWNER_SECURITY_INFORMATION
))
767 DesiredAccess
|= READ_CONTROL
;
769 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
770 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
772 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
775 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
776 return ERROR_ACCESS_DENIED
;
779 lpService
= hSvc
->ServiceEntry
;
780 if (lpService
== NULL
)
782 DPRINT1("lpService == NULL!\n");
783 return ERROR_INVALID_HANDLE
;
786 /* FIXME: Lock the service list */
788 Status
= RtlQuerySecurityObject(lpService
->lpSecurityDescriptor
,
789 dwSecurityInformation
,
790 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
791 dwSecuityDescriptorSize
,
794 /* FIXME: Unlock the service list */
796 if (NT_SUCCESS(Status
))
798 *pcbBytesNeeded
= dwBytesNeeded
;
799 dwError
= STATUS_SUCCESS
;
801 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
803 *pcbBytesNeeded
= dwBytesNeeded
;
804 dwError
= ERROR_INSUFFICIENT_BUFFER
;
806 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
808 dwError
= ERROR_GEN_FAILURE
;
812 dwError
= RtlNtStatusToDosError(Status
);
818 return ERROR_CALL_NOT_IMPLEMENTED
;
823 DWORD
RSetServiceObjectSecurity(
824 handle_t BindingHandle
,
825 SC_RPC_HANDLE hService
,
826 DWORD dwSecurityInformation
,
827 LPBYTE lpSecurityDescriptor
,
828 DWORD dwSecuityDescriptorSize
)
830 PSERVICE_HANDLE hSvc
;
832 ULONG DesiredAccess
= 0;
833 HANDLE hToken
= NULL
;
838 DPRINT1("RSetServiceObjectSecurity() called\n");
840 hSvc
= (PSERVICE_HANDLE
)hService
;
841 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
843 DPRINT1("Invalid handle tag!\n");
844 return ERROR_INVALID_HANDLE
;
847 if (dwSecurityInformation
== 0 ||
848 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
849 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
850 return ERROR_INVALID_PARAMETER
;
852 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
853 return ERROR_INVALID_PARAMETER
;
855 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
856 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
858 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
859 DesiredAccess
|= WRITE_DAC
;
861 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
862 DesiredAccess
|= WRITE_OWNER
;
864 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
865 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
866 return ERROR_INVALID_PARAMETER
;
868 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
869 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
870 return ERROR_INVALID_PARAMETER
;
872 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
875 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
876 return ERROR_ACCESS_DENIED
;
879 lpService
= hSvc
->ServiceEntry
;
880 if (lpService
== NULL
)
882 DPRINT1("lpService == NULL!\n");
883 return ERROR_INVALID_HANDLE
;
886 if (lpService
->bDeleted
)
887 return ERROR_SERVICE_MARKED_FOR_DELETE
;
889 RpcImpersonateClient(NULL
);
891 Status
= NtOpenThreadToken(NtCurrentThread(),
895 if (!NT_SUCCESS(Status
))
896 return RtlNtStatusToDosError(Status
);
900 /* FIXME: Lock service database */
903 Status
= RtlSetSecurityObject(dwSecurityInformation
,
904 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
905 &lpService
->lpSecurityDescriptor
,
908 if (!NT_SUCCESS(Status
))
910 dwError
= RtlNtStatusToDosError(Status
);
915 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
916 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
918 if (dwError
!= ERROR_SUCCESS
)
922 dwError
= ERROR_SUCCESS
;
923 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
924 // lpService->lpSecurityDescriptor);
926 RegFlushKey(hServiceKey
);
927 RegCloseKey(hServiceKey
);
934 /* FIXME: Unlock service database */
936 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
943 DWORD
RQueryServiceStatus(
944 handle_t BindingHandle
,
945 SC_RPC_HANDLE hService
,
946 LPSERVICE_STATUS lpServiceStatus
)
948 PSERVICE_HANDLE hSvc
;
951 DPRINT("RQueryServiceStatus() called\n");
954 return ERROR_SHUTDOWN_IN_PROGRESS
;
956 hSvc
= (PSERVICE_HANDLE
)hService
;
957 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
959 DPRINT1("Invalid handle tag!\n");
960 return ERROR_INVALID_HANDLE
;
963 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
964 SERVICE_QUERY_STATUS
))
966 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
967 return ERROR_ACCESS_DENIED
;
970 lpService
= hSvc
->ServiceEntry
;
971 if (lpService
== NULL
)
973 DPRINT1("lpService == NULL!\n");
974 return ERROR_INVALID_HANDLE
;
977 /* Return service status information */
978 RtlCopyMemory(lpServiceStatus
,
980 sizeof(SERVICE_STATUS
));
982 return ERROR_SUCCESS
;
987 DWORD
RSetServiceStatus(
988 handle_t BindingHandle
,
989 SC_RPC_HANDLE hServiceStatus
,
990 LPSERVICE_STATUS lpServiceStatus
)
994 DPRINT("RSetServiceStatus() called\n");
997 return ERROR_SHUTDOWN_IN_PROGRESS
;
999 lpService
= ScmGetServiceEntryByClientHandle((ULONG
)hServiceStatus
);
1000 if (lpService
== NULL
)
1002 DPRINT1("lpService == NULL!\n");
1003 return ERROR_INVALID_HANDLE
;
1006 RtlCopyMemory(&lpService
->Status
,
1008 sizeof(SERVICE_STATUS
));
1010 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1011 DPRINT("RSetServiceStatus() done\n");
1013 return ERROR_SUCCESS
;
1018 DWORD
RUnlockServiceDatabase(
1019 handle_t BindingHandle
,
1023 return ERROR_SUCCESS
;
1028 DWORD
RNotifyBootConfigStatus(
1029 handle_t BindingHandle
,
1030 SVCCTL_HANDLEW lpMachineName
,
1031 DWORD BootAcceptable
)
1034 return ERROR_CALL_NOT_IMPLEMENTED
;
1039 DWORD
RSetServiceBitsW(
1040 handle_t BindingHandle
,
1041 SC_RPC_HANDLE hServiceStatus
,
1042 DWORD dwServiceBits
,
1044 int bUpdateImmediately
,
1048 return ERROR_CALL_NOT_IMPLEMENTED
;
1053 DWORD
RChangeServiceConfigW(
1054 handle_t BindingHandle
,
1055 SC_RPC_HANDLE hService
,
1056 DWORD dwServiceType
,
1058 DWORD dwErrorControl
,
1059 LPWSTR lpBinaryPathName
,
1060 LPWSTR lpLoadOrderGroup
,
1062 LPBYTE lpDependencies
,
1064 LPWSTR lpServiceStartName
,
1067 LPWSTR lpDisplayName
)
1069 DWORD dwError
= ERROR_SUCCESS
;
1070 PSERVICE_HANDLE hSvc
;
1071 PSERVICE lpService
= NULL
;
1072 HKEY hServiceKey
= NULL
;
1073 LPWSTR lpDisplayNameW
= NULL
;
1075 DPRINT("RChangeServiceConfigW() called\n");
1076 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1077 DPRINT("dwStartType = %lu\n", dwStartType
);
1078 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1079 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1080 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1081 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1084 return ERROR_SHUTDOWN_IN_PROGRESS
;
1086 hSvc
= (PSERVICE_HANDLE
)hService
;
1087 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1089 DPRINT1("Invalid handle tag!\n");
1090 return ERROR_INVALID_HANDLE
;
1093 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1094 SERVICE_CHANGE_CONFIG
))
1096 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1097 return ERROR_ACCESS_DENIED
;
1100 lpService
= hSvc
->ServiceEntry
;
1101 if (lpService
== NULL
)
1103 DPRINT1("lpService == NULL!\n");
1104 return ERROR_INVALID_HANDLE
;
1107 /* FIXME: Lock database exclusively */
1109 if (lpService
->bDeleted
)
1111 /* FIXME: Unlock database */
1112 DPRINT1("The service has already been marked for delete!\n");
1113 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1116 /* Open the service key */
1117 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1120 if (dwError
!= ERROR_SUCCESS
)
1123 /* Write service data to the registry */
1124 /* Set the display name */
1125 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1127 RegSetValueExW(hServiceKey
,
1131 (LPBYTE
)lpDisplayName
,
1132 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1134 /* Update the display name */
1135 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1137 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1138 if (lpDisplayNameW
== NULL
)
1140 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1144 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1145 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1147 lpService
->lpDisplayName
= lpDisplayNameW
;
1150 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1152 /* Set the service type */
1153 dwError
= RegSetValueExW(hServiceKey
,
1157 (LPBYTE
)&dwServiceType
,
1159 if (dwError
!= ERROR_SUCCESS
)
1162 lpService
->Status
.dwServiceType
= dwServiceType
;
1165 if (dwStartType
!= SERVICE_NO_CHANGE
)
1167 /* Set the start value */
1168 dwError
= RegSetValueExW(hServiceKey
,
1172 (LPBYTE
)&dwStartType
,
1174 if (dwError
!= ERROR_SUCCESS
)
1177 lpService
->dwStartType
= dwStartType
;
1180 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1182 /* Set the error control value */
1183 dwError
= RegSetValueExW(hServiceKey
,
1187 (LPBYTE
)&dwErrorControl
,
1189 if (dwError
!= ERROR_SUCCESS
)
1192 lpService
->dwErrorControl
= dwErrorControl
;
1196 /* FIXME: set the new ImagePath value */
1198 /* Set the image path */
1199 if (dwServiceType
& SERVICE_WIN32
)
1201 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1203 dwError
= RegSetValueExW(hServiceKey
,
1207 (LPBYTE
)lpBinaryPathName
,
1208 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1209 if (dwError
!= ERROR_SUCCESS
)
1213 else if (dwServiceType
& SERVICE_DRIVER
)
1215 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1217 dwError
= RegSetValueExW(hServiceKey
,
1221 (LPBYTE
)lpImagePath
,
1222 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1223 if (dwError
!= ERROR_SUCCESS
)
1229 /* Set the group name */
1230 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1232 dwError
= RegSetValueExW(hServiceKey
,
1236 (LPBYTE
)lpLoadOrderGroup
,
1237 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1238 if (dwError
!= ERROR_SUCCESS
)
1240 /* FIXME: Update lpService->lpServiceGroup */
1243 if (lpdwTagId
!= NULL
)
1245 dwError
= ScmAssignNewTag(lpService
);
1246 if (dwError
!= ERROR_SUCCESS
)
1249 dwError
= RegSetValueExW(hServiceKey
,
1253 (LPBYTE
)&lpService
->dwTag
,
1255 if (dwError
!= ERROR_SUCCESS
)
1258 *lpdwTagId
= lpService
->dwTag
;
1261 /* Write dependencies */
1262 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1264 dwError
= ScmWriteDependencies(hServiceKey
,
1265 (LPWSTR
)lpDependencies
,
1267 if (dwError
!= ERROR_SUCCESS
)
1271 if (lpPassword
!= NULL
)
1273 /* FIXME: Write password */
1276 /* FIXME: Unlock database */
1279 if (hServiceKey
!= NULL
)
1280 RegCloseKey(hServiceKey
);
1282 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1288 /* Create a path suitable for the bootloader out of the full path */
1290 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1292 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1295 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1296 OBJECT_ATTRIBUTES ObjectAttributes
;
1298 HANDLE SymbolicLinkHandle
;
1300 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1302 ServiceNameLen
= wcslen(CanonName
);
1304 /* First check, if it's already good */
1305 if (ServiceNameLen
> 12 &&
1306 !wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1308 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1309 if (*RelativeName
== NULL
)
1311 DPRINT1("Error allocating memory for boot driver name!\n");
1312 return ERROR_NOT_ENOUGH_MEMORY
;
1316 wcscpy(*RelativeName
, CanonName
);
1318 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1319 return ERROR_SUCCESS
;
1322 /* If it has %SystemRoot% prefix, substitute it to \System*/
1323 if (ServiceNameLen
> 13 &&
1324 !wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1326 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1327 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1329 if (*RelativeName
== NULL
)
1331 DPRINT1("Error allocating memory for boot driver name!\n");
1332 return ERROR_NOT_ENOUGH_MEMORY
;
1336 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1337 wcscat(*RelativeName
, CanonName
+ 13);
1339 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1340 return ERROR_SUCCESS
;
1343 /* Get buffer size needed for expanding env strings */
1344 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1346 if (BufferSize
<= 1)
1348 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1349 return ERROR_INVALID_ENVIRONMENT
;
1352 /* Allocate memory, since the size is known now */
1353 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1356 DPRINT1("Error allocating memory for boot driver name!\n");
1357 return ERROR_NOT_ENOUGH_MEMORY
;
1361 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1364 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1365 LocalFree(Expanded
);
1366 return ERROR_NOT_ENOUGH_MEMORY
;
1369 /* Convert to NY-style path */
1370 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1372 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1373 return ERROR_INVALID_ENVIRONMENT
;
1376 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1378 /* No need to keep the dos-path anymore */
1379 LocalFree(Expanded
);
1381 /* Copy it to the allocated place */
1382 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1385 DPRINT1("Error allocating memory for boot driver name!\n");
1386 return ERROR_NOT_ENOUGH_MEMORY
;
1389 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1390 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1391 Expanded
[ExpandedLen
] = 0;
1393 if (ServiceNameLen
> ExpandedLen
&&
1394 !wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1396 /* Only \SystemRoot\ is missing */
1397 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1398 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1399 if (*RelativeName
== NULL
)
1401 DPRINT1("Error allocating memory for boot driver name!\n");
1402 LocalFree(Expanded
);
1403 return ERROR_NOT_ENOUGH_MEMORY
;
1406 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1407 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1409 RtlFreeUnicodeString(&NtPathName
);
1410 return ERROR_SUCCESS
;
1413 /* The most complex case starts here */
1414 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1415 InitializeObjectAttributes(&ObjectAttributes
,
1417 OBJ_CASE_INSENSITIVE
,
1421 /* Open this symlink */
1422 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1424 if (NT_SUCCESS(Status
))
1426 LinkTarget
.Length
= 0;
1427 LinkTarget
.MaximumLength
= 0;
1429 DPRINT("Opened symbolic link object\n");
1431 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1432 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1434 /* Check if required buffer size is sane */
1435 if (BufferSize
> 0xFFFD)
1437 DPRINT1("Too large buffer required\n");
1440 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1441 LocalFree(Expanded
);
1442 return ERROR_NOT_ENOUGH_MEMORY
;
1445 /* Alloc the string */
1446 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1447 if (!LinkTarget
.Buffer
)
1449 DPRINT1("Unable to alloc buffer\n");
1450 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1451 LocalFree(Expanded
);
1452 return ERROR_NOT_ENOUGH_MEMORY
;
1455 /* Do a real query now */
1456 LinkTarget
.Length
= BufferSize
;
1457 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1459 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1460 if (NT_SUCCESS(Status
))
1462 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1464 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1465 if ((ServiceNameLen
> ExpandedLen
) &&
1466 !wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1468 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1469 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1471 if (*RelativeName
== NULL
)
1473 DPRINT1("Unable to alloc buffer\n");
1474 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1475 LocalFree(Expanded
);
1476 RtlFreeUnicodeString(&NtPathName
);
1477 return ERROR_NOT_ENOUGH_MEMORY
;
1480 /* Copy it over, substituting the first part
1482 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1483 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1486 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1487 LocalFree(Expanded
);
1488 RtlFreeUnicodeString(&NtPathName
);
1490 /* Return success */
1491 return ERROR_SUCCESS
;
1495 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1496 LocalFree(Expanded
);
1497 RtlFreeUnicodeString(&NtPathName
);
1498 return ERROR_INVALID_PARAMETER
;
1503 DPRINT1("Error, Status = %08X\n", Status
);
1504 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1505 LocalFree(Expanded
);
1506 RtlFreeUnicodeString(&NtPathName
);
1507 return ERROR_INVALID_PARAMETER
;
1512 DPRINT1("Error, Status = %08X\n", Status
);
1513 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1514 LocalFree(Expanded
);
1515 RtlFreeUnicodeString(&NtPathName
);
1516 return ERROR_INVALID_PARAMETER
;
1521 DPRINT1("Error, Status = %08X\n", Status
);
1522 LocalFree(Expanded
);
1523 return ERROR_INVALID_PARAMETER
;
1527 *RelativeName
= NULL
;
1528 return ERROR_INVALID_PARAMETER
;
1532 ScmCanonDriverImagePath(DWORD dwStartType
,
1533 wchar_t *lpServiceName
,
1534 wchar_t **lpCanonName
)
1536 DWORD ServiceNameLen
, Result
;
1537 UNICODE_STRING NtServiceName
;
1538 WCHAR
*RelativeName
;
1539 WCHAR
*SourceName
= lpServiceName
;
1541 /* Calculate the length of the service's name */
1542 ServiceNameLen
= wcslen(lpServiceName
);
1544 /* 12 is wcslen(L"\\SystemRoot\\") */
1545 if (ServiceNameLen
> 12 &&
1546 !wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1548 /* SystemRoot prefix is already included */
1550 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1552 if (*lpCanonName
== NULL
)
1554 DPRINT1("Error allocating memory for canonized service name!\n");
1555 return ERROR_NOT_ENOUGH_MEMORY
;
1558 /* If it's a boot-time driver, it must be systemroot relative */
1559 if (dwStartType
== SERVICE_BOOT_START
)
1563 wcscpy(*lpCanonName
, SourceName
);
1565 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1569 /* Check if it has %SystemRoot% (len=13) */
1570 if (ServiceNameLen
> 13 &&
1571 !wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1573 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1574 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1576 if (*lpCanonName
== NULL
)
1578 DPRINT1("Error allocating memory for canonized service name!\n");
1579 return ERROR_NOT_ENOUGH_MEMORY
;
1582 /* If it's a boot-time driver, it must be systemroot relative */
1583 if (dwStartType
== SERVICE_BOOT_START
)
1584 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1586 wcscat(*lpCanonName
, lpServiceName
+ 13);
1588 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1592 /* Check if it's a relative path name */
1593 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1595 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1597 if (*lpCanonName
== NULL
)
1599 DPRINT1("Error allocating memory for canonized service name!\n");
1600 return ERROR_NOT_ENOUGH_MEMORY
;
1603 /* Just copy it over without changing */
1604 wcscpy(*lpCanonName
, lpServiceName
);
1609 /* It seems to be a DOS path, convert it */
1610 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1612 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1613 return ERROR_INVALID_PARAMETER
;
1616 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1618 if (*lpCanonName
== NULL
)
1620 DPRINT1("Error allocating memory for canonized service name!\n");
1621 RtlFreeUnicodeString(&NtServiceName
);
1622 return ERROR_NOT_ENOUGH_MEMORY
;
1625 /* Copy the string */
1626 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1628 /* The unicode string is not needed anymore */
1629 RtlFreeUnicodeString(&NtServiceName
);
1631 if (dwStartType
!= SERVICE_BOOT_START
)
1633 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1637 /* The service is boot-started, so must be relative */
1638 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1641 /* There is a problem, free name and return */
1642 LocalFree(*lpCanonName
);
1643 DPRINT1("Error converting named!\n");
1647 ASSERT(RelativeName
);
1649 /* Copy that string */
1650 wcscpy(*lpCanonName
, RelativeName
+ 12);
1652 /* Free the allocated buffer */
1653 LocalFree(RelativeName
);
1655 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1663 DWORD
RCreateServiceW(
1664 handle_t BindingHandle
,
1665 SC_RPC_HANDLE hSCManager
,
1666 LPWSTR lpServiceName
,
1667 LPWSTR lpDisplayName
,
1668 DWORD dwDesiredAccess
,
1669 DWORD dwServiceType
,
1671 DWORD dwErrorControl
,
1672 LPWSTR lpBinaryPathName
,
1673 LPWSTR lpLoadOrderGroup
,
1675 LPBYTE lpDependencies
,
1677 LPWSTR lpServiceStartName
,
1680 LPSC_RPC_HANDLE lpServiceHandle
)
1682 PMANAGER_HANDLE hManager
;
1683 DWORD dwError
= ERROR_SUCCESS
;
1684 PSERVICE lpService
= NULL
;
1685 SC_HANDLE hServiceHandle
= NULL
;
1686 LPWSTR lpImagePath
= NULL
;
1687 HKEY hServiceKey
= NULL
;
1689 DPRINT("RCreateServiceW() called\n");
1690 DPRINT("lpServiceName = %S\n", lpServiceName
);
1691 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1692 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1693 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1694 DPRINT("dwStartType = %lu\n", dwStartType
);
1695 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1696 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1697 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1700 return ERROR_SHUTDOWN_IN_PROGRESS
;
1702 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1703 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1705 DPRINT1("Invalid manager handle!\n");
1706 return ERROR_INVALID_HANDLE
;
1709 /* Check access rights */
1710 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1711 SC_MANAGER_CREATE_SERVICE
))
1713 DPRINT1("Insufficient access rights! 0x%lx\n",
1714 hManager
->Handle
.DesiredAccess
);
1715 return ERROR_ACCESS_DENIED
;
1718 if (wcslen(lpServiceName
) == 0)
1720 return ERROR_INVALID_NAME
;
1723 if (wcslen(lpBinaryPathName
) == 0)
1725 return ERROR_INVALID_PARAMETER
;
1728 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1729 (lpServiceStartName
))
1731 return ERROR_INVALID_PARAMETER
;
1734 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1735 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1736 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1738 return ERROR_INVALID_PARAMETER
;
1741 if (dwStartType
> SERVICE_DISABLED
)
1743 return ERROR_INVALID_PARAMETER
;
1746 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1749 /* check if it is marked for deletion */
1750 if (lpService
->bDeleted
)
1751 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1752 /* Return Error exist */
1753 return ERROR_SERVICE_EXISTS
;
1756 if (lpDisplayName
!= NULL
&&
1757 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1758 return ERROR_DUPLICATE_SERVICE_NAME
;
1760 if (dwServiceType
& SERVICE_DRIVER
)
1762 dwError
= ScmCanonDriverImagePath(dwStartType
,
1765 if (dwError
!= ERROR_SUCCESS
)
1770 if (dwStartType
== SERVICE_BOOT_START
||
1771 dwStartType
== SERVICE_SYSTEM_START
)
1773 return ERROR_INVALID_PARAMETER
;
1777 /* Allocate a new service entry */
1778 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1780 if (dwError
!= ERROR_SUCCESS
)
1783 /* Fill the new service entry */
1784 lpService
->Status
.dwServiceType
= dwServiceType
;
1785 lpService
->dwStartType
= dwStartType
;
1786 lpService
->dwErrorControl
= dwErrorControl
;
1788 /* Fill the display name */
1789 if (lpDisplayName
!= NULL
&&
1790 *lpDisplayName
!= 0 &&
1791 wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1793 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1794 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1795 if (lpService
->lpDisplayName
== NULL
)
1797 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1800 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1803 /* Assign the service to a group */
1804 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1806 dwError
= ScmSetServiceGroup(lpService
,
1808 if (dwError
!= ERROR_SUCCESS
)
1812 /* Assign a new tag */
1813 if (lpdwTagId
!= NULL
)
1815 dwError
= ScmAssignNewTag(lpService
);
1816 if (dwError
!= ERROR_SUCCESS
)
1820 /* Write service data to the registry */
1821 /* Create the service key */
1822 dwError
= ScmCreateServiceKey(lpServiceName
,
1825 if (dwError
!= ERROR_SUCCESS
)
1828 /* Set the display name */
1829 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1831 RegSetValueExW(hServiceKey
,
1835 (LPBYTE
)lpDisplayName
,
1836 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1839 /* Set the service type */
1840 dwError
= RegSetValueExW(hServiceKey
,
1844 (LPBYTE
)&dwServiceType
,
1846 if (dwError
!= ERROR_SUCCESS
)
1849 /* Set the start value */
1850 dwError
= RegSetValueExW(hServiceKey
,
1854 (LPBYTE
)&dwStartType
,
1856 if (dwError
!= ERROR_SUCCESS
)
1859 /* Set the error control value */
1860 dwError
= RegSetValueExW(hServiceKey
,
1864 (LPBYTE
)&dwErrorControl
,
1866 if (dwError
!= ERROR_SUCCESS
)
1869 /* Set the image path */
1870 if (dwServiceType
& SERVICE_WIN32
)
1872 dwError
= RegSetValueExW(hServiceKey
,
1876 (LPBYTE
)lpBinaryPathName
,
1877 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1878 if (dwError
!= ERROR_SUCCESS
)
1881 else if (dwServiceType
& SERVICE_DRIVER
)
1883 dwError
= RegSetValueExW(hServiceKey
,
1887 (LPBYTE
)lpImagePath
,
1888 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1889 if (dwError
!= ERROR_SUCCESS
)
1893 /* Set the group name */
1894 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1896 dwError
= RegSetValueExW(hServiceKey
,
1900 (LPBYTE
)lpLoadOrderGroup
,
1901 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1902 if (dwError
!= ERROR_SUCCESS
)
1906 if (lpdwTagId
!= NULL
)
1908 dwError
= RegSetValueExW(hServiceKey
,
1912 (LPBYTE
)&lpService
->dwTag
,
1914 if (dwError
!= ERROR_SUCCESS
)
1918 /* Write dependencies */
1919 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1921 dwError
= ScmWriteDependencies(hServiceKey
,
1922 (LPWSTR
)lpDependencies
,
1924 if (dwError
!= ERROR_SUCCESS
)
1928 /* If a non driver and NULL for lpServiceName, write ObjectName as LocalSystem */
1929 if ((dwServiceType
& SERVICE_WIN32
) && (!lpServiceName
))
1931 dwError
= RegSetValueExW(hServiceKey
,
1935 (LPBYTE
)L
"LocalSystem",
1937 if (dwError
!= ERROR_SUCCESS
)
1941 if (lpPassword
!= NULL
)
1943 /* FIXME: Write password */
1946 dwError
= ScmCreateServiceHandle(lpService
,
1948 if (dwError
!= ERROR_SUCCESS
)
1951 dwError
= ScmCheckAccess(hServiceHandle
,
1953 if (dwError
!= ERROR_SUCCESS
)
1956 lpService
->dwRefCount
= 1;
1957 DPRINT1("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
1960 if (hServiceKey
!= NULL
)
1961 RegCloseKey(hServiceKey
);
1963 if (dwError
== ERROR_SUCCESS
)
1965 DPRINT("hService %p\n", hServiceHandle
);
1966 *lpServiceHandle
= (unsigned long)hServiceHandle
; /* FIXME: 64 bit portability */
1968 if (lpdwTagId
!= NULL
)
1969 *lpdwTagId
= lpService
->dwTag
;
1973 /* Release the display name buffer */
1974 if (lpService
->lpServiceName
!= NULL
)
1975 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1979 /* Remove the service handle */
1980 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
1983 if (lpService
!= NULL
)
1985 /* FIXME: remove the service entry */
1989 if (lpImagePath
!= NULL
)
1990 HeapFree(GetProcessHeap(), 0, lpImagePath
);
1992 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
1999 DWORD
REnumDependentServicesW(
2000 handle_t BindingHandle
,
2001 SC_RPC_HANDLE hService
,
2002 DWORD dwServiceState
,
2005 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2006 LPBOUNDED_DWORD_256K lpServicesReturned
)
2008 DWORD dwError
= ERROR_SUCCESS
;
2009 DWORD dwServicesReturned
= 0;
2010 DWORD dwServiceCount
;
2011 HKEY hServicesKey
= NULL
;
2012 LPSC_RPC_HANDLE hSCObject
;
2013 PSERVICE_HANDLE hSvc
;
2014 PSERVICE lpService
= NULL
;
2015 PSERVICE
*lpServicesArray
= NULL
;
2016 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2019 *pcbBytesNeeded
= 0;
2020 *lpServicesReturned
= 0;
2022 DPRINT("REnumDependentServicesW() called\n");
2024 hSCObject
= &hService
;
2025 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
2026 lpService
= hSvc
->ServiceEntry
;
2028 /* Check access rights */
2029 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2030 SC_MANAGER_ENUMERATE_SERVICE
))
2032 DPRINT1("Insufficient access rights! 0x%lx\n",
2033 hSvc
->Handle
.DesiredAccess
);
2034 return ERROR_ACCESS_DENIED
;
2037 /* Open the Services Reg key */
2038 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2039 L
"System\\CurrentControlSet\\Services",
2043 if (dwError
!= ERROR_SUCCESS
)
2046 /* First determine the bytes needed and get the number of dependent services */
2047 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2052 &dwServicesReturned
);
2053 if (dwError
!= ERROR_SUCCESS
)
2056 /* If buffer size is less than the bytes needed or pointer is null */
2057 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2059 dwError
= ERROR_MORE_DATA
;
2063 /* Allocate memory for array of service pointers */
2064 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2066 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2067 if (!lpServicesArray
)
2069 DPRINT1("Could not allocate a buffer!!\n");
2070 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2074 dwServicesReturned
= 0;
2075 *pcbBytesNeeded
= 0;
2077 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2082 &dwServicesReturned
);
2083 if (dwError
!= ERROR_SUCCESS
)
2088 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2089 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2091 /* Copy EnumDepenedentService to Buffer */
2092 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2094 lpService
= lpServicesArray
[dwServiceCount
];
2096 /* Copy status info */
2097 memcpy(&lpServicesPtr
->ServiceStatus
,
2099 sizeof(SERVICE_STATUS
));
2101 /* Copy display name */
2102 wcscpy(lpStr
, lpService
->lpDisplayName
);
2103 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2104 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2106 /* Copy service name */
2107 wcscpy(lpStr
, lpService
->lpServiceName
);
2108 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2109 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2114 *lpServicesReturned
= dwServicesReturned
;
2117 if (lpServicesArray
!= NULL
)
2118 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2120 RegCloseKey(hServicesKey
);
2122 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2129 DWORD
REnumServicesStatusW(
2130 handle_t BindingHandle
,
2131 SC_RPC_HANDLE hSCManager
,
2132 DWORD dwServiceType
,
2133 DWORD dwServiceState
,
2136 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2137 LPBOUNDED_DWORD_256K lpServicesReturned
,
2138 LPBOUNDED_DWORD_256K lpResumeHandle
)
2140 PMANAGER_HANDLE hManager
;
2142 DWORD dwError
= ERROR_SUCCESS
;
2143 PLIST_ENTRY ServiceEntry
;
2144 PSERVICE CurrentService
;
2146 DWORD dwRequiredSize
;
2147 DWORD dwServiceCount
;
2149 DWORD dwLastResumeCount
;
2150 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2153 DPRINT("REnumServicesStatusW() called\n");
2156 return ERROR_SHUTDOWN_IN_PROGRESS
;
2158 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2159 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2161 DPRINT1("Invalid manager handle!\n");
2162 return ERROR_INVALID_HANDLE
;
2165 /* Check access rights */
2166 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2167 SC_MANAGER_ENUMERATE_SERVICE
))
2169 DPRINT1("Insufficient access rights! 0x%lx\n",
2170 hManager
->Handle
.DesiredAccess
);
2171 return ERROR_ACCESS_DENIED
;
2174 *pcbBytesNeeded
= 0;
2175 *lpServicesReturned
= 0;
2177 dwLastResumeCount
= *lpResumeHandle
;
2179 /* FIXME: Lock the service list shared */
2181 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2182 if (lpService
== NULL
)
2184 dwError
= ERROR_SUCCESS
;
2191 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2192 ServiceEntry
!= &ServiceListHead
;
2193 ServiceEntry
= ServiceEntry
->Flink
)
2195 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2199 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2202 dwState
= SERVICE_ACTIVE
;
2203 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2204 dwState
= SERVICE_INACTIVE
;
2206 if ((dwState
& dwServiceState
) == 0)
2209 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2210 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2211 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2213 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2215 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2219 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2220 dwRequiredSize
+= dwSize
;
2222 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2225 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2226 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2229 ServiceEntry
!= &ServiceListHead
;
2230 ServiceEntry
= ServiceEntry
->Flink
)
2232 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2236 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2239 dwState
= SERVICE_ACTIVE
;
2240 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2241 dwState
= SERVICE_INACTIVE
;
2243 if ((dwState
& dwServiceState
) == 0)
2246 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2247 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2248 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2250 dwError
= ERROR_MORE_DATA
;
2253 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2255 *lpResumeHandle
= dwLastResumeCount
;
2256 *lpServicesReturned
= dwServiceCount
;
2257 *pcbBytesNeeded
= dwRequiredSize
;
2259 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2260 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2261 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2264 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2265 ServiceEntry
!= &ServiceListHead
;
2266 ServiceEntry
= ServiceEntry
->Flink
)
2268 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2272 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2275 dwState
= SERVICE_ACTIVE
;
2276 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2277 dwState
= SERVICE_INACTIVE
;
2279 if ((dwState
& dwServiceState
) == 0)
2282 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2283 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2284 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2286 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2289 /* Copy the service name */
2290 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2291 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2292 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2294 /* Copy the display name */
2295 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2296 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2297 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2299 /* Copy the status information */
2300 memcpy(&lpStatusPtr
->ServiceStatus
,
2301 &CurrentService
->Status
,
2302 sizeof(SERVICE_STATUS
));
2305 dwRequiredSize
+= dwSize
;
2309 /* FIXME: Unlock the service list */
2311 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2318 DWORD
ROpenSCManagerW(
2319 handle_t BindingHandle
,
2320 LPWSTR lpMachineName
,
2321 LPWSTR lpDatabaseName
,
2322 DWORD dwDesiredAccess
,
2323 LPSC_RPC_HANDLE lpScHandle
)
2328 DPRINT("ROpenSCManagerW() called\n");
2329 DPRINT("lpMachineName = %p\n", lpMachineName
);
2330 DPRINT("lpMachineName: %S\n", lpMachineName
);
2331 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2332 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2333 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2336 return ERROR_SHUTDOWN_IN_PROGRESS
;
2339 return ERROR_INVALID_PARAMETER
;
2341 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2343 if (dwError
!= ERROR_SUCCESS
)
2345 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2349 /* Check the desired access */
2350 dwError
= ScmCheckAccess(hHandle
,
2351 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2352 if (dwError
!= ERROR_SUCCESS
)
2354 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2355 HeapFree(GetProcessHeap(), 0, hHandle
);
2359 *lpScHandle
= (unsigned long)hHandle
; /* FIXME: 64 bit portability */
2360 DPRINT("*hScm = %p\n", *lpScHandle
);
2362 DPRINT("ROpenSCManagerW() done\n");
2364 return ERROR_SUCCESS
;
2369 DWORD
ROpenServiceW(
2370 handle_t BindingHandle
,
2371 SC_RPC_HANDLE hSCManager
,
2372 LPWSTR lpServiceName
,
2373 DWORD dwDesiredAccess
,
2374 LPSC_RPC_HANDLE lpServiceHandle
)
2377 PMANAGER_HANDLE hManager
;
2381 DPRINT("ROpenServiceW() called\n");
2382 DPRINT("hSCManager = %p\n", hSCManager
);
2383 DPRINT("lpServiceName = %p\n", lpServiceName
);
2384 DPRINT("lpServiceName: %S\n", lpServiceName
);
2385 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2388 return ERROR_SHUTDOWN_IN_PROGRESS
;
2390 if (!lpServiceHandle
)
2391 return ERROR_INVALID_PARAMETER
;
2394 return ERROR_INVALID_ADDRESS
;
2396 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2397 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2399 DPRINT1("Invalid manager handle!\n");
2400 return ERROR_INVALID_HANDLE
;
2403 /* FIXME: Lock the service list */
2405 /* Get service database entry */
2406 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2407 if (lpService
== NULL
)
2409 DPRINT("Could not find a service!\n");
2410 return ERROR_SERVICE_DOES_NOT_EXIST
;
2413 /* Create a service handle */
2414 dwError
= ScmCreateServiceHandle(lpService
,
2416 if (dwError
!= ERROR_SUCCESS
)
2418 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2422 /* Check the desired access */
2423 dwError
= ScmCheckAccess(hHandle
,
2425 if (dwError
!= ERROR_SUCCESS
)
2427 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2428 HeapFree(GetProcessHeap(), 0, hHandle
);
2432 lpService
->dwRefCount
++;
2433 DPRINT1("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2435 *lpServiceHandle
= (unsigned long)hHandle
; /* FIXME: 64 bit portability */
2436 DPRINT("*hService = %p\n", *lpServiceHandle
);
2438 DPRINT("ROpenServiceW() done\n");
2440 return ERROR_SUCCESS
;
2445 DWORD
RQueryServiceConfigW(
2446 handle_t BindingHandle
,
2447 SC_RPC_HANDLE hService
,
2448 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2450 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2452 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2453 DWORD dwError
= ERROR_SUCCESS
;
2454 PSERVICE_HANDLE hSvc
;
2455 PSERVICE lpService
= NULL
;
2456 HKEY hServiceKey
= NULL
;
2457 LPWSTR lpImagePath
= NULL
;
2458 LPWSTR lpServiceStartName
= NULL
;
2459 DWORD dwRequiredSize
;
2460 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2461 WCHAR lpEmptyString
[] = {0,0};
2464 DPRINT("RQueryServiceConfigW() called\n");
2467 return ERROR_SHUTDOWN_IN_PROGRESS
;
2469 hSvc
= (PSERVICE_HANDLE
)hService
;
2470 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2472 DPRINT1("Invalid handle tag!\n");
2473 return ERROR_INVALID_HANDLE
;
2476 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2477 SERVICE_QUERY_CONFIG
))
2479 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2480 return ERROR_ACCESS_DENIED
;
2483 lpService
= hSvc
->ServiceEntry
;
2484 if (lpService
== NULL
)
2486 DPRINT1("lpService == NULL!\n");
2487 return ERROR_INVALID_HANDLE
;
2490 /* FIXME: Lock the service database shared */
2492 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2495 if (dwError
!= ERROR_SUCCESS
)
2498 dwError
= ScmReadString(hServiceKey
,
2501 if (dwError
!= ERROR_SUCCESS
)
2504 ScmReadString(hServiceKey
,
2506 &lpServiceStartName
);
2508 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2510 if (lpImagePath
!= NULL
)
2511 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2513 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2515 if (lpService
->lpGroup
!= NULL
)
2516 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2518 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2520 /* FIXME: Add Dependencies length*/
2522 if (lpServiceStartName
!= NULL
)
2523 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2525 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2527 if (lpService
->lpDisplayName
!= NULL
)
2528 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2530 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2532 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2534 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2538 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2539 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2540 lpConfig
->dwStartType
= lpService
->dwStartType
;
2541 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2542 lpConfig
->dwTagId
= lpService
->dwTag
;
2544 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2546 if (lpImagePath
!= NULL
)
2548 wcscpy(lpStr
, lpImagePath
);
2552 wcscpy(lpStr
, lpEmptyString
);
2555 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2556 lpStr
+= (wcslen(lpStr
) + 1);
2558 if (lpService
->lpGroup
!= NULL
)
2560 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2564 wcscpy(lpStr
, lpEmptyString
);
2567 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2568 lpStr
+= (wcslen(lpStr
) + 1);
2570 /* FIXME: Append Dependencies */
2571 wcscpy(lpStr
, lpEmptyString
);
2573 lpStr
+= (wcslen(lpStr
) + 1);
2574 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2576 if (lpServiceStartName
!= NULL
)
2578 wcscpy(lpStr
, lpServiceStartName
);
2582 wcscpy(lpStr
, lpEmptyString
);
2585 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2586 lpStr
+= (wcslen(lpStr
) + 1);
2588 if (lpService
->lpDisplayName
!= NULL
)
2590 wcscpy(lpStr
, lpService
->lpDisplayName
);
2594 wcscpy(lpStr
, lpEmptyString
);
2597 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2600 if (pcbBytesNeeded
!= NULL
)
2601 *pcbBytesNeeded
= dwRequiredSize
;
2604 if (lpImagePath
!= NULL
)
2605 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2607 if (lpServiceStartName
!= NULL
)
2608 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2610 if (hServiceKey
!= NULL
)
2611 RegCloseKey(hServiceKey
);
2613 /* FIXME: Unlock the service database */
2615 DPRINT("RQueryServiceConfigW() done\n");
2622 DWORD
RQueryServiceLockStatusW(
2623 handle_t BindingHandle
,
2624 SC_RPC_HANDLE hSCManager
,
2625 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2627 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2630 return ERROR_CALL_NOT_IMPLEMENTED
;
2635 DWORD
RStartServiceW(
2636 handle_t BindingHandle
,
2637 SC_RPC_HANDLE hService
,
2639 LPSTRING_PTRSW argv
)
2641 DWORD dwError
= ERROR_SUCCESS
;
2642 PSERVICE_HANDLE hSvc
;
2643 PSERVICE lpService
= NULL
;
2645 DPRINT("RStartServiceW() called\n");
2648 return ERROR_SHUTDOWN_IN_PROGRESS
;
2650 hSvc
= (PSERVICE_HANDLE
)hService
;
2651 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2653 DPRINT1("Invalid handle tag!\n");
2654 return ERROR_INVALID_HANDLE
;
2657 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2660 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2661 return ERROR_ACCESS_DENIED
;
2664 lpService
= hSvc
->ServiceEntry
;
2665 if (lpService
== NULL
)
2667 DPRINT1("lpService == NULL!\n");
2668 return ERROR_INVALID_HANDLE
;
2671 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2672 return ERROR_SERVICE_DISABLED
;
2674 if (lpService
->bDeleted
)
2675 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2682 /* Start the service */
2683 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2690 DWORD
RGetServiceDisplayNameW(
2691 handle_t BindingHandle
,
2692 SC_RPC_HANDLE hSCManager
,
2693 LPWSTR lpServiceName
,
2694 LPWSTR lpDisplayName
,
2697 // PMANAGER_HANDLE hManager;
2702 DPRINT("RGetServiceDisplayNameW() called\n");
2703 DPRINT("hSCManager = %p\n", hSCManager
);
2704 DPRINT("lpServiceName: %S\n", lpServiceName
);
2705 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2706 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2708 // hManager = (PMANAGER_HANDLE)hSCManager;
2709 // if (hManager->Handle.Tag != MANAGER_TAG)
2711 // DPRINT1("Invalid manager handle!\n");
2712 // return ERROR_INVALID_HANDLE;
2715 /* Get service database entry */
2716 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2717 if (lpService
== NULL
)
2719 DPRINT1("Could not find a service!\n");
2721 /* If the service could not be found and lpcchBuffer is 0, windows
2722 puts null in lpDisplayName and puts 1 in lpcchBuffer */
2723 if (*lpcchBuffer
== 0)
2726 *lpDisplayName
= '\0';
2729 return ERROR_SERVICE_DOES_NOT_EXIST
;
2732 if (!lpService
->lpDisplayName
)
2734 dwLength
= wcslen(lpService
->lpServiceName
);
2736 if (lpServiceName
!= NULL
&&
2737 *lpcchBuffer
> dwLength
)
2739 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2744 dwLength
= wcslen(lpService
->lpDisplayName
);
2746 if (lpDisplayName
!= NULL
&&
2747 *lpcchBuffer
> dwLength
)
2749 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2753 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2755 *lpcchBuffer
= dwLength
;
2762 DWORD
RGetServiceKeyNameW(
2763 handle_t BindingHandle
,
2764 SC_RPC_HANDLE hSCManager
,
2765 LPWSTR lpDisplayName
,
2766 LPWSTR lpServiceName
,
2769 // PMANAGER_HANDLE hManager;
2774 DPRINT("RGetServiceKeyNameW() called\n");
2775 DPRINT("hSCManager = %p\n", hSCManager
);
2776 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2777 DPRINT("lpServiceName: %p\n", lpServiceName
);
2778 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2780 // hManager = (PMANAGER_HANDLE)hSCManager;
2781 // if (hManager->Handle.Tag != MANAGER_TAG)
2783 // DPRINT1("Invalid manager handle!\n");
2784 // return ERROR_INVALID_HANDLE;
2787 /* Get service database entry */
2788 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2789 if (lpService
== NULL
)
2791 DPRINT1("Could not find a service!\n");
2793 /* If the service could not be found and lpcchBuffer is 0, windows
2794 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2795 if (*lpcchBuffer
== 0)
2798 *lpServiceName
= '\0';
2801 return ERROR_SERVICE_DOES_NOT_EXIST
;
2804 dwLength
= wcslen(lpService
->lpServiceName
);
2806 if (lpServiceName
!= NULL
&&
2807 *lpcchBuffer
> dwLength
)
2809 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2810 *lpcchBuffer
= dwLength
;
2811 return ERROR_SUCCESS
;
2814 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2816 *lpcchBuffer
= dwLength
* 2;
2823 DWORD
RSetServiceBitsA(
2824 handle_t BindingHandle
,
2825 SC_RPC_HANDLE hServiceStatus
,
2826 DWORD dwServiceBits
,
2828 int bUpdateImmediately
,
2832 return ERROR_CALL_NOT_IMPLEMENTED
;
2837 DWORD
RChangeServiceConfigA(
2838 handle_t BindingHandle
,
2839 SC_RPC_HANDLE hService
,
2840 DWORD dwServiceType
,
2842 DWORD dwErrorControl
,
2843 LPSTR lpBinaryPathName
,
2844 LPSTR lpLoadOrderGroup
,
2846 LPSTR lpDependencies
,
2848 LPSTR lpServiceStartName
,
2851 LPSTR lpDisplayName
)
2853 DWORD dwError
= ERROR_SUCCESS
;
2854 PSERVICE_HANDLE hSvc
;
2855 PSERVICE lpService
= NULL
;
2856 HKEY hServiceKey
= NULL
;
2857 LPWSTR lpDisplayNameW
= NULL
;
2858 // LPWSTR lpBinaryPathNameW = NULL;
2859 LPWSTR lpLoadOrderGroupW
= NULL
;
2860 LPWSTR lpDependenciesW
= NULL
;
2861 // LPWSTR lpPasswordW = NULL;
2863 DPRINT("RChangeServiceConfigA() called\n");
2864 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2865 DPRINT("dwStartType = %lu\n", dwStartType
);
2866 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2867 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2868 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2869 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2872 return ERROR_SHUTDOWN_IN_PROGRESS
;
2874 hSvc
= (PSERVICE_HANDLE
)hService
;
2875 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2877 DPRINT1("Invalid handle tag!\n");
2878 return ERROR_INVALID_HANDLE
;
2881 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2882 SERVICE_CHANGE_CONFIG
))
2884 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2885 return ERROR_ACCESS_DENIED
;
2888 lpService
= hSvc
->ServiceEntry
;
2889 if (lpService
== NULL
)
2891 DPRINT1("lpService == NULL!\n");
2892 return ERROR_INVALID_HANDLE
;
2895 /* FIXME: Lock database exclusively */
2897 if (lpService
->bDeleted
)
2899 /* FIXME: Unlock database */
2900 DPRINT1("The service has already been marked for delete!\n");
2901 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2904 /* Open the service key */
2905 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2908 if (dwError
!= ERROR_SUCCESS
)
2911 /* Write service data to the registry */
2913 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2915 /* Set the display name */
2916 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2918 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2919 if (lpDisplayNameW
== NULL
)
2921 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2925 MultiByteToWideChar(CP_ACP
,
2930 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2932 RegSetValueExW(hServiceKey
,
2936 (LPBYTE
)lpDisplayNameW
,
2937 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2939 /* Update lpService->lpDisplayName */
2940 if (lpService
->lpDisplayName
)
2941 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2943 lpService
->lpDisplayName
= lpDisplayNameW
;
2946 if (dwServiceType
!= SERVICE_NO_CHANGE
)
2948 /* Set the service type */
2949 dwError
= RegSetValueExW(hServiceKey
,
2953 (LPBYTE
)&dwServiceType
,
2955 if (dwError
!= ERROR_SUCCESS
)
2958 lpService
->Status
.dwServiceType
= dwServiceType
;
2961 if (dwStartType
!= SERVICE_NO_CHANGE
)
2963 /* Set the start value */
2964 dwError
= RegSetValueExW(hServiceKey
,
2968 (LPBYTE
)&dwStartType
,
2970 if (dwError
!= ERROR_SUCCESS
)
2973 lpService
->dwStartType
= dwStartType
;
2976 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
2978 /* Set the error control value */
2979 dwError
= RegSetValueExW(hServiceKey
,
2983 (LPBYTE
)&dwErrorControl
,
2985 if (dwError
!= ERROR_SUCCESS
)
2988 lpService
->dwErrorControl
= dwErrorControl
;
2992 /* FIXME: set the new ImagePath value */
2994 /* Set the image path */
2995 if (dwServiceType
& SERVICE_WIN32
)
2997 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
2999 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3000 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, (wcslen(lpBinaryPathNameW
)+1) * sizeof(WCHAR
));
3001 dwError
= RegSetValueExW(hServiceKey
,
3005 (LPBYTE
)lpBinaryPathNameW
,
3006 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3007 if (dwError
!= ERROR_SUCCESS
)
3011 else if (dwServiceType
& SERVICE_DRIVER
)
3013 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3015 dwError
= RegSetValueExW(hServiceKey
,
3019 (LPBYTE
)lpImagePath
,
3020 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3021 if (dwError
!= ERROR_SUCCESS
)
3027 /* Set the group name */
3028 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3030 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3032 (strlen(lpLoadOrderGroup
)+1) * sizeof(WCHAR
));
3033 if (lpLoadOrderGroupW
== NULL
)
3035 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3039 MultiByteToWideChar(CP_ACP
,
3044 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3046 dwError
= RegSetValueExW(hServiceKey
,
3050 (LPBYTE
)lpLoadOrderGroupW
,
3051 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3052 if (dwError
!= ERROR_SUCCESS
)
3055 /* FIXME: Update lpService->lpServiceGroup */
3057 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3060 if (lpdwTagId
!= NULL
)
3062 dwError
= ScmAssignNewTag(lpService
);
3063 if (dwError
!= ERROR_SUCCESS
)
3066 dwError
= RegSetValueExW(hServiceKey
,
3070 (LPBYTE
)&lpService
->dwTag
,
3072 if (dwError
!= ERROR_SUCCESS
)
3075 *lpdwTagId
= lpService
->dwTag
;
3078 /* Write dependencies */
3079 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3081 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3083 (strlen(lpDependencies
)+1) * sizeof(WCHAR
));
3084 if (lpDependenciesW
== NULL
)
3086 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3090 MultiByteToWideChar(CP_ACP
,
3095 (wcslen(lpDependenciesW
)+1) * sizeof(WCHAR
));
3097 dwError
= ScmWriteDependencies(hServiceKey
,
3098 (LPWSTR
)lpDependenciesW
,
3101 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3104 if (lpPassword
!= NULL
)
3106 /* FIXME: Write password */
3109 /* FIXME: Unlock database */
3112 if (hServiceKey
!= NULL
)
3113 RegCloseKey(hServiceKey
);
3115 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3122 DWORD
RCreateServiceA(
3123 handle_t BindingHandle
,
3124 SC_RPC_HANDLE hSCManager
,
3125 LPSTR lpServiceName
,
3126 LPSTR lpDisplayName
,
3127 DWORD dwDesiredAccess
,
3128 DWORD dwServiceType
,
3130 DWORD dwErrorControl
,
3131 LPSTR lpBinaryPathName
,
3132 LPSTR lpLoadOrderGroup
,
3134 LPBYTE lpDependencies
,
3136 LPSTR lpServiceStartName
,
3139 LPSC_RPC_HANDLE lpServiceHandle
)
3142 return ERROR_CALL_NOT_IMPLEMENTED
;
3147 DWORD
REnumDependentServicesA(
3148 handle_t BindingHandle
,
3149 SC_RPC_HANDLE hService
,
3150 DWORD dwServiceState
,
3153 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3154 LPBOUNDED_DWORD_256K lpServicesReturned
)
3156 DWORD dwError
= ERROR_SUCCESS
;
3157 DWORD dwServicesReturned
= 0;
3158 DWORD dwServiceCount
;
3159 HKEY hServicesKey
= NULL
;
3160 LPSC_RPC_HANDLE hSCObject
;
3161 PSERVICE_HANDLE hSvc
;
3162 PSERVICE lpService
= NULL
;
3163 PSERVICE
*lpServicesArray
= NULL
;
3164 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3167 *pcbBytesNeeded
= 0;
3168 *lpServicesReturned
= 0;
3170 DPRINT("REnumDependentServicesA() called\n");
3172 hSCObject
= &hService
;
3173 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3174 lpService
= hSvc
->ServiceEntry
;
3176 /* Check access rights */
3177 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3178 SC_MANAGER_ENUMERATE_SERVICE
))
3180 DPRINT1("Insufficient access rights! 0x%lx\n",
3181 hSvc
->Handle
.DesiredAccess
);
3182 return ERROR_ACCESS_DENIED
;
3185 /* Open the Services Reg key */
3186 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3187 L
"System\\CurrentControlSet\\Services",
3192 if (dwError
!= ERROR_SUCCESS
) return dwError
;
3194 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3195 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3196 are the same for both. Verified in WINXP. */
3198 /* First determine the bytes needed and get the number of dependent services*/
3199 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3204 &dwServicesReturned
);
3205 if (dwError
!= ERROR_SUCCESS
)
3208 /* If buffer size is less than the bytes needed or pointer is null*/
3209 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3211 dwError
= ERROR_MORE_DATA
;
3215 /* Allocate memory for array of service pointers */
3216 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3218 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3219 if (!lpServicesArray
)
3221 DPRINT1("Could not allocate a buffer!!\n");
3222 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3226 dwServicesReturned
= 0;
3227 *pcbBytesNeeded
= 0;
3229 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3234 &dwServicesReturned
);
3235 if (dwError
!= ERROR_SUCCESS
)
3240 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3241 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3243 /* Copy EnumDepenedentService to Buffer */
3244 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3246 lpService
= lpServicesArray
[dwServiceCount
];
3248 /* Copy the status info */
3249 memcpy(&lpServicesPtr
->ServiceStatus
,
3251 sizeof(SERVICE_STATUS
));
3253 /* Copy display name */
3254 WideCharToMultiByte(CP_ACP
,
3256 lpService
->lpDisplayName
,
3259 wcslen(lpService
->lpDisplayName
),
3262 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3263 lpStr
+= strlen(lpStr
) + 1;