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 DPRINT("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 ScmIsValidServiceState(DWORD dwCurrentState
)
988 switch (dwCurrentState
)
990 case SERVICE_STOPPED
:
991 case SERVICE_START_PENDING
:
992 case SERVICE_STOP_PENDING
:
993 case SERVICE_RUNNING
:
994 case SERVICE_CONTINUE_PENDING
:
995 case SERVICE_PAUSE_PENDING
:
1006 DWORD
RSetServiceStatus(
1007 handle_t BindingHandle
,
1008 SC_RPC_HANDLE hServiceStatus
,
1009 LPSERVICE_STATUS lpServiceStatus
)
1013 DPRINT("RSetServiceStatus() called\n");
1014 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1015 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1016 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1017 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1018 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1019 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1020 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1021 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1023 if (hServiceStatus
== 0)
1025 DPRINT1("hServiceStatus == NULL!\n");
1026 return ERROR_INVALID_HANDLE
;
1029 lpService
= ScmGetServiceEntryByClientHandle((ULONG
)hServiceStatus
);
1030 if (lpService
== NULL
)
1032 DPRINT1("lpService == NULL!\n");
1033 return ERROR_INVALID_HANDLE
;
1036 /* Check current state */
1037 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1039 DPRINT1("Invalid service state!\n");
1040 return ERROR_INVALID_DATA
;
1043 /* Check service type */
1044 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1045 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1047 DPRINT1("Invalid service type!\n");
1048 return ERROR_INVALID_DATA
;
1051 /* Check accepted controls */
1052 if (lpServiceStatus
->dwControlsAccepted
== 0 ||
1053 lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1055 DPRINT1("Invalid controls accepted!\n");
1056 return ERROR_INVALID_DATA
;
1060 RtlCopyMemory(&lpService
->Status
,
1062 sizeof(SERVICE_STATUS
));
1064 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1065 DPRINT("RSetServiceStatus() done\n");
1067 return ERROR_SUCCESS
;
1072 DWORD
RUnlockServiceDatabase(
1073 handle_t BindingHandle
,
1077 return ERROR_SUCCESS
;
1082 DWORD
RNotifyBootConfigStatus(
1083 handle_t BindingHandle
,
1084 SVCCTL_HANDLEW lpMachineName
,
1085 DWORD BootAcceptable
)
1088 return ERROR_CALL_NOT_IMPLEMENTED
;
1093 DWORD
RI_ScSetServiceBitsW(
1094 handle_t BindingHandle
,
1095 SC_RPC_HANDLE hServiceStatus
,
1096 DWORD dwServiceBits
,
1098 int bUpdateImmediately
,
1102 return ERROR_CALL_NOT_IMPLEMENTED
;
1107 DWORD
RChangeServiceConfigW(
1108 handle_t BindingHandle
,
1109 SC_RPC_HANDLE hService
,
1110 DWORD dwServiceType
,
1112 DWORD dwErrorControl
,
1113 LPWSTR lpBinaryPathName
,
1114 LPWSTR lpLoadOrderGroup
,
1116 LPBYTE lpDependencies
,
1118 LPWSTR lpServiceStartName
,
1121 LPWSTR lpDisplayName
)
1123 DWORD dwError
= ERROR_SUCCESS
;
1124 PSERVICE_HANDLE hSvc
;
1125 PSERVICE lpService
= NULL
;
1126 HKEY hServiceKey
= NULL
;
1127 LPWSTR lpDisplayNameW
= NULL
;
1129 DPRINT("RChangeServiceConfigW() called\n");
1130 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1131 DPRINT("dwStartType = %lu\n", dwStartType
);
1132 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1133 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1134 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1135 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1138 return ERROR_SHUTDOWN_IN_PROGRESS
;
1140 hSvc
= (PSERVICE_HANDLE
)hService
;
1141 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1143 DPRINT1("Invalid handle tag!\n");
1144 return ERROR_INVALID_HANDLE
;
1147 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1148 SERVICE_CHANGE_CONFIG
))
1150 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1151 return ERROR_ACCESS_DENIED
;
1154 lpService
= hSvc
->ServiceEntry
;
1155 if (lpService
== NULL
)
1157 DPRINT1("lpService == NULL!\n");
1158 return ERROR_INVALID_HANDLE
;
1161 /* FIXME: Lock database exclusively */
1163 if (lpService
->bDeleted
)
1165 /* FIXME: Unlock database */
1166 DPRINT1("The service has already been marked for delete!\n");
1167 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1170 /* Open the service key */
1171 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1174 if (dwError
!= ERROR_SUCCESS
)
1177 /* Write service data to the registry */
1178 /* Set the display name */
1179 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1181 RegSetValueExW(hServiceKey
,
1185 (LPBYTE
)lpDisplayName
,
1186 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1188 /* Update the display name */
1189 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1191 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1192 if (lpDisplayNameW
== NULL
)
1194 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1198 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1199 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1201 lpService
->lpDisplayName
= lpDisplayNameW
;
1204 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1206 /* Set the service type */
1207 dwError
= RegSetValueExW(hServiceKey
,
1211 (LPBYTE
)&dwServiceType
,
1213 if (dwError
!= ERROR_SUCCESS
)
1216 lpService
->Status
.dwServiceType
= dwServiceType
;
1219 if (dwStartType
!= SERVICE_NO_CHANGE
)
1221 /* Set the start value */
1222 dwError
= RegSetValueExW(hServiceKey
,
1226 (LPBYTE
)&dwStartType
,
1228 if (dwError
!= ERROR_SUCCESS
)
1231 lpService
->dwStartType
= dwStartType
;
1234 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1236 /* Set the error control value */
1237 dwError
= RegSetValueExW(hServiceKey
,
1241 (LPBYTE
)&dwErrorControl
,
1243 if (dwError
!= ERROR_SUCCESS
)
1246 lpService
->dwErrorControl
= dwErrorControl
;
1250 /* FIXME: set the new ImagePath value */
1252 /* Set the image path */
1253 if (dwServiceType
& SERVICE_WIN32
)
1255 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1257 dwError
= RegSetValueExW(hServiceKey
,
1261 (LPBYTE
)lpBinaryPathName
,
1262 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1263 if (dwError
!= ERROR_SUCCESS
)
1267 else if (dwServiceType
& SERVICE_DRIVER
)
1269 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1271 dwError
= RegSetValueExW(hServiceKey
,
1275 (LPBYTE
)lpImagePath
,
1276 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1277 if (dwError
!= ERROR_SUCCESS
)
1283 /* Set the group name */
1284 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1286 dwError
= RegSetValueExW(hServiceKey
,
1290 (LPBYTE
)lpLoadOrderGroup
,
1291 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1292 if (dwError
!= ERROR_SUCCESS
)
1294 /* FIXME: Update lpService->lpServiceGroup */
1297 if (lpdwTagId
!= NULL
)
1299 dwError
= ScmAssignNewTag(lpService
);
1300 if (dwError
!= ERROR_SUCCESS
)
1303 dwError
= RegSetValueExW(hServiceKey
,
1307 (LPBYTE
)&lpService
->dwTag
,
1309 if (dwError
!= ERROR_SUCCESS
)
1312 *lpdwTagId
= lpService
->dwTag
;
1315 /* Write dependencies */
1316 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1318 dwError
= ScmWriteDependencies(hServiceKey
,
1319 (LPWSTR
)lpDependencies
,
1321 if (dwError
!= ERROR_SUCCESS
)
1325 if (lpPassword
!= NULL
)
1327 /* FIXME: Write password */
1330 /* FIXME: Unlock database */
1333 if (hServiceKey
!= NULL
)
1334 RegCloseKey(hServiceKey
);
1336 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1342 /* Create a path suitable for the bootloader out of the full path */
1344 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1346 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1349 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1350 OBJECT_ATTRIBUTES ObjectAttributes
;
1352 HANDLE SymbolicLinkHandle
;
1354 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1356 ServiceNameLen
= wcslen(CanonName
);
1358 /* First check, if it's already good */
1359 if (ServiceNameLen
> 12 &&
1360 !wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1362 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1363 if (*RelativeName
== NULL
)
1365 DPRINT1("Error allocating memory for boot driver name!\n");
1366 return ERROR_NOT_ENOUGH_MEMORY
;
1370 wcscpy(*RelativeName
, CanonName
);
1372 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1373 return ERROR_SUCCESS
;
1376 /* If it has %SystemRoot% prefix, substitute it to \System*/
1377 if (ServiceNameLen
> 13 &&
1378 !wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1380 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1381 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1383 if (*RelativeName
== NULL
)
1385 DPRINT1("Error allocating memory for boot driver name!\n");
1386 return ERROR_NOT_ENOUGH_MEMORY
;
1390 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1391 wcscat(*RelativeName
, CanonName
+ 13);
1393 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1394 return ERROR_SUCCESS
;
1397 /* Get buffer size needed for expanding env strings */
1398 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1400 if (BufferSize
<= 1)
1402 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1403 return ERROR_INVALID_ENVIRONMENT
;
1406 /* Allocate memory, since the size is known now */
1407 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1410 DPRINT1("Error allocating memory for boot driver name!\n");
1411 return ERROR_NOT_ENOUGH_MEMORY
;
1415 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1418 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1419 LocalFree(Expanded
);
1420 return ERROR_NOT_ENOUGH_MEMORY
;
1423 /* Convert to NY-style path */
1424 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1426 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1427 return ERROR_INVALID_ENVIRONMENT
;
1430 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1432 /* No need to keep the dos-path anymore */
1433 LocalFree(Expanded
);
1435 /* Copy it to the allocated place */
1436 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1439 DPRINT1("Error allocating memory for boot driver name!\n");
1440 return ERROR_NOT_ENOUGH_MEMORY
;
1443 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1444 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1445 Expanded
[ExpandedLen
] = 0;
1447 if (ServiceNameLen
> ExpandedLen
&&
1448 !wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1450 /* Only \SystemRoot\ is missing */
1451 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1452 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1453 if (*RelativeName
== NULL
)
1455 DPRINT1("Error allocating memory for boot driver name!\n");
1456 LocalFree(Expanded
);
1457 return ERROR_NOT_ENOUGH_MEMORY
;
1460 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1461 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1463 RtlFreeUnicodeString(&NtPathName
);
1464 return ERROR_SUCCESS
;
1467 /* The most complex case starts here */
1468 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1469 InitializeObjectAttributes(&ObjectAttributes
,
1471 OBJ_CASE_INSENSITIVE
,
1475 /* Open this symlink */
1476 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1478 if (NT_SUCCESS(Status
))
1480 LinkTarget
.Length
= 0;
1481 LinkTarget
.MaximumLength
= 0;
1483 DPRINT("Opened symbolic link object\n");
1485 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1486 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1488 /* Check if required buffer size is sane */
1489 if (BufferSize
> 0xFFFD)
1491 DPRINT1("Too large buffer required\n");
1494 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1495 LocalFree(Expanded
);
1496 return ERROR_NOT_ENOUGH_MEMORY
;
1499 /* Alloc the string */
1500 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1501 if (!LinkTarget
.Buffer
)
1503 DPRINT1("Unable to alloc buffer\n");
1504 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1505 LocalFree(Expanded
);
1506 return ERROR_NOT_ENOUGH_MEMORY
;
1509 /* Do a real query now */
1510 LinkTarget
.Length
= BufferSize
;
1511 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1513 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1514 if (NT_SUCCESS(Status
))
1516 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1518 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1519 if ((ServiceNameLen
> ExpandedLen
) &&
1520 !wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1522 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1523 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1525 if (*RelativeName
== NULL
)
1527 DPRINT1("Unable to alloc buffer\n");
1528 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1529 LocalFree(Expanded
);
1530 RtlFreeUnicodeString(&NtPathName
);
1531 return ERROR_NOT_ENOUGH_MEMORY
;
1534 /* Copy it over, substituting the first part
1536 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1537 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1540 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1541 LocalFree(Expanded
);
1542 RtlFreeUnicodeString(&NtPathName
);
1544 /* Return success */
1545 return ERROR_SUCCESS
;
1549 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1550 LocalFree(Expanded
);
1551 RtlFreeUnicodeString(&NtPathName
);
1552 return ERROR_INVALID_PARAMETER
;
1557 DPRINT1("Error, Status = %08X\n", Status
);
1558 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1559 LocalFree(Expanded
);
1560 RtlFreeUnicodeString(&NtPathName
);
1561 return ERROR_INVALID_PARAMETER
;
1566 DPRINT1("Error, Status = %08X\n", Status
);
1567 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1568 LocalFree(Expanded
);
1569 RtlFreeUnicodeString(&NtPathName
);
1570 return ERROR_INVALID_PARAMETER
;
1575 DPRINT1("Error, Status = %08X\n", Status
);
1576 LocalFree(Expanded
);
1577 return ERROR_INVALID_PARAMETER
;
1581 *RelativeName
= NULL
;
1582 return ERROR_INVALID_PARAMETER
;
1586 ScmCanonDriverImagePath(DWORD dwStartType
,
1587 wchar_t *lpServiceName
,
1588 wchar_t **lpCanonName
)
1590 DWORD ServiceNameLen
, Result
;
1591 UNICODE_STRING NtServiceName
;
1592 WCHAR
*RelativeName
;
1593 WCHAR
*SourceName
= lpServiceName
;
1595 /* Calculate the length of the service's name */
1596 ServiceNameLen
= wcslen(lpServiceName
);
1598 /* 12 is wcslen(L"\\SystemRoot\\") */
1599 if (ServiceNameLen
> 12 &&
1600 !wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1602 /* SystemRoot prefix is already included */
1604 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1606 if (*lpCanonName
== NULL
)
1608 DPRINT1("Error allocating memory for canonized service name!\n");
1609 return ERROR_NOT_ENOUGH_MEMORY
;
1612 /* If it's a boot-time driver, it must be systemroot relative */
1613 if (dwStartType
== SERVICE_BOOT_START
)
1617 wcscpy(*lpCanonName
, SourceName
);
1619 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1623 /* Check if it has %SystemRoot% (len=13) */
1624 if (ServiceNameLen
> 13 &&
1625 !wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1627 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1628 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1630 if (*lpCanonName
== NULL
)
1632 DPRINT1("Error allocating memory for canonized service name!\n");
1633 return ERROR_NOT_ENOUGH_MEMORY
;
1636 /* If it's a boot-time driver, it must be systemroot relative */
1637 if (dwStartType
== SERVICE_BOOT_START
)
1638 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1640 wcscat(*lpCanonName
, lpServiceName
+ 13);
1642 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1646 /* Check if it's a relative path name */
1647 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1649 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1651 if (*lpCanonName
== NULL
)
1653 DPRINT1("Error allocating memory for canonized service name!\n");
1654 return ERROR_NOT_ENOUGH_MEMORY
;
1657 /* Just copy it over without changing */
1658 wcscpy(*lpCanonName
, lpServiceName
);
1663 /* It seems to be a DOS path, convert it */
1664 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1666 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1667 return ERROR_INVALID_PARAMETER
;
1670 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1672 if (*lpCanonName
== NULL
)
1674 DPRINT1("Error allocating memory for canonized service name!\n");
1675 RtlFreeUnicodeString(&NtServiceName
);
1676 return ERROR_NOT_ENOUGH_MEMORY
;
1679 /* Copy the string */
1680 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1682 /* The unicode string is not needed anymore */
1683 RtlFreeUnicodeString(&NtServiceName
);
1685 if (dwStartType
!= SERVICE_BOOT_START
)
1687 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1691 /* The service is boot-started, so must be relative */
1692 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1695 /* There is a problem, free name and return */
1696 LocalFree(*lpCanonName
);
1697 DPRINT1("Error converting named!\n");
1701 ASSERT(RelativeName
);
1703 /* Copy that string */
1704 wcscpy(*lpCanonName
, RelativeName
+ 12);
1706 /* Free the allocated buffer */
1707 LocalFree(RelativeName
);
1709 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1717 DWORD
RCreateServiceW(
1718 handle_t BindingHandle
,
1719 SC_RPC_HANDLE hSCManager
,
1720 LPWSTR lpServiceName
,
1721 LPWSTR lpDisplayName
,
1722 DWORD dwDesiredAccess
,
1723 DWORD dwServiceType
,
1725 DWORD dwErrorControl
,
1726 LPWSTR lpBinaryPathName
,
1727 LPWSTR lpLoadOrderGroup
,
1729 LPBYTE lpDependencies
,
1731 LPWSTR lpServiceStartName
,
1734 LPSC_RPC_HANDLE lpServiceHandle
)
1736 PMANAGER_HANDLE hManager
;
1737 DWORD dwError
= ERROR_SUCCESS
;
1738 PSERVICE lpService
= NULL
;
1739 SC_HANDLE hServiceHandle
= NULL
;
1740 LPWSTR lpImagePath
= NULL
;
1741 HKEY hServiceKey
= NULL
;
1743 DPRINT("RCreateServiceW() called\n");
1744 DPRINT("lpServiceName = %S\n", lpServiceName
);
1745 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1746 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1747 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1748 DPRINT("dwStartType = %lu\n", dwStartType
);
1749 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1750 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1751 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1754 return ERROR_SHUTDOWN_IN_PROGRESS
;
1756 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1757 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1759 DPRINT1("Invalid manager handle!\n");
1760 return ERROR_INVALID_HANDLE
;
1763 /* Check access rights */
1764 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1765 SC_MANAGER_CREATE_SERVICE
))
1767 DPRINT1("Insufficient access rights! 0x%lx\n",
1768 hManager
->Handle
.DesiredAccess
);
1769 return ERROR_ACCESS_DENIED
;
1772 if (wcslen(lpServiceName
) == 0)
1774 return ERROR_INVALID_NAME
;
1777 if (wcslen(lpBinaryPathName
) == 0)
1779 return ERROR_INVALID_PARAMETER
;
1782 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1783 (lpServiceStartName
))
1785 return ERROR_INVALID_PARAMETER
;
1788 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1789 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1790 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1792 return ERROR_INVALID_PARAMETER
;
1795 if (dwStartType
> SERVICE_DISABLED
)
1797 return ERROR_INVALID_PARAMETER
;
1800 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1803 /* check if it is marked for deletion */
1804 if (lpService
->bDeleted
)
1805 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1806 /* Return Error exist */
1807 return ERROR_SERVICE_EXISTS
;
1810 if (lpDisplayName
!= NULL
&&
1811 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1812 return ERROR_DUPLICATE_SERVICE_NAME
;
1814 if (dwServiceType
& SERVICE_DRIVER
)
1816 dwError
= ScmCanonDriverImagePath(dwStartType
,
1819 if (dwError
!= ERROR_SUCCESS
)
1824 if (dwStartType
== SERVICE_BOOT_START
||
1825 dwStartType
== SERVICE_SYSTEM_START
)
1827 return ERROR_INVALID_PARAMETER
;
1831 /* Allocate a new service entry */
1832 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1834 if (dwError
!= ERROR_SUCCESS
)
1837 /* Fill the new service entry */
1838 lpService
->Status
.dwServiceType
= dwServiceType
;
1839 lpService
->dwStartType
= dwStartType
;
1840 lpService
->dwErrorControl
= dwErrorControl
;
1842 /* Fill the display name */
1843 if (lpDisplayName
!= NULL
&&
1844 *lpDisplayName
!= 0 &&
1845 wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1847 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1848 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1849 if (lpService
->lpDisplayName
== NULL
)
1851 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1854 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1857 /* Assign the service to a group */
1858 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1860 dwError
= ScmSetServiceGroup(lpService
,
1862 if (dwError
!= ERROR_SUCCESS
)
1866 /* Assign a new tag */
1867 if (lpdwTagId
!= NULL
)
1869 dwError
= ScmAssignNewTag(lpService
);
1870 if (dwError
!= ERROR_SUCCESS
)
1874 /* Write service data to the registry */
1875 /* Create the service key */
1876 dwError
= ScmCreateServiceKey(lpServiceName
,
1879 if (dwError
!= ERROR_SUCCESS
)
1882 /* Set the display name */
1883 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1885 RegSetValueExW(hServiceKey
,
1889 (LPBYTE
)lpDisplayName
,
1890 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1893 /* Set the service type */
1894 dwError
= RegSetValueExW(hServiceKey
,
1898 (LPBYTE
)&dwServiceType
,
1900 if (dwError
!= ERROR_SUCCESS
)
1903 /* Set the start value */
1904 dwError
= RegSetValueExW(hServiceKey
,
1908 (LPBYTE
)&dwStartType
,
1910 if (dwError
!= ERROR_SUCCESS
)
1913 /* Set the error control value */
1914 dwError
= RegSetValueExW(hServiceKey
,
1918 (LPBYTE
)&dwErrorControl
,
1920 if (dwError
!= ERROR_SUCCESS
)
1923 /* Set the image path */
1924 if (dwServiceType
& SERVICE_WIN32
)
1926 dwError
= RegSetValueExW(hServiceKey
,
1930 (LPBYTE
)lpBinaryPathName
,
1931 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1932 if (dwError
!= ERROR_SUCCESS
)
1935 else if (dwServiceType
& SERVICE_DRIVER
)
1937 dwError
= RegSetValueExW(hServiceKey
,
1941 (LPBYTE
)lpImagePath
,
1942 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1943 if (dwError
!= ERROR_SUCCESS
)
1947 /* Set the group name */
1948 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1950 dwError
= RegSetValueExW(hServiceKey
,
1954 (LPBYTE
)lpLoadOrderGroup
,
1955 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1956 if (dwError
!= ERROR_SUCCESS
)
1960 if (lpdwTagId
!= NULL
)
1962 dwError
= RegSetValueExW(hServiceKey
,
1966 (LPBYTE
)&lpService
->dwTag
,
1968 if (dwError
!= ERROR_SUCCESS
)
1972 /* Write dependencies */
1973 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1975 dwError
= ScmWriteDependencies(hServiceKey
,
1976 (LPWSTR
)lpDependencies
,
1978 if (dwError
!= ERROR_SUCCESS
)
1982 /* If a non driver and NULL for lpServiceName, write ObjectName as LocalSystem */
1983 if ((dwServiceType
& SERVICE_WIN32
) && (!lpServiceName
))
1985 dwError
= RegSetValueExW(hServiceKey
,
1989 (LPBYTE
)L
"LocalSystem",
1991 if (dwError
!= ERROR_SUCCESS
)
1995 if (lpPassword
!= NULL
)
1997 /* FIXME: Write password */
2000 dwError
= ScmCreateServiceHandle(lpService
,
2002 if (dwError
!= ERROR_SUCCESS
)
2005 dwError
= ScmCheckAccess(hServiceHandle
,
2007 if (dwError
!= ERROR_SUCCESS
)
2010 lpService
->dwRefCount
= 1;
2011 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2014 if (hServiceKey
!= NULL
)
2015 RegCloseKey(hServiceKey
);
2017 if (dwError
== ERROR_SUCCESS
)
2019 DPRINT("hService %p\n", hServiceHandle
);
2020 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2022 if (lpdwTagId
!= NULL
)
2023 *lpdwTagId
= lpService
->dwTag
;
2027 /* Release the display name buffer */
2028 if (lpService
->lpServiceName
!= NULL
)
2029 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2033 /* Remove the service handle */
2034 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2037 if (lpService
!= NULL
)
2039 /* FIXME: remove the service entry */
2043 if (lpImagePath
!= NULL
)
2044 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2046 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2053 DWORD
REnumDependentServicesW(
2054 handle_t BindingHandle
,
2055 SC_RPC_HANDLE hService
,
2056 DWORD dwServiceState
,
2059 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2060 LPBOUNDED_DWORD_256K lpServicesReturned
)
2062 DWORD dwError
= ERROR_SUCCESS
;
2063 DWORD dwServicesReturned
= 0;
2064 DWORD dwServiceCount
;
2065 HKEY hServicesKey
= NULL
;
2066 LPSC_RPC_HANDLE hSCObject
;
2067 PSERVICE_HANDLE hSvc
;
2068 PSERVICE lpService
= NULL
;
2069 PSERVICE
*lpServicesArray
= NULL
;
2070 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2073 *pcbBytesNeeded
= 0;
2074 *lpServicesReturned
= 0;
2076 DPRINT("REnumDependentServicesW() called\n");
2078 hSCObject
= &hService
;
2079 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
2080 lpService
= hSvc
->ServiceEntry
;
2082 /* Check access rights */
2083 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2084 SC_MANAGER_ENUMERATE_SERVICE
))
2086 DPRINT1("Insufficient access rights! 0x%lx\n",
2087 hSvc
->Handle
.DesiredAccess
);
2088 return ERROR_ACCESS_DENIED
;
2091 /* Open the Services Reg key */
2092 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2093 L
"System\\CurrentControlSet\\Services",
2097 if (dwError
!= ERROR_SUCCESS
)
2100 /* First determine the bytes needed and get the number of dependent services */
2101 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2106 &dwServicesReturned
);
2107 if (dwError
!= ERROR_SUCCESS
)
2110 /* If buffer size is less than the bytes needed or pointer is null */
2111 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2113 dwError
= ERROR_MORE_DATA
;
2117 /* Allocate memory for array of service pointers */
2118 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2120 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2121 if (!lpServicesArray
)
2123 DPRINT1("Could not allocate a buffer!!\n");
2124 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2128 dwServicesReturned
= 0;
2129 *pcbBytesNeeded
= 0;
2131 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2136 &dwServicesReturned
);
2137 if (dwError
!= ERROR_SUCCESS
)
2142 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2143 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2145 /* Copy EnumDepenedentService to Buffer */
2146 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2148 lpService
= lpServicesArray
[dwServiceCount
];
2150 /* Copy status info */
2151 memcpy(&lpServicesPtr
->ServiceStatus
,
2153 sizeof(SERVICE_STATUS
));
2155 /* Copy display name */
2156 wcscpy(lpStr
, lpService
->lpDisplayName
);
2157 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2158 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2160 /* Copy service name */
2161 wcscpy(lpStr
, lpService
->lpServiceName
);
2162 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2163 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2168 *lpServicesReturned
= dwServicesReturned
;
2171 if (lpServicesArray
!= NULL
)
2172 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2174 RegCloseKey(hServicesKey
);
2176 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2183 DWORD
REnumServicesStatusW(
2184 handle_t BindingHandle
,
2185 SC_RPC_HANDLE hSCManager
,
2186 DWORD dwServiceType
,
2187 DWORD dwServiceState
,
2190 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2191 LPBOUNDED_DWORD_256K lpServicesReturned
,
2192 LPBOUNDED_DWORD_256K lpResumeHandle
)
2194 PMANAGER_HANDLE hManager
;
2196 DWORD dwError
= ERROR_SUCCESS
;
2197 PLIST_ENTRY ServiceEntry
;
2198 PSERVICE CurrentService
;
2200 DWORD dwRequiredSize
;
2201 DWORD dwServiceCount
;
2203 DWORD dwLastResumeCount
;
2204 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2207 DPRINT("REnumServicesStatusW() called\n");
2210 return ERROR_SHUTDOWN_IN_PROGRESS
;
2212 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2213 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2215 DPRINT1("Invalid manager handle!\n");
2216 return ERROR_INVALID_HANDLE
;
2219 /* Check access rights */
2220 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2221 SC_MANAGER_ENUMERATE_SERVICE
))
2223 DPRINT1("Insufficient access rights! 0x%lx\n",
2224 hManager
->Handle
.DesiredAccess
);
2225 return ERROR_ACCESS_DENIED
;
2228 *pcbBytesNeeded
= 0;
2229 *lpServicesReturned
= 0;
2231 dwLastResumeCount
= *lpResumeHandle
;
2233 /* FIXME: Lock the service list shared */
2235 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2236 if (lpService
== NULL
)
2238 dwError
= ERROR_SUCCESS
;
2245 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2246 ServiceEntry
!= &ServiceListHead
;
2247 ServiceEntry
= ServiceEntry
->Flink
)
2249 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2253 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2256 dwState
= SERVICE_ACTIVE
;
2257 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2258 dwState
= SERVICE_INACTIVE
;
2260 if ((dwState
& dwServiceState
) == 0)
2263 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2264 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2265 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2267 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2269 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2273 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2274 dwRequiredSize
+= dwSize
;
2276 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2279 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2280 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2283 ServiceEntry
!= &ServiceListHead
;
2284 ServiceEntry
= ServiceEntry
->Flink
)
2286 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2290 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2293 dwState
= SERVICE_ACTIVE
;
2294 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2295 dwState
= SERVICE_INACTIVE
;
2297 if ((dwState
& dwServiceState
) == 0)
2300 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2301 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2302 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2304 dwError
= ERROR_MORE_DATA
;
2307 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2309 *lpResumeHandle
= dwLastResumeCount
;
2310 *lpServicesReturned
= dwServiceCount
;
2311 *pcbBytesNeeded
= dwRequiredSize
;
2313 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2314 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2315 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2318 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2319 ServiceEntry
!= &ServiceListHead
;
2320 ServiceEntry
= ServiceEntry
->Flink
)
2322 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2326 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2329 dwState
= SERVICE_ACTIVE
;
2330 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2331 dwState
= SERVICE_INACTIVE
;
2333 if ((dwState
& dwServiceState
) == 0)
2336 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2337 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2338 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2340 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2343 /* Copy the service name */
2344 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2345 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2346 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2348 /* Copy the display name */
2349 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2350 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2351 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2353 /* Copy the status information */
2354 memcpy(&lpStatusPtr
->ServiceStatus
,
2355 &CurrentService
->Status
,
2356 sizeof(SERVICE_STATUS
));
2359 dwRequiredSize
+= dwSize
;
2363 /* FIXME: Unlock the service list */
2365 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2372 DWORD
ROpenSCManagerW(
2373 handle_t BindingHandle
,
2374 LPWSTR lpMachineName
,
2375 LPWSTR lpDatabaseName
,
2376 DWORD dwDesiredAccess
,
2377 LPSC_RPC_HANDLE lpScHandle
)
2382 DPRINT("ROpenSCManagerW() called\n");
2383 DPRINT("lpMachineName = %p\n", lpMachineName
);
2384 DPRINT("lpMachineName: %S\n", lpMachineName
);
2385 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2386 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2387 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2390 return ERROR_SHUTDOWN_IN_PROGRESS
;
2393 return ERROR_INVALID_PARAMETER
;
2395 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2397 if (dwError
!= ERROR_SUCCESS
)
2399 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2403 /* Check the desired access */
2404 dwError
= ScmCheckAccess(hHandle
,
2405 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2406 if (dwError
!= ERROR_SUCCESS
)
2408 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2409 HeapFree(GetProcessHeap(), 0, hHandle
);
2413 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2414 DPRINT("*hScm = %p\n", *lpScHandle
);
2416 DPRINT("ROpenSCManagerW() done\n");
2418 return ERROR_SUCCESS
;
2423 DWORD
ROpenServiceW(
2424 handle_t BindingHandle
,
2425 SC_RPC_HANDLE hSCManager
,
2426 LPWSTR lpServiceName
,
2427 DWORD dwDesiredAccess
,
2428 LPSC_RPC_HANDLE lpServiceHandle
)
2431 PMANAGER_HANDLE hManager
;
2435 DPRINT("ROpenServiceW() called\n");
2436 DPRINT("hSCManager = %p\n", hSCManager
);
2437 DPRINT("lpServiceName = %p\n", lpServiceName
);
2438 DPRINT("lpServiceName: %S\n", lpServiceName
);
2439 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2442 return ERROR_SHUTDOWN_IN_PROGRESS
;
2444 if (!lpServiceHandle
)
2445 return ERROR_INVALID_PARAMETER
;
2448 return ERROR_INVALID_ADDRESS
;
2450 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2451 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2453 DPRINT1("Invalid manager handle!\n");
2454 return ERROR_INVALID_HANDLE
;
2457 /* FIXME: Lock the service list */
2459 /* Get service database entry */
2460 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2461 if (lpService
== NULL
)
2463 DPRINT("Could not find a service!\n");
2464 return ERROR_SERVICE_DOES_NOT_EXIST
;
2467 /* Create a service handle */
2468 dwError
= ScmCreateServiceHandle(lpService
,
2470 if (dwError
!= ERROR_SUCCESS
)
2472 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2476 /* Check the desired access */
2477 dwError
= ScmCheckAccess(hHandle
,
2479 if (dwError
!= ERROR_SUCCESS
)
2481 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2482 HeapFree(GetProcessHeap(), 0, hHandle
);
2486 lpService
->dwRefCount
++;
2487 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2489 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2490 DPRINT("*hService = %p\n", *lpServiceHandle
);
2492 DPRINT("ROpenServiceW() done\n");
2494 return ERROR_SUCCESS
;
2499 DWORD
RQueryServiceConfigW(
2500 handle_t BindingHandle
,
2501 SC_RPC_HANDLE hService
,
2502 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2504 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2506 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2507 DWORD dwError
= ERROR_SUCCESS
;
2508 PSERVICE_HANDLE hSvc
;
2509 PSERVICE lpService
= NULL
;
2510 HKEY hServiceKey
= NULL
;
2511 LPWSTR lpImagePath
= NULL
;
2512 LPWSTR lpServiceStartName
= NULL
;
2513 DWORD dwRequiredSize
;
2514 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2515 WCHAR lpEmptyString
[] = {0,0};
2518 DPRINT("RQueryServiceConfigW() called\n");
2521 return ERROR_SHUTDOWN_IN_PROGRESS
;
2523 hSvc
= (PSERVICE_HANDLE
)hService
;
2524 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2526 DPRINT1("Invalid handle tag!\n");
2527 return ERROR_INVALID_HANDLE
;
2530 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2531 SERVICE_QUERY_CONFIG
))
2533 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2534 return ERROR_ACCESS_DENIED
;
2537 lpService
= hSvc
->ServiceEntry
;
2538 if (lpService
== NULL
)
2540 DPRINT1("lpService == NULL!\n");
2541 return ERROR_INVALID_HANDLE
;
2544 /* FIXME: Lock the service database shared */
2546 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2549 if (dwError
!= ERROR_SUCCESS
)
2552 dwError
= ScmReadString(hServiceKey
,
2555 if (dwError
!= ERROR_SUCCESS
)
2558 ScmReadString(hServiceKey
,
2560 &lpServiceStartName
);
2562 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2564 if (lpImagePath
!= NULL
)
2565 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2567 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2569 if (lpService
->lpGroup
!= NULL
)
2570 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2572 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2574 /* FIXME: Add Dependencies length*/
2576 if (lpServiceStartName
!= NULL
)
2577 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2579 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2581 if (lpService
->lpDisplayName
!= NULL
)
2582 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2584 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2586 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2588 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2592 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2593 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2594 lpConfig
->dwStartType
= lpService
->dwStartType
;
2595 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2596 lpConfig
->dwTagId
= lpService
->dwTag
;
2598 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2600 if (lpImagePath
!= NULL
)
2602 wcscpy(lpStr
, lpImagePath
);
2606 wcscpy(lpStr
, lpEmptyString
);
2609 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2610 lpStr
+= (wcslen(lpStr
) + 1);
2612 if (lpService
->lpGroup
!= NULL
)
2614 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2618 wcscpy(lpStr
, lpEmptyString
);
2621 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2622 lpStr
+= (wcslen(lpStr
) + 1);
2624 /* FIXME: Append Dependencies */
2625 wcscpy(lpStr
, lpEmptyString
);
2627 lpStr
+= (wcslen(lpStr
) + 1);
2628 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2630 if (lpServiceStartName
!= NULL
)
2632 wcscpy(lpStr
, lpServiceStartName
);
2636 wcscpy(lpStr
, lpEmptyString
);
2639 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2640 lpStr
+= (wcslen(lpStr
) + 1);
2642 if (lpService
->lpDisplayName
!= NULL
)
2644 wcscpy(lpStr
, lpService
->lpDisplayName
);
2648 wcscpy(lpStr
, lpEmptyString
);
2651 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2654 if (pcbBytesNeeded
!= NULL
)
2655 *pcbBytesNeeded
= dwRequiredSize
;
2658 if (lpImagePath
!= NULL
)
2659 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2661 if (lpServiceStartName
!= NULL
)
2662 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2664 if (hServiceKey
!= NULL
)
2665 RegCloseKey(hServiceKey
);
2667 /* FIXME: Unlock the service database */
2669 DPRINT("RQueryServiceConfigW() done\n");
2676 DWORD
RQueryServiceLockStatusW(
2677 handle_t BindingHandle
,
2678 SC_RPC_HANDLE hSCManager
,
2679 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2681 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2684 return ERROR_CALL_NOT_IMPLEMENTED
;
2689 DWORD
RStartServiceW(
2690 handle_t BindingHandle
,
2691 SC_RPC_HANDLE hService
,
2693 LPSTRING_PTRSW argv
)
2695 DWORD dwError
= ERROR_SUCCESS
;
2696 PSERVICE_HANDLE hSvc
;
2697 PSERVICE lpService
= NULL
;
2699 DPRINT("RStartServiceW() called\n");
2702 return ERROR_SHUTDOWN_IN_PROGRESS
;
2704 hSvc
= (PSERVICE_HANDLE
)hService
;
2705 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2707 DPRINT1("Invalid handle tag!\n");
2708 return ERROR_INVALID_HANDLE
;
2711 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2714 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2715 return ERROR_ACCESS_DENIED
;
2718 lpService
= hSvc
->ServiceEntry
;
2719 if (lpService
== NULL
)
2721 DPRINT1("lpService == NULL!\n");
2722 return ERROR_INVALID_HANDLE
;
2725 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2726 return ERROR_SERVICE_DISABLED
;
2728 if (lpService
->bDeleted
)
2729 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2736 /* Start the service */
2737 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2744 DWORD
RGetServiceDisplayNameW(
2745 handle_t BindingHandle
,
2746 SC_RPC_HANDLE hSCManager
,
2747 LPWSTR lpServiceName
,
2748 LPWSTR lpDisplayName
,
2751 // PMANAGER_HANDLE hManager;
2756 DPRINT("RGetServiceDisplayNameW() called\n");
2757 DPRINT("hSCManager = %p\n", hSCManager
);
2758 DPRINT("lpServiceName: %S\n", lpServiceName
);
2759 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2760 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2762 // hManager = (PMANAGER_HANDLE)hSCManager;
2763 // if (hManager->Handle.Tag != MANAGER_TAG)
2765 // DPRINT1("Invalid manager handle!\n");
2766 // return ERROR_INVALID_HANDLE;
2769 /* Get service database entry */
2770 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2771 if (lpService
== NULL
)
2773 DPRINT1("Could not find a service!\n");
2775 /* If the service could not be found and lpcchBuffer is 0, windows
2776 puts null in lpDisplayName and puts 1 in lpcchBuffer */
2777 if (*lpcchBuffer
== 0)
2780 *lpDisplayName
= '\0';
2783 return ERROR_SERVICE_DOES_NOT_EXIST
;
2786 if (!lpService
->lpDisplayName
)
2788 dwLength
= wcslen(lpService
->lpServiceName
);
2790 if (lpServiceName
!= NULL
&&
2791 *lpcchBuffer
> dwLength
)
2793 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2798 dwLength
= wcslen(lpService
->lpDisplayName
);
2800 if (lpDisplayName
!= NULL
&&
2801 *lpcchBuffer
> dwLength
)
2803 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2807 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2809 *lpcchBuffer
= dwLength
;
2816 DWORD
RGetServiceKeyNameW(
2817 handle_t BindingHandle
,
2818 SC_RPC_HANDLE hSCManager
,
2819 LPWSTR lpDisplayName
,
2820 LPWSTR lpServiceName
,
2823 // PMANAGER_HANDLE hManager;
2828 DPRINT("RGetServiceKeyNameW() called\n");
2829 DPRINT("hSCManager = %p\n", hSCManager
);
2830 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2831 DPRINT("lpServiceName: %p\n", lpServiceName
);
2832 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2834 // hManager = (PMANAGER_HANDLE)hSCManager;
2835 // if (hManager->Handle.Tag != MANAGER_TAG)
2837 // DPRINT1("Invalid manager handle!\n");
2838 // return ERROR_INVALID_HANDLE;
2841 /* Get service database entry */
2842 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2843 if (lpService
== NULL
)
2845 DPRINT1("Could not find a service!\n");
2847 /* If the service could not be found and lpcchBuffer is 0, windows
2848 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2849 if (*lpcchBuffer
== 0)
2852 *lpServiceName
= '\0';
2855 return ERROR_SERVICE_DOES_NOT_EXIST
;
2858 dwLength
= wcslen(lpService
->lpServiceName
);
2860 if (lpServiceName
!= NULL
&&
2861 *lpcchBuffer
> dwLength
)
2863 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2864 *lpcchBuffer
= dwLength
;
2865 return ERROR_SUCCESS
;
2868 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2870 *lpcchBuffer
= dwLength
* 2;
2877 DWORD
RI_ScSetServiceBitsA(
2878 handle_t BindingHandle
,
2879 SC_RPC_HANDLE hServiceStatus
,
2880 DWORD dwServiceBits
,
2882 int bUpdateImmediately
,
2886 return ERROR_CALL_NOT_IMPLEMENTED
;
2891 DWORD
RChangeServiceConfigA(
2892 handle_t BindingHandle
,
2893 SC_RPC_HANDLE hService
,
2894 DWORD dwServiceType
,
2896 DWORD dwErrorControl
,
2897 LPSTR lpBinaryPathName
,
2898 LPSTR lpLoadOrderGroup
,
2900 LPSTR lpDependencies
,
2902 LPSTR lpServiceStartName
,
2905 LPSTR lpDisplayName
)
2907 DWORD dwError
= ERROR_SUCCESS
;
2908 PSERVICE_HANDLE hSvc
;
2909 PSERVICE lpService
= NULL
;
2910 HKEY hServiceKey
= NULL
;
2911 LPWSTR lpDisplayNameW
= NULL
;
2912 // LPWSTR lpBinaryPathNameW = NULL;
2913 LPWSTR lpLoadOrderGroupW
= NULL
;
2914 LPWSTR lpDependenciesW
= NULL
;
2915 // LPWSTR lpPasswordW = NULL;
2917 DPRINT("RChangeServiceConfigA() called\n");
2918 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2919 DPRINT("dwStartType = %lu\n", dwStartType
);
2920 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2921 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2922 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2923 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2926 return ERROR_SHUTDOWN_IN_PROGRESS
;
2928 hSvc
= (PSERVICE_HANDLE
)hService
;
2929 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2931 DPRINT1("Invalid handle tag!\n");
2932 return ERROR_INVALID_HANDLE
;
2935 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2936 SERVICE_CHANGE_CONFIG
))
2938 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2939 return ERROR_ACCESS_DENIED
;
2942 lpService
= hSvc
->ServiceEntry
;
2943 if (lpService
== NULL
)
2945 DPRINT1("lpService == NULL!\n");
2946 return ERROR_INVALID_HANDLE
;
2949 /* FIXME: Lock database exclusively */
2951 if (lpService
->bDeleted
)
2953 /* FIXME: Unlock database */
2954 DPRINT1("The service has already been marked for delete!\n");
2955 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2958 /* Open the service key */
2959 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2962 if (dwError
!= ERROR_SUCCESS
)
2965 /* Write service data to the registry */
2967 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2969 /* Set the display name */
2970 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2972 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2973 if (lpDisplayNameW
== NULL
)
2975 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2979 MultiByteToWideChar(CP_ACP
,
2984 wcslen(lpDisplayNameW
) + 1);
2986 RegSetValueExW(hServiceKey
,
2990 (LPBYTE
)lpDisplayNameW
,
2991 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2993 /* Update lpService->lpDisplayName */
2994 if (lpService
->lpDisplayName
)
2995 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2997 lpService
->lpDisplayName
= lpDisplayNameW
;
3000 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3002 /* Set the service type */
3003 dwError
= RegSetValueExW(hServiceKey
,
3007 (LPBYTE
)&dwServiceType
,
3009 if (dwError
!= ERROR_SUCCESS
)
3012 lpService
->Status
.dwServiceType
= dwServiceType
;
3015 if (dwStartType
!= SERVICE_NO_CHANGE
)
3017 /* Set the start value */
3018 dwError
= RegSetValueExW(hServiceKey
,
3022 (LPBYTE
)&dwStartType
,
3024 if (dwError
!= ERROR_SUCCESS
)
3027 lpService
->dwStartType
= dwStartType
;
3030 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3032 /* Set the error control value */
3033 dwError
= RegSetValueExW(hServiceKey
,
3037 (LPBYTE
)&dwErrorControl
,
3039 if (dwError
!= ERROR_SUCCESS
)
3042 lpService
->dwErrorControl
= dwErrorControl
;
3046 /* FIXME: set the new ImagePath value */
3048 /* Set the image path */
3049 if (dwServiceType
& SERVICE_WIN32
)
3051 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3053 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3054 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, wcslen(lpBinaryPathNameW
)+1);
3055 dwError
= RegSetValueExW(hServiceKey
,
3059 (LPBYTE
)lpBinaryPathNameW
,
3060 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3061 if (dwError
!= ERROR_SUCCESS
)
3065 else if (dwServiceType
& SERVICE_DRIVER
)
3067 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3069 dwError
= RegSetValueExW(hServiceKey
,
3073 (LPBYTE
)lpImagePath
,
3074 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3075 if (dwError
!= ERROR_SUCCESS
)
3081 /* Set the group name */
3082 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3084 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3086 (strlen(lpLoadOrderGroup
)+1) * sizeof(WCHAR
));
3087 if (lpLoadOrderGroupW
== NULL
)
3089 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3093 MultiByteToWideChar(CP_ACP
,
3098 wcslen(lpLoadOrderGroupW
) + 1);
3100 dwError
= RegSetValueExW(hServiceKey
,
3104 (LPBYTE
)lpLoadOrderGroupW
,
3105 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3106 if (dwError
!= ERROR_SUCCESS
)
3109 /* FIXME: Update lpService->lpServiceGroup */
3111 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3114 if (lpdwTagId
!= NULL
)
3116 dwError
= ScmAssignNewTag(lpService
);
3117 if (dwError
!= ERROR_SUCCESS
)
3120 dwError
= RegSetValueExW(hServiceKey
,
3124 (LPBYTE
)&lpService
->dwTag
,
3126 if (dwError
!= ERROR_SUCCESS
)
3129 *lpdwTagId
= lpService
->dwTag
;
3132 /* Write dependencies */
3133 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3135 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3137 (strlen(lpDependencies
)+1) * sizeof(WCHAR
));
3138 if (lpDependenciesW
== NULL
)
3140 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3144 MultiByteToWideChar(CP_ACP
,
3149 wcslen(lpDependenciesW
)+1);
3151 dwError
= ScmWriteDependencies(hServiceKey
,
3152 (LPWSTR
)lpDependenciesW
,
3155 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3158 if (lpPassword
!= NULL
)
3160 /* FIXME: Write password */
3163 /* FIXME: Unlock database */
3166 if (hServiceKey
!= NULL
)
3167 RegCloseKey(hServiceKey
);
3169 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3176 DWORD
RCreateServiceA(
3177 handle_t BindingHandle
,
3178 SC_RPC_HANDLE hSCManager
,
3179 LPSTR lpServiceName
,
3180 LPSTR lpDisplayName
,
3181 DWORD dwDesiredAccess
,
3182 DWORD dwServiceType
,
3184 DWORD dwErrorControl
,
3185 LPSTR lpBinaryPathName
,
3186 LPSTR lpLoadOrderGroup
,
3188 LPBYTE lpDependencies
,
3190 LPSTR lpServiceStartName
,
3193 LPSC_RPC_HANDLE lpServiceHandle
)
3196 return ERROR_CALL_NOT_IMPLEMENTED
;
3201 DWORD
REnumDependentServicesA(
3202 handle_t BindingHandle
,
3203 SC_RPC_HANDLE hService
,
3204 DWORD dwServiceState
,
3207 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3208 LPBOUNDED_DWORD_256K lpServicesReturned
)
3210 DWORD dwError
= ERROR_SUCCESS
;
3211 DWORD dwServicesReturned
= 0;
3212 DWORD dwServiceCount
;
3213 HKEY hServicesKey
= NULL
;
3214 LPSC_RPC_HANDLE hSCObject
;
3215 PSERVICE_HANDLE hSvc
;
3216 PSERVICE lpService
= NULL
;
3217 PSERVICE
*lpServicesArray
= NULL
;
3218 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3221 *pcbBytesNeeded
= 0;
3222 *lpServicesReturned
= 0;
3224 DPRINT("REnumDependentServicesA() called\n");
3226 hSCObject
= &hService
;
3227 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3228 lpService
= hSvc
->ServiceEntry
;
3230 /* Check access rights */
3231 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3232 SC_MANAGER_ENUMERATE_SERVICE
))
3234 DPRINT1("Insufficient access rights! 0x%lx\n",
3235 hSvc
->Handle
.DesiredAccess
);
3236 return ERROR_ACCESS_DENIED
;
3239 /* Open the Services Reg key */
3240 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3241 L
"System\\CurrentControlSet\\Services",
3246 if (dwError
!= ERROR_SUCCESS
) return dwError
;
3248 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3249 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3250 are the same for both. Verified in WINXP. */
3252 /* First determine the bytes needed and get the number of dependent services*/
3253 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3258 &dwServicesReturned
);
3259 if (dwError
!= ERROR_SUCCESS
)
3262 /* If buffer size is less than the bytes needed or pointer is null*/
3263 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))