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 LPSC_RPC_HANDLE hSCObject
)
405 PMANAGER_HANDLE hManager
;
406 PSERVICE_HANDLE hService
;
410 DWORD pcbBytesNeeded
= 0;
411 DWORD dwServicesReturned
= 0;
413 DPRINT("RCloseServiceHandle() called\n");
415 DPRINT("hSCObject = %p\n", *hSCObject
);
418 return ERROR_INVALID_HANDLE
;
420 hManager
= (PMANAGER_HANDLE
)*hSCObject
;
421 hService
= (PSERVICE_HANDLE
)*hSCObject
;
422 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
424 DPRINT("Found manager handle\n");
426 hManager
->Handle
.RefCount
--;
427 if (hManager
->Handle
.RefCount
== 0)
429 /* FIXME: add handle cleanup code */
431 HeapFree(GetProcessHeap(), 0, hManager
);
435 DPRINT("RCloseServiceHandle() done\n");
436 return ERROR_SUCCESS
;
438 else if (hService
->Handle
.Tag
== SERVICE_TAG
)
440 DPRINT("Found service handle\n");
442 /* Get the pointer to the service record */
443 lpService
= hService
->ServiceEntry
;
445 ASSERT(hService
->Handle
.RefCount
> 0);
447 hService
->Handle
.RefCount
--;
448 if (hService
->Handle
.RefCount
== 0)
450 /* FIXME: add handle cleanup code */
452 /* Free the handle */
453 HeapFree(GetProcessHeap(), 0, hService
);
457 ASSERT(lpService
->dwRefCount
> 0);
459 lpService
->dwRefCount
--;
460 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
461 lpService
->dwRefCount
);
463 if (lpService
->dwRefCount
== 0)
465 /* If this service has been marked for deletion */
466 if (lpService
->bDeleted
)
468 /* Open the Services Reg key */
469 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
470 L
"System\\CurrentControlSet\\Services",
472 KEY_SET_VALUE
| KEY_READ
,
474 if (dwError
!= ERROR_SUCCESS
)
476 DPRINT1("Failed to open services key\n");
480 /* Call the internal function with NULL, just to get bytes we need */
481 Int_EnumDependentServicesW(hServicesKey
,
486 &dwServicesReturned
);
488 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
491 DPRINT1("Deletion failed due to running dependencies.\n");
492 RegCloseKey(hServicesKey
);
493 return ERROR_SUCCESS
;
496 /* There are no references and no runnning dependencies,
497 it is now safe to delete the service */
499 /* Delete the Service Key */
500 dwError
= RegDeleteKey(hServicesKey
,
501 lpService
->lpServiceName
);
503 RegCloseKey(hServicesKey
);
505 if (dwError
!= ERROR_SUCCESS
)
507 DPRINT1("Failed to Delete the Service Registry key\n");
511 /* Delete the Service */
512 ScmDeleteServiceRecord(lpService
);
516 DPRINT("RCloseServiceHandle() done\n");
517 return ERROR_SUCCESS
;
520 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
522 return ERROR_INVALID_HANDLE
;
527 DWORD
RControlService(
528 SC_RPC_HANDLE hService
,
530 LPSERVICE_STATUS lpServiceStatus
)
532 PSERVICE_HANDLE hSvc
;
534 ACCESS_MASK DesiredAccess
;
535 DWORD dwError
= ERROR_SUCCESS
;
536 DWORD pcbBytesNeeded
= 0;
537 DWORD dwServicesReturned
= 0;
538 HKEY hServicesKey
= NULL
;
540 DPRINT("RControlService() called\n");
543 return ERROR_SHUTDOWN_IN_PROGRESS
;
545 /* Check the service handle */
546 hSvc
= (PSERVICE_HANDLE
)hService
;
547 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
549 DPRINT1("Invalid handle tag!\n");
550 return ERROR_INVALID_HANDLE
;
553 /* Check the service entry point */
554 lpService
= hSvc
->ServiceEntry
;
555 if (lpService
== NULL
)
557 DPRINT1("lpService == NULL!\n");
558 return ERROR_INVALID_HANDLE
;
561 /* Check access rights */
564 case SERVICE_CONTROL_STOP
:
565 DesiredAccess
= SERVICE_STOP
;
568 case SERVICE_CONTROL_PAUSE
:
569 case SERVICE_CONTROL_CONTINUE
:
570 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
573 case SERVICE_INTERROGATE
:
574 DesiredAccess
= SERVICE_INTERROGATE
;
578 if (dwControl
>= 128 && dwControl
<= 255)
579 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
581 DesiredAccess
= SERVICE_QUERY_CONFIG
|
582 SERVICE_CHANGE_CONFIG
|
583 SERVICE_QUERY_STATUS
|
585 SERVICE_PAUSE_CONTINUE
;
589 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
591 return ERROR_ACCESS_DENIED
;
593 if (dwControl
== SERVICE_CONTROL_STOP
)
595 /* Check if the service has dependencies running as windows
596 doesn't stop a service that does */
598 /* Open the Services Reg key */
599 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
600 L
"System\\CurrentControlSet\\Services",
604 if (dwError
!= ERROR_SUCCESS
)
606 DPRINT1("Failed to open services key\n");
610 /* Call the internal function with NULL, just to get bytes we need */
611 Int_EnumDependentServicesW(hServicesKey
,
616 &dwServicesReturned
);
618 RegCloseKey(hServicesKey
);
620 /* If pcbBytesNeeded is not zero then there are services running that
621 are dependent on this service */
622 if (pcbBytesNeeded
!= 0)
624 DPRINT("Service has running dependencies. Failed to stop service.\n");
625 return ERROR_DEPENDENT_SERVICES_RUNNING
;
629 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
631 /* Send control code to the driver */
632 dwError
= ScmControlDriver(lpService
,
638 /* Send control code to the service */
639 dwError
= ScmControlService(lpService
,
644 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
645 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
647 /* Return service status information */
648 RtlCopyMemory(lpServiceStatus
,
650 sizeof(SERVICE_STATUS
));
657 DWORD
RDeleteService(
658 SC_RPC_HANDLE hService
)
660 PSERVICE_HANDLE hSvc
;
664 DPRINT("RDeleteService() called\n");
667 return ERROR_SHUTDOWN_IN_PROGRESS
;
669 hSvc
= (PSERVICE_HANDLE
)hService
;
670 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
671 return ERROR_INVALID_HANDLE
;
673 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
675 return ERROR_ACCESS_DENIED
;
677 lpService
= hSvc
->ServiceEntry
;
678 if (lpService
== NULL
)
680 DPRINT1("lpService == NULL!\n");
681 return ERROR_INVALID_HANDLE
;
684 /* FIXME: Acquire service database lock exclusively */
686 if (lpService
->bDeleted
)
688 DPRINT1("The service has already been marked for delete!\n");
689 return ERROR_SERVICE_MARKED_FOR_DELETE
;
692 /* Mark service for delete */
693 lpService
->bDeleted
= TRUE
;
695 dwError
= ScmMarkServiceForDelete(lpService
);
697 /* FIXME: Release service database lock */
699 DPRINT("RDeleteService() done\n");
706 DWORD
RLockServiceDatabase(
707 SC_RPC_HANDLE hSCManager
,
708 LPSC_RPC_LOCK lpLock
)
710 PMANAGER_HANDLE hMgr
;
712 DPRINT("RLockServiceDatabase() called\n");
716 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
717 if (!hMgr
|| hMgr
->Handle
.Tag
!= MANAGER_TAG
)
718 return ERROR_INVALID_HANDLE
;
720 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
722 return ERROR_ACCESS_DENIED
;
724 // return ScmLockDatabase(0, hMgr->0xC, hLock);
726 /* FIXME: Lock the database */
727 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
729 return ERROR_SUCCESS
;
734 DWORD
RQueryServiceObjectSecurity(
735 SC_RPC_HANDLE hService
,
736 SECURITY_INFORMATION dwSecurityInformation
,
737 LPBYTE lpSecurityDescriptor
,
739 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
742 PSERVICE_HANDLE hSvc
;
744 ULONG DesiredAccess
= 0;
749 DPRINT("RQueryServiceObjectSecurity() called\n");
751 hSvc
= (PSERVICE_HANDLE
)hService
;
752 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
754 DPRINT1("Invalid handle tag!\n");
755 return ERROR_INVALID_HANDLE
;
758 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
759 GROUP_SECURITY_INFORMATION
||
760 OWNER_SECURITY_INFORMATION
))
761 DesiredAccess
|= READ_CONTROL
;
763 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
764 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
766 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
769 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
770 return ERROR_ACCESS_DENIED
;
773 lpService
= hSvc
->ServiceEntry
;
774 if (lpService
== NULL
)
776 DPRINT1("lpService == NULL!\n");
777 return ERROR_INVALID_HANDLE
;
780 /* FIXME: Lock the service list */
782 Status
= RtlQuerySecurityObject(lpService
->lpSecurityDescriptor
,
783 dwSecurityInformation
,
784 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
785 dwSecuityDescriptorSize
,
788 /* FIXME: Unlock the service list */
790 if (NT_SUCCESS(Status
))
792 *pcbBytesNeeded
= dwBytesNeeded
;
793 dwError
= STATUS_SUCCESS
;
795 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
797 *pcbBytesNeeded
= dwBytesNeeded
;
798 dwError
= ERROR_INSUFFICIENT_BUFFER
;
800 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
802 dwError
= ERROR_GEN_FAILURE
;
806 dwError
= RtlNtStatusToDosError(Status
);
812 return ERROR_CALL_NOT_IMPLEMENTED
;
817 DWORD
RSetServiceObjectSecurity(
818 SC_RPC_HANDLE hService
,
819 DWORD dwSecurityInformation
,
820 LPBYTE lpSecurityDescriptor
,
821 DWORD dwSecuityDescriptorSize
)
823 PSERVICE_HANDLE hSvc
;
825 ULONG DesiredAccess
= 0;
826 HANDLE hToken
= NULL
;
831 DPRINT1("RSetServiceObjectSecurity() called\n");
833 hSvc
= (PSERVICE_HANDLE
)hService
;
834 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
836 DPRINT1("Invalid handle tag!\n");
837 return ERROR_INVALID_HANDLE
;
840 if (dwSecurityInformation
== 0 ||
841 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
842 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
843 return ERROR_INVALID_PARAMETER
;
845 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
846 return ERROR_INVALID_PARAMETER
;
848 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
849 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
851 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
852 DesiredAccess
|= WRITE_DAC
;
854 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
855 DesiredAccess
|= WRITE_OWNER
;
857 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
858 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
859 return ERROR_INVALID_PARAMETER
;
861 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
862 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
863 return ERROR_INVALID_PARAMETER
;
865 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
868 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
869 return ERROR_ACCESS_DENIED
;
872 lpService
= hSvc
->ServiceEntry
;
873 if (lpService
== NULL
)
875 DPRINT1("lpService == NULL!\n");
876 return ERROR_INVALID_HANDLE
;
879 if (lpService
->bDeleted
)
880 return ERROR_SERVICE_MARKED_FOR_DELETE
;
882 RpcImpersonateClient(NULL
);
884 Status
= NtOpenThreadToken(NtCurrentThread(),
888 if (!NT_SUCCESS(Status
))
889 return RtlNtStatusToDosError(Status
);
893 /* FIXME: Lock service database */
896 Status
= RtlSetSecurityObject(dwSecurityInformation
,
897 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
898 &lpService
->lpSecurityDescriptor
,
901 if (!NT_SUCCESS(Status
))
903 dwError
= RtlNtStatusToDosError(Status
);
908 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
909 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
911 if (dwError
!= ERROR_SUCCESS
)
915 dwError
= ERROR_SUCCESS
;
916 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
917 // lpService->lpSecurityDescriptor);
919 RegFlushKey(hServiceKey
);
920 RegCloseKey(hServiceKey
);
927 /* FIXME: Unlock service database */
929 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
936 DWORD
RQueryServiceStatus(
937 SC_RPC_HANDLE hService
,
938 LPSERVICE_STATUS lpServiceStatus
)
940 PSERVICE_HANDLE hSvc
;
943 DPRINT("RQueryServiceStatus() called\n");
946 return ERROR_SHUTDOWN_IN_PROGRESS
;
948 hSvc
= (PSERVICE_HANDLE
)hService
;
949 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
951 DPRINT1("Invalid handle tag!\n");
952 return ERROR_INVALID_HANDLE
;
955 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
956 SERVICE_QUERY_STATUS
))
958 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
959 return ERROR_ACCESS_DENIED
;
962 lpService
= hSvc
->ServiceEntry
;
963 if (lpService
== NULL
)
965 DPRINT1("lpService == NULL!\n");
966 return ERROR_INVALID_HANDLE
;
969 /* Return service status information */
970 RtlCopyMemory(lpServiceStatus
,
972 sizeof(SERVICE_STATUS
));
974 return ERROR_SUCCESS
;
979 ScmIsValidServiceState(DWORD dwCurrentState
)
981 switch (dwCurrentState
)
983 case SERVICE_STOPPED
:
984 case SERVICE_START_PENDING
:
985 case SERVICE_STOP_PENDING
:
986 case SERVICE_RUNNING
:
987 case SERVICE_CONTINUE_PENDING
:
988 case SERVICE_PAUSE_PENDING
:
999 DWORD
RSetServiceStatus(
1000 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1001 LPSERVICE_STATUS lpServiceStatus
)
1005 DPRINT("RSetServiceStatus() called\n");
1006 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1007 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1008 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1009 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1010 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1011 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1012 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1013 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1015 if (hServiceStatus
== 0)
1017 DPRINT1("hServiceStatus == NULL!\n");
1018 return ERROR_INVALID_HANDLE
;
1021 lpService
= ScmGetServiceEntryByClientHandle(hServiceStatus
);
1022 if (lpService
== NULL
)
1024 DPRINT1("lpService == NULL!\n");
1025 return ERROR_INVALID_HANDLE
;
1028 /* Check current state */
1029 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1031 DPRINT1("Invalid service state!\n");
1032 return ERROR_INVALID_DATA
;
1035 /* Check service type */
1036 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1037 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1039 DPRINT1("Invalid service type!\n");
1040 return ERROR_INVALID_DATA
;
1043 /* Check accepted controls */
1044 if (lpServiceStatus
->dwControlsAccepted
== 0 ||
1045 lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1047 DPRINT1("Invalid controls accepted!\n");
1048 return ERROR_INVALID_DATA
;
1052 RtlCopyMemory(&lpService
->Status
,
1054 sizeof(SERVICE_STATUS
));
1056 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1057 DPRINT("RSetServiceStatus() done\n");
1059 return ERROR_SUCCESS
;
1064 DWORD
RUnlockServiceDatabase(
1068 return ERROR_SUCCESS
;
1073 DWORD
RNotifyBootConfigStatus(
1074 SVCCTL_HANDLEW lpMachineName
,
1075 DWORD BootAcceptable
)
1078 return ERROR_CALL_NOT_IMPLEMENTED
;
1083 DWORD
RI_ScSetServiceBitsW(
1084 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1085 DWORD dwServiceBits
,
1087 int bUpdateImmediately
,
1091 return ERROR_CALL_NOT_IMPLEMENTED
;
1096 DWORD
RChangeServiceConfigW(
1097 SC_RPC_HANDLE hService
,
1098 DWORD dwServiceType
,
1100 DWORD dwErrorControl
,
1101 LPWSTR lpBinaryPathName
,
1102 LPWSTR lpLoadOrderGroup
,
1104 LPBYTE lpDependencies
,
1106 LPWSTR lpServiceStartName
,
1109 LPWSTR lpDisplayName
)
1111 DWORD dwError
= ERROR_SUCCESS
;
1112 PSERVICE_HANDLE hSvc
;
1113 PSERVICE lpService
= NULL
;
1114 HKEY hServiceKey
= NULL
;
1115 LPWSTR lpDisplayNameW
= NULL
;
1117 DPRINT("RChangeServiceConfigW() called\n");
1118 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1119 DPRINT("dwStartType = %lu\n", dwStartType
);
1120 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1121 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1122 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1123 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1126 return ERROR_SHUTDOWN_IN_PROGRESS
;
1128 hSvc
= (PSERVICE_HANDLE
)hService
;
1129 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1131 DPRINT1("Invalid handle tag!\n");
1132 return ERROR_INVALID_HANDLE
;
1135 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1136 SERVICE_CHANGE_CONFIG
))
1138 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1139 return ERROR_ACCESS_DENIED
;
1142 lpService
= hSvc
->ServiceEntry
;
1143 if (lpService
== NULL
)
1145 DPRINT1("lpService == NULL!\n");
1146 return ERROR_INVALID_HANDLE
;
1149 /* FIXME: Lock database exclusively */
1151 if (lpService
->bDeleted
)
1153 /* FIXME: Unlock database */
1154 DPRINT1("The service has already been marked for delete!\n");
1155 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1158 /* Open the service key */
1159 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1162 if (dwError
!= ERROR_SUCCESS
)
1165 /* Write service data to the registry */
1166 /* Set the display name */
1167 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1169 RegSetValueExW(hServiceKey
,
1173 (LPBYTE
)lpDisplayName
,
1174 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1176 /* Update the display name */
1177 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1179 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1180 if (lpDisplayNameW
== NULL
)
1182 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1186 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1187 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1189 lpService
->lpDisplayName
= lpDisplayNameW
;
1192 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1194 /* Set the service type */
1195 dwError
= RegSetValueExW(hServiceKey
,
1199 (LPBYTE
)&dwServiceType
,
1201 if (dwError
!= ERROR_SUCCESS
)
1204 lpService
->Status
.dwServiceType
= dwServiceType
;
1207 if (dwStartType
!= SERVICE_NO_CHANGE
)
1209 /* Set the start value */
1210 dwError
= RegSetValueExW(hServiceKey
,
1214 (LPBYTE
)&dwStartType
,
1216 if (dwError
!= ERROR_SUCCESS
)
1219 lpService
->dwStartType
= dwStartType
;
1222 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1224 /* Set the error control value */
1225 dwError
= RegSetValueExW(hServiceKey
,
1229 (LPBYTE
)&dwErrorControl
,
1231 if (dwError
!= ERROR_SUCCESS
)
1234 lpService
->dwErrorControl
= dwErrorControl
;
1238 /* FIXME: set the new ImagePath value */
1240 /* Set the image path */
1241 if (dwServiceType
& SERVICE_WIN32
)
1243 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1245 dwError
= RegSetValueExW(hServiceKey
,
1249 (LPBYTE
)lpBinaryPathName
,
1250 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1251 if (dwError
!= ERROR_SUCCESS
)
1255 else if (dwServiceType
& SERVICE_DRIVER
)
1257 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1259 dwError
= RegSetValueExW(hServiceKey
,
1263 (LPBYTE
)lpImagePath
,
1264 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1265 if (dwError
!= ERROR_SUCCESS
)
1271 /* Set the group name */
1272 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1274 dwError
= RegSetValueExW(hServiceKey
,
1278 (LPBYTE
)lpLoadOrderGroup
,
1279 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1280 if (dwError
!= ERROR_SUCCESS
)
1282 /* FIXME: Update lpService->lpServiceGroup */
1285 if (lpdwTagId
!= NULL
)
1287 dwError
= ScmAssignNewTag(lpService
);
1288 if (dwError
!= ERROR_SUCCESS
)
1291 dwError
= RegSetValueExW(hServiceKey
,
1295 (LPBYTE
)&lpService
->dwTag
,
1297 if (dwError
!= ERROR_SUCCESS
)
1300 *lpdwTagId
= lpService
->dwTag
;
1303 /* Write dependencies */
1304 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1306 dwError
= ScmWriteDependencies(hServiceKey
,
1307 (LPWSTR
)lpDependencies
,
1309 if (dwError
!= ERROR_SUCCESS
)
1313 if (lpPassword
!= NULL
)
1315 /* FIXME: Write password */
1318 /* FIXME: Unlock database */
1321 if (hServiceKey
!= NULL
)
1322 RegCloseKey(hServiceKey
);
1324 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1330 /* Create a path suitable for the bootloader out of the full path */
1332 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1334 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1337 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1338 OBJECT_ATTRIBUTES ObjectAttributes
;
1340 HANDLE SymbolicLinkHandle
;
1342 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1344 ServiceNameLen
= wcslen(CanonName
);
1346 /* First check, if it's already good */
1347 if (ServiceNameLen
> 12 &&
1348 !wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1350 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1351 if (*RelativeName
== NULL
)
1353 DPRINT1("Error allocating memory for boot driver name!\n");
1354 return ERROR_NOT_ENOUGH_MEMORY
;
1358 wcscpy(*RelativeName
, CanonName
);
1360 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1361 return ERROR_SUCCESS
;
1364 /* If it has %SystemRoot% prefix, substitute it to \System*/
1365 if (ServiceNameLen
> 13 &&
1366 !wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1368 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1369 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1371 if (*RelativeName
== NULL
)
1373 DPRINT1("Error allocating memory for boot driver name!\n");
1374 return ERROR_NOT_ENOUGH_MEMORY
;
1378 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1379 wcscat(*RelativeName
, CanonName
+ 13);
1381 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1382 return ERROR_SUCCESS
;
1385 /* Get buffer size needed for expanding env strings */
1386 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1388 if (BufferSize
<= 1)
1390 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1391 return ERROR_INVALID_ENVIRONMENT
;
1394 /* Allocate memory, since the size is known now */
1395 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1398 DPRINT1("Error allocating memory for boot driver name!\n");
1399 return ERROR_NOT_ENOUGH_MEMORY
;
1403 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1406 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1407 LocalFree(Expanded
);
1408 return ERROR_NOT_ENOUGH_MEMORY
;
1411 /* Convert to NY-style path */
1412 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1414 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1415 return ERROR_INVALID_ENVIRONMENT
;
1418 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1420 /* No need to keep the dos-path anymore */
1421 LocalFree(Expanded
);
1423 /* Copy it to the allocated place */
1424 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1427 DPRINT1("Error allocating memory for boot driver name!\n");
1428 return ERROR_NOT_ENOUGH_MEMORY
;
1431 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1432 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1433 Expanded
[ExpandedLen
] = 0;
1435 if (ServiceNameLen
> ExpandedLen
&&
1436 !wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1438 /* Only \SystemRoot\ is missing */
1439 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1440 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1441 if (*RelativeName
== NULL
)
1443 DPRINT1("Error allocating memory for boot driver name!\n");
1444 LocalFree(Expanded
);
1445 return ERROR_NOT_ENOUGH_MEMORY
;
1448 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1449 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1451 RtlFreeUnicodeString(&NtPathName
);
1452 return ERROR_SUCCESS
;
1455 /* The most complex case starts here */
1456 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1457 InitializeObjectAttributes(&ObjectAttributes
,
1459 OBJ_CASE_INSENSITIVE
,
1463 /* Open this symlink */
1464 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1466 if (NT_SUCCESS(Status
))
1468 LinkTarget
.Length
= 0;
1469 LinkTarget
.MaximumLength
= 0;
1471 DPRINT("Opened symbolic link object\n");
1473 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1474 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1476 /* Check if required buffer size is sane */
1477 if (BufferSize
> 0xFFFD)
1479 DPRINT1("Too large buffer required\n");
1482 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1483 LocalFree(Expanded
);
1484 return ERROR_NOT_ENOUGH_MEMORY
;
1487 /* Alloc the string */
1488 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1489 if (!LinkTarget
.Buffer
)
1491 DPRINT1("Unable to alloc buffer\n");
1492 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1493 LocalFree(Expanded
);
1494 return ERROR_NOT_ENOUGH_MEMORY
;
1497 /* Do a real query now */
1498 LinkTarget
.Length
= BufferSize
;
1499 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1501 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1502 if (NT_SUCCESS(Status
))
1504 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1506 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1507 if ((ServiceNameLen
> ExpandedLen
) &&
1508 !wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1510 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1511 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1513 if (*RelativeName
== NULL
)
1515 DPRINT1("Unable to alloc buffer\n");
1516 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1517 LocalFree(Expanded
);
1518 RtlFreeUnicodeString(&NtPathName
);
1519 return ERROR_NOT_ENOUGH_MEMORY
;
1522 /* Copy it over, substituting the first part
1524 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1525 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1528 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1529 LocalFree(Expanded
);
1530 RtlFreeUnicodeString(&NtPathName
);
1532 /* Return success */
1533 return ERROR_SUCCESS
;
1537 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1538 LocalFree(Expanded
);
1539 RtlFreeUnicodeString(&NtPathName
);
1540 return ERROR_INVALID_PARAMETER
;
1545 DPRINT1("Error, Status = %08X\n", Status
);
1546 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1547 LocalFree(Expanded
);
1548 RtlFreeUnicodeString(&NtPathName
);
1549 return ERROR_INVALID_PARAMETER
;
1554 DPRINT1("Error, Status = %08X\n", Status
);
1555 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1556 LocalFree(Expanded
);
1557 RtlFreeUnicodeString(&NtPathName
);
1558 return ERROR_INVALID_PARAMETER
;
1563 DPRINT1("Error, Status = %08X\n", Status
);
1564 LocalFree(Expanded
);
1565 return ERROR_INVALID_PARAMETER
;
1569 *RelativeName
= NULL
;
1570 return ERROR_INVALID_PARAMETER
;
1574 ScmCanonDriverImagePath(DWORD dwStartType
,
1575 wchar_t *lpServiceName
,
1576 wchar_t **lpCanonName
)
1578 DWORD ServiceNameLen
, Result
;
1579 UNICODE_STRING NtServiceName
;
1580 WCHAR
*RelativeName
;
1581 WCHAR
*SourceName
= lpServiceName
;
1583 /* Calculate the length of the service's name */
1584 ServiceNameLen
= wcslen(lpServiceName
);
1586 /* 12 is wcslen(L"\\SystemRoot\\") */
1587 if (ServiceNameLen
> 12 &&
1588 !wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1590 /* SystemRoot prefix is already included */
1592 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1594 if (*lpCanonName
== NULL
)
1596 DPRINT1("Error allocating memory for canonized service name!\n");
1597 return ERROR_NOT_ENOUGH_MEMORY
;
1600 /* If it's a boot-time driver, it must be systemroot relative */
1601 if (dwStartType
== SERVICE_BOOT_START
)
1605 wcscpy(*lpCanonName
, SourceName
);
1607 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1611 /* Check if it has %SystemRoot% (len=13) */
1612 if (ServiceNameLen
> 13 &&
1613 !wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1615 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1616 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1618 if (*lpCanonName
== NULL
)
1620 DPRINT1("Error allocating memory for canonized service name!\n");
1621 return ERROR_NOT_ENOUGH_MEMORY
;
1624 /* If it's a boot-time driver, it must be systemroot relative */
1625 if (dwStartType
== SERVICE_BOOT_START
)
1626 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1628 wcscat(*lpCanonName
, lpServiceName
+ 13);
1630 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1634 /* Check if it's a relative path name */
1635 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1637 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1639 if (*lpCanonName
== NULL
)
1641 DPRINT1("Error allocating memory for canonized service name!\n");
1642 return ERROR_NOT_ENOUGH_MEMORY
;
1645 /* Just copy it over without changing */
1646 wcscpy(*lpCanonName
, lpServiceName
);
1651 /* It seems to be a DOS path, convert it */
1652 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1654 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1655 return ERROR_INVALID_PARAMETER
;
1658 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1660 if (*lpCanonName
== NULL
)
1662 DPRINT1("Error allocating memory for canonized service name!\n");
1663 RtlFreeUnicodeString(&NtServiceName
);
1664 return ERROR_NOT_ENOUGH_MEMORY
;
1667 /* Copy the string */
1668 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1670 /* The unicode string is not needed anymore */
1671 RtlFreeUnicodeString(&NtServiceName
);
1673 if (dwStartType
!= SERVICE_BOOT_START
)
1675 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1679 /* The service is boot-started, so must be relative */
1680 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1683 /* There is a problem, free name and return */
1684 LocalFree(*lpCanonName
);
1685 DPRINT1("Error converting named!\n");
1689 ASSERT(RelativeName
);
1691 /* Copy that string */
1692 wcscpy(*lpCanonName
, RelativeName
+ 12);
1694 /* Free the allocated buffer */
1695 LocalFree(RelativeName
);
1697 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1705 DWORD
RCreateServiceW(
1706 SC_RPC_HANDLE hSCManager
,
1707 LPWSTR lpServiceName
,
1708 LPWSTR lpDisplayName
,
1709 DWORD dwDesiredAccess
,
1710 DWORD dwServiceType
,
1712 DWORD dwErrorControl
,
1713 LPWSTR lpBinaryPathName
,
1714 LPWSTR lpLoadOrderGroup
,
1716 LPBYTE lpDependencies
,
1718 LPWSTR lpServiceStartName
,
1721 LPSC_RPC_HANDLE lpServiceHandle
)
1723 PMANAGER_HANDLE hManager
;
1724 DWORD dwError
= ERROR_SUCCESS
;
1725 PSERVICE lpService
= NULL
;
1726 SC_HANDLE hServiceHandle
= NULL
;
1727 LPWSTR lpImagePath
= NULL
;
1728 HKEY hServiceKey
= NULL
;
1730 DPRINT("RCreateServiceW() called\n");
1731 DPRINT("lpServiceName = %S\n", lpServiceName
);
1732 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1733 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1734 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1735 DPRINT("dwStartType = %lu\n", dwStartType
);
1736 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1737 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1738 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1741 return ERROR_SHUTDOWN_IN_PROGRESS
;
1743 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1744 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1746 DPRINT1("Invalid manager handle!\n");
1747 return ERROR_INVALID_HANDLE
;
1750 /* Check access rights */
1751 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1752 SC_MANAGER_CREATE_SERVICE
))
1754 DPRINT1("Insufficient access rights! 0x%lx\n",
1755 hManager
->Handle
.DesiredAccess
);
1756 return ERROR_ACCESS_DENIED
;
1759 if (wcslen(lpServiceName
) == 0)
1761 return ERROR_INVALID_NAME
;
1764 if (wcslen(lpBinaryPathName
) == 0)
1766 return ERROR_INVALID_PARAMETER
;
1769 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1770 (lpServiceStartName
))
1772 return ERROR_INVALID_PARAMETER
;
1775 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1776 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1777 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1779 return ERROR_INVALID_PARAMETER
;
1782 if (dwStartType
> SERVICE_DISABLED
)
1784 return ERROR_INVALID_PARAMETER
;
1787 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1790 /* check if it is marked for deletion */
1791 if (lpService
->bDeleted
)
1792 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1793 /* Return Error exist */
1794 return ERROR_SERVICE_EXISTS
;
1797 if (lpDisplayName
!= NULL
&&
1798 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1799 return ERROR_DUPLICATE_SERVICE_NAME
;
1801 if (dwServiceType
& SERVICE_DRIVER
)
1803 dwError
= ScmCanonDriverImagePath(dwStartType
,
1806 if (dwError
!= ERROR_SUCCESS
)
1811 if (dwStartType
== SERVICE_BOOT_START
||
1812 dwStartType
== SERVICE_SYSTEM_START
)
1814 return ERROR_INVALID_PARAMETER
;
1818 /* Allocate a new service entry */
1819 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1821 if (dwError
!= ERROR_SUCCESS
)
1824 /* Fill the new service entry */
1825 lpService
->Status
.dwServiceType
= dwServiceType
;
1826 lpService
->dwStartType
= dwStartType
;
1827 lpService
->dwErrorControl
= dwErrorControl
;
1829 /* Fill the display name */
1830 if (lpDisplayName
!= NULL
&&
1831 *lpDisplayName
!= 0 &&
1832 wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1834 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1835 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1836 if (lpService
->lpDisplayName
== NULL
)
1838 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1841 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1844 /* Assign the service to a group */
1845 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1847 dwError
= ScmSetServiceGroup(lpService
,
1849 if (dwError
!= ERROR_SUCCESS
)
1853 /* Assign a new tag */
1854 if (lpdwTagId
!= NULL
)
1856 dwError
= ScmAssignNewTag(lpService
);
1857 if (dwError
!= ERROR_SUCCESS
)
1861 /* Write service data to the registry */
1862 /* Create the service key */
1863 dwError
= ScmCreateServiceKey(lpServiceName
,
1866 if (dwError
!= ERROR_SUCCESS
)
1869 /* Set the display name */
1870 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1872 RegSetValueExW(hServiceKey
,
1876 (LPBYTE
)lpDisplayName
,
1877 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1880 /* Set the service type */
1881 dwError
= RegSetValueExW(hServiceKey
,
1885 (LPBYTE
)&dwServiceType
,
1887 if (dwError
!= ERROR_SUCCESS
)
1890 /* Set the start value */
1891 dwError
= RegSetValueExW(hServiceKey
,
1895 (LPBYTE
)&dwStartType
,
1897 if (dwError
!= ERROR_SUCCESS
)
1900 /* Set the error control value */
1901 dwError
= RegSetValueExW(hServiceKey
,
1905 (LPBYTE
)&dwErrorControl
,
1907 if (dwError
!= ERROR_SUCCESS
)
1910 /* Set the image path */
1911 if (dwServiceType
& SERVICE_WIN32
)
1913 dwError
= RegSetValueExW(hServiceKey
,
1917 (LPBYTE
)lpBinaryPathName
,
1918 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1919 if (dwError
!= ERROR_SUCCESS
)
1922 else if (dwServiceType
& SERVICE_DRIVER
)
1924 dwError
= RegSetValueExW(hServiceKey
,
1928 (LPBYTE
)lpImagePath
,
1929 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1930 if (dwError
!= ERROR_SUCCESS
)
1934 /* Set the group name */
1935 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1937 dwError
= RegSetValueExW(hServiceKey
,
1941 (LPBYTE
)lpLoadOrderGroup
,
1942 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1943 if (dwError
!= ERROR_SUCCESS
)
1947 if (lpdwTagId
!= NULL
)
1949 dwError
= RegSetValueExW(hServiceKey
,
1953 (LPBYTE
)&lpService
->dwTag
,
1955 if (dwError
!= ERROR_SUCCESS
)
1959 /* Write dependencies */
1960 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1962 dwError
= ScmWriteDependencies(hServiceKey
,
1963 (LPWSTR
)lpDependencies
,
1965 if (dwError
!= ERROR_SUCCESS
)
1969 /* If a non driver and NULL for lpServiceName, write ObjectName as LocalSystem */
1970 if ((dwServiceType
& SERVICE_WIN32
) && (!lpServiceName
))
1972 dwError
= RegSetValueExW(hServiceKey
,
1976 (LPBYTE
)L
"LocalSystem",
1978 if (dwError
!= ERROR_SUCCESS
)
1982 if (lpPassword
!= NULL
)
1984 /* FIXME: Write password */
1987 dwError
= ScmCreateServiceHandle(lpService
,
1989 if (dwError
!= ERROR_SUCCESS
)
1992 dwError
= ScmCheckAccess(hServiceHandle
,
1994 if (dwError
!= ERROR_SUCCESS
)
1997 lpService
->dwRefCount
= 1;
1998 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2001 if (hServiceKey
!= NULL
)
2002 RegCloseKey(hServiceKey
);
2004 if (dwError
== ERROR_SUCCESS
)
2006 DPRINT("hService %p\n", hServiceHandle
);
2007 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2009 if (lpdwTagId
!= NULL
)
2010 *lpdwTagId
= lpService
->dwTag
;
2014 /* Release the display name buffer */
2015 if (lpService
->lpServiceName
!= NULL
)
2016 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2020 /* Remove the service handle */
2021 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2024 if (lpService
!= NULL
)
2026 /* FIXME: remove the service entry */
2030 if (lpImagePath
!= NULL
)
2031 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2033 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2040 DWORD
REnumDependentServicesW(
2041 SC_RPC_HANDLE hService
,
2042 DWORD dwServiceState
,
2045 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2046 LPBOUNDED_DWORD_256K lpServicesReturned
)
2048 DWORD dwError
= ERROR_SUCCESS
;
2049 DWORD dwServicesReturned
= 0;
2050 DWORD dwServiceCount
;
2051 HKEY hServicesKey
= NULL
;
2052 LPSC_RPC_HANDLE hSCObject
;
2053 PSERVICE_HANDLE hSvc
;
2054 PSERVICE lpService
= NULL
;
2055 PSERVICE
*lpServicesArray
= NULL
;
2056 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2059 *pcbBytesNeeded
= 0;
2060 *lpServicesReturned
= 0;
2062 DPRINT("REnumDependentServicesW() called\n");
2064 hSCObject
= &hService
;
2065 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
2066 lpService
= hSvc
->ServiceEntry
;
2068 /* Check access rights */
2069 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2070 SC_MANAGER_ENUMERATE_SERVICE
))
2072 DPRINT1("Insufficient access rights! 0x%lx\n",
2073 hSvc
->Handle
.DesiredAccess
);
2074 return ERROR_ACCESS_DENIED
;
2077 /* Open the Services Reg key */
2078 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2079 L
"System\\CurrentControlSet\\Services",
2083 if (dwError
!= ERROR_SUCCESS
)
2086 /* First determine the bytes needed and get the number of dependent services */
2087 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2092 &dwServicesReturned
);
2093 if (dwError
!= ERROR_SUCCESS
)
2096 /* If buffer size is less than the bytes needed or pointer is null */
2097 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2099 dwError
= ERROR_MORE_DATA
;
2103 /* Allocate memory for array of service pointers */
2104 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2106 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2107 if (!lpServicesArray
)
2109 DPRINT1("Could not allocate a buffer!!\n");
2110 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2114 dwServicesReturned
= 0;
2115 *pcbBytesNeeded
= 0;
2117 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2122 &dwServicesReturned
);
2123 if (dwError
!= ERROR_SUCCESS
)
2128 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2129 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2131 /* Copy EnumDepenedentService to Buffer */
2132 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2134 lpService
= lpServicesArray
[dwServiceCount
];
2136 /* Copy status info */
2137 memcpy(&lpServicesPtr
->ServiceStatus
,
2139 sizeof(SERVICE_STATUS
));
2141 /* Copy display name */
2142 wcscpy(lpStr
, lpService
->lpDisplayName
);
2143 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2144 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2146 /* Copy service name */
2147 wcscpy(lpStr
, lpService
->lpServiceName
);
2148 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2149 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2154 *lpServicesReturned
= dwServicesReturned
;
2157 if (lpServicesArray
!= NULL
)
2158 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2160 RegCloseKey(hServicesKey
);
2162 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2169 DWORD
REnumServicesStatusW(
2170 SC_RPC_HANDLE hSCManager
,
2171 DWORD dwServiceType
,
2172 DWORD dwServiceState
,
2175 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2176 LPBOUNDED_DWORD_256K lpServicesReturned
,
2177 LPBOUNDED_DWORD_256K lpResumeHandle
)
2179 PMANAGER_HANDLE hManager
;
2181 DWORD dwError
= ERROR_SUCCESS
;
2182 PLIST_ENTRY ServiceEntry
;
2183 PSERVICE CurrentService
;
2185 DWORD dwRequiredSize
;
2186 DWORD dwServiceCount
;
2188 DWORD dwLastResumeCount
= 0;
2189 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2192 DPRINT("REnumServicesStatusW() called\n");
2195 return ERROR_SHUTDOWN_IN_PROGRESS
;
2197 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2198 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2200 DPRINT1("Invalid manager handle!\n");
2201 return ERROR_INVALID_HANDLE
;
2204 *pcbBytesNeeded
= 0;
2205 *lpServicesReturned
= 0;
2207 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2209 DPRINT("Not a valid Service Type!\n");
2210 return ERROR_INVALID_PARAMETER
;
2213 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2215 DPRINT("Not a valid Service State!\n");
2216 return ERROR_INVALID_PARAMETER
;
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 if (lpResumeHandle
) dwLastResumeCount
= *lpResumeHandle
;
2230 /* FIXME: Lock the service list shared */
2232 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2233 if (lpService
== NULL
)
2235 dwError
= ERROR_SUCCESS
;
2242 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2243 ServiceEntry
!= &ServiceListHead
;
2244 ServiceEntry
= ServiceEntry
->Flink
)
2246 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2250 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2253 dwState
= SERVICE_ACTIVE
;
2254 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2255 dwState
= SERVICE_INACTIVE
;
2257 if ((dwState
& dwServiceState
) == 0)
2260 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2261 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2262 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2264 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2266 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2270 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2271 dwRequiredSize
+= dwSize
;
2273 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2276 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2277 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2280 ServiceEntry
!= &ServiceListHead
;
2281 ServiceEntry
= ServiceEntry
->Flink
)
2283 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2287 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2290 dwState
= SERVICE_ACTIVE
;
2291 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2292 dwState
= SERVICE_INACTIVE
;
2294 if ((dwState
& dwServiceState
) == 0)
2297 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2298 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2299 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2301 dwError
= ERROR_MORE_DATA
;
2304 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2306 if (lpResumeHandle
) *lpResumeHandle
= dwLastResumeCount
;
2307 *lpServicesReturned
= dwServiceCount
;
2308 *pcbBytesNeeded
= dwRequiredSize
;
2310 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2311 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2312 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2315 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2316 ServiceEntry
!= &ServiceListHead
;
2317 ServiceEntry
= ServiceEntry
->Flink
)
2319 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2323 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2326 dwState
= SERVICE_ACTIVE
;
2327 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2328 dwState
= SERVICE_INACTIVE
;
2330 if ((dwState
& dwServiceState
) == 0)
2333 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2334 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2335 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2337 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2340 /* Copy the service name */
2341 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2342 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2343 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2345 /* Copy the display name */
2346 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2347 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2348 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2350 /* Copy the status information */
2351 memcpy(&lpStatusPtr
->ServiceStatus
,
2352 &CurrentService
->Status
,
2353 sizeof(SERVICE_STATUS
));
2356 dwRequiredSize
+= dwSize
;
2361 *pcbBytesNeeded
= 0;
2362 if (lpResumeHandle
) *lpResumeHandle
= 0;
2366 /* FIXME: Unlock the service list */
2368 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2375 DWORD
ROpenSCManagerW(
2376 LPWSTR lpMachineName
,
2377 LPWSTR lpDatabaseName
,
2378 DWORD dwDesiredAccess
,
2379 LPSC_RPC_HANDLE lpScHandle
)
2384 DPRINT("ROpenSCManagerW() called\n");
2385 DPRINT("lpMachineName = %p\n", lpMachineName
);
2386 DPRINT("lpMachineName: %S\n", lpMachineName
);
2387 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2388 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2389 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2392 return ERROR_SHUTDOWN_IN_PROGRESS
;
2395 return ERROR_INVALID_PARAMETER
;
2397 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2399 if (dwError
!= ERROR_SUCCESS
)
2401 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2405 /* Check the desired access */
2406 dwError
= ScmCheckAccess(hHandle
,
2407 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2408 if (dwError
!= ERROR_SUCCESS
)
2410 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2411 HeapFree(GetProcessHeap(), 0, hHandle
);
2415 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2416 DPRINT("*hScm = %p\n", *lpScHandle
);
2418 DPRINT("ROpenSCManagerW() done\n");
2420 return ERROR_SUCCESS
;
2425 DWORD
ROpenServiceW(
2426 SC_RPC_HANDLE hSCManager
,
2427 LPWSTR lpServiceName
,
2428 DWORD dwDesiredAccess
,
2429 LPSC_RPC_HANDLE lpServiceHandle
)
2432 PMANAGER_HANDLE hManager
;
2436 DPRINT("ROpenServiceW() called\n");
2437 DPRINT("hSCManager = %p\n", hSCManager
);
2438 DPRINT("lpServiceName = %p\n", lpServiceName
);
2439 DPRINT("lpServiceName: %S\n", lpServiceName
);
2440 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2443 return ERROR_SHUTDOWN_IN_PROGRESS
;
2445 if (!lpServiceHandle
)
2446 return ERROR_INVALID_PARAMETER
;
2449 return ERROR_INVALID_ADDRESS
;
2451 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2452 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2454 DPRINT1("Invalid manager handle!\n");
2455 return ERROR_INVALID_HANDLE
;
2458 /* FIXME: Lock the service list */
2460 /* Get service database entry */
2461 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2462 if (lpService
== NULL
)
2464 DPRINT("Could not find a service!\n");
2465 return ERROR_SERVICE_DOES_NOT_EXIST
;
2468 /* Create a service handle */
2469 dwError
= ScmCreateServiceHandle(lpService
,
2471 if (dwError
!= ERROR_SUCCESS
)
2473 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2477 /* Check the desired access */
2478 dwError
= ScmCheckAccess(hHandle
,
2480 if (dwError
!= ERROR_SUCCESS
)
2482 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2483 HeapFree(GetProcessHeap(), 0, hHandle
);
2487 lpService
->dwRefCount
++;
2488 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2490 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2491 DPRINT("*hService = %p\n", *lpServiceHandle
);
2493 DPRINT("ROpenServiceW() done\n");
2495 return ERROR_SUCCESS
;
2500 DWORD
RQueryServiceConfigW(
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 SC_RPC_HANDLE hSCManager
,
2678 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2680 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2683 return ERROR_CALL_NOT_IMPLEMENTED
;
2688 DWORD
RStartServiceW(
2689 SC_RPC_HANDLE hService
,
2691 LPSTRING_PTRSW argv
)
2693 DWORD dwError
= ERROR_SUCCESS
;
2694 PSERVICE_HANDLE hSvc
;
2695 PSERVICE lpService
= NULL
;
2697 DPRINT("RStartServiceW() called\n");
2700 return ERROR_SHUTDOWN_IN_PROGRESS
;
2702 hSvc
= (PSERVICE_HANDLE
)hService
;
2703 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2705 DPRINT1("Invalid handle tag!\n");
2706 return ERROR_INVALID_HANDLE
;
2709 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2712 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2713 return ERROR_ACCESS_DENIED
;
2716 lpService
= hSvc
->ServiceEntry
;
2717 if (lpService
== NULL
)
2719 DPRINT1("lpService == NULL!\n");
2720 return ERROR_INVALID_HANDLE
;
2723 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2724 return ERROR_SERVICE_DISABLED
;
2726 if (lpService
->bDeleted
)
2727 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2734 /* Start the service */
2735 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2742 DWORD
RGetServiceDisplayNameW(
2743 SC_RPC_HANDLE hSCManager
,
2744 LPWSTR lpServiceName
,
2745 LPWSTR lpDisplayName
,
2748 // PMANAGER_HANDLE hManager;
2753 DPRINT("RGetServiceDisplayNameW() called\n");
2754 DPRINT("hSCManager = %p\n", hSCManager
);
2755 DPRINT("lpServiceName: %S\n", lpServiceName
);
2756 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2757 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2759 // hManager = (PMANAGER_HANDLE)hSCManager;
2760 // if (hManager->Handle.Tag != MANAGER_TAG)
2762 // DPRINT1("Invalid manager handle!\n");
2763 // return ERROR_INVALID_HANDLE;
2766 /* Get service database entry */
2767 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2768 if (lpService
== NULL
)
2770 DPRINT1("Could not find a service!\n");
2772 /* If the service could not be found and lpcchBuffer is 0, windows
2773 puts null in lpDisplayName and puts 1 in lpcchBuffer */
2774 if (*lpcchBuffer
== 0)
2777 *lpDisplayName
= '\0';
2780 return ERROR_SERVICE_DOES_NOT_EXIST
;
2783 if (!lpService
->lpDisplayName
)
2785 dwLength
= wcslen(lpService
->lpServiceName
);
2787 if (lpServiceName
!= NULL
&&
2788 *lpcchBuffer
> dwLength
)
2790 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2795 dwLength
= wcslen(lpService
->lpDisplayName
);
2797 if (lpDisplayName
!= NULL
&&
2798 *lpcchBuffer
> dwLength
)
2800 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2804 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2806 *lpcchBuffer
= dwLength
;
2813 DWORD
RGetServiceKeyNameW(
2814 SC_RPC_HANDLE hSCManager
,
2815 LPWSTR lpDisplayName
,
2816 LPWSTR lpServiceName
,
2819 // PMANAGER_HANDLE hManager;
2824 DPRINT("RGetServiceKeyNameW() called\n");
2825 DPRINT("hSCManager = %p\n", hSCManager
);
2826 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2827 DPRINT("lpServiceName: %p\n", lpServiceName
);
2828 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2830 // hManager = (PMANAGER_HANDLE)hSCManager;
2831 // if (hManager->Handle.Tag != MANAGER_TAG)
2833 // DPRINT1("Invalid manager handle!\n");
2834 // return ERROR_INVALID_HANDLE;
2837 /* Get service database entry */
2838 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2839 if (lpService
== NULL
)
2841 DPRINT1("Could not find a service!\n");
2843 /* If the service could not be found and lpcchBuffer is 0, windows
2844 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2845 if (*lpcchBuffer
== 0)
2848 *lpServiceName
= '\0';
2851 return ERROR_SERVICE_DOES_NOT_EXIST
;
2854 dwLength
= wcslen(lpService
->lpServiceName
);
2856 if (lpServiceName
!= NULL
&&
2857 *lpcchBuffer
> dwLength
)
2859 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2860 *lpcchBuffer
= dwLength
;
2861 return ERROR_SUCCESS
;
2864 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2866 *lpcchBuffer
= dwLength
* 2;
2873 DWORD
RI_ScSetServiceBitsA(
2874 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
2875 DWORD dwServiceBits
,
2877 int bUpdateImmediately
,
2881 return ERROR_CALL_NOT_IMPLEMENTED
;
2886 DWORD
RChangeServiceConfigA(
2887 SC_RPC_HANDLE hService
,
2888 DWORD dwServiceType
,
2890 DWORD dwErrorControl
,
2891 LPSTR lpBinaryPathName
,
2892 LPSTR lpLoadOrderGroup
,
2894 LPSTR lpDependencies
,
2896 LPSTR lpServiceStartName
,
2899 LPSTR lpDisplayName
)
2901 DWORD dwError
= ERROR_SUCCESS
;
2902 PSERVICE_HANDLE hSvc
;
2903 PSERVICE lpService
= NULL
;
2904 HKEY hServiceKey
= NULL
;
2905 LPWSTR lpDisplayNameW
= NULL
;
2906 // LPWSTR lpBinaryPathNameW = NULL;
2907 LPWSTR lpLoadOrderGroupW
= NULL
;
2908 LPWSTR lpDependenciesW
= NULL
;
2909 // LPWSTR lpPasswordW = NULL;
2911 DPRINT("RChangeServiceConfigA() called\n");
2912 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2913 DPRINT("dwStartType = %lu\n", dwStartType
);
2914 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2915 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2916 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2917 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2920 return ERROR_SHUTDOWN_IN_PROGRESS
;
2922 hSvc
= (PSERVICE_HANDLE
)hService
;
2923 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2925 DPRINT1("Invalid handle tag!\n");
2926 return ERROR_INVALID_HANDLE
;
2929 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2930 SERVICE_CHANGE_CONFIG
))
2932 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2933 return ERROR_ACCESS_DENIED
;
2936 lpService
= hSvc
->ServiceEntry
;
2937 if (lpService
== NULL
)
2939 DPRINT1("lpService == NULL!\n");
2940 return ERROR_INVALID_HANDLE
;
2943 /* FIXME: Lock database exclusively */
2945 if (lpService
->bDeleted
)
2947 /* FIXME: Unlock database */
2948 DPRINT1("The service has already been marked for delete!\n");
2949 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2952 /* Open the service key */
2953 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2956 if (dwError
!= ERROR_SUCCESS
)
2959 /* Write service data to the registry */
2961 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2963 /* Set the display name */
2964 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2966 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2967 if (lpDisplayNameW
== NULL
)
2969 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2973 MultiByteToWideChar(CP_ACP
,
2978 wcslen(lpDisplayNameW
) + 1);
2980 RegSetValueExW(hServiceKey
,
2984 (LPBYTE
)lpDisplayNameW
,
2985 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2987 /* Update lpService->lpDisplayName */
2988 if (lpService
->lpDisplayName
)
2989 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2991 lpService
->lpDisplayName
= lpDisplayNameW
;
2994 if (dwServiceType
!= SERVICE_NO_CHANGE
)
2996 /* Set the service type */
2997 dwError
= RegSetValueExW(hServiceKey
,
3001 (LPBYTE
)&dwServiceType
,
3003 if (dwError
!= ERROR_SUCCESS
)
3006 lpService
->Status
.dwServiceType
= dwServiceType
;
3009 if (dwStartType
!= SERVICE_NO_CHANGE
)
3011 /* Set the start value */
3012 dwError
= RegSetValueExW(hServiceKey
,
3016 (LPBYTE
)&dwStartType
,
3018 if (dwError
!= ERROR_SUCCESS
)
3021 lpService
->dwStartType
= dwStartType
;
3024 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3026 /* Set the error control value */
3027 dwError
= RegSetValueExW(hServiceKey
,
3031 (LPBYTE
)&dwErrorControl
,
3033 if (dwError
!= ERROR_SUCCESS
)
3036 lpService
->dwErrorControl
= dwErrorControl
;
3040 /* FIXME: set the new ImagePath value */
3042 /* Set the image path */
3043 if (dwServiceType
& SERVICE_WIN32
)
3045 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3047 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3048 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, wcslen(lpBinaryPathNameW
)+1);
3049 dwError
= RegSetValueExW(hServiceKey
,
3053 (LPBYTE
)lpBinaryPathNameW
,
3054 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3055 if (dwError
!= ERROR_SUCCESS
)
3059 else if (dwServiceType
& SERVICE_DRIVER
)
3061 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3063 dwError
= RegSetValueExW(hServiceKey
,
3067 (LPBYTE
)lpImagePath
,
3068 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3069 if (dwError
!= ERROR_SUCCESS
)
3075 /* Set the group name */
3076 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3078 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3080 (strlen(lpLoadOrderGroup
)+1) * sizeof(WCHAR
));
3081 if (lpLoadOrderGroupW
== NULL
)
3083 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3087 MultiByteToWideChar(CP_ACP
,
3092 wcslen(lpLoadOrderGroupW
) + 1);
3094 dwError
= RegSetValueExW(hServiceKey
,
3098 (LPBYTE
)lpLoadOrderGroupW
,
3099 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3100 if (dwError
!= ERROR_SUCCESS
)
3103 /* FIXME: Update lpService->lpServiceGroup */
3105 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3108 if (lpdwTagId
!= NULL
)
3110 dwError
= ScmAssignNewTag(lpService
);
3111 if (dwError
!= ERROR_SUCCESS
)
3114 dwError
= RegSetValueExW(hServiceKey
,
3118 (LPBYTE
)&lpService
->dwTag
,
3120 if (dwError
!= ERROR_SUCCESS
)
3123 *lpdwTagId
= lpService
->dwTag
;
3126 /* Write dependencies */
3127 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3129 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3131 (strlen(lpDependencies
)+1) * sizeof(WCHAR
));
3132 if (lpDependenciesW
== NULL
)
3134 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3138 MultiByteToWideChar(CP_ACP
,
3143 wcslen(lpDependenciesW
)+1);
3145 dwError
= ScmWriteDependencies(hServiceKey
,
3146 (LPWSTR
)lpDependenciesW
,
3149 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3152 if (lpPassword
!= NULL
)
3154 /* FIXME: Write password */
3157 /* FIXME: Unlock database */
3160 if (hServiceKey
!= NULL
)
3161 RegCloseKey(hServiceKey
);
3163 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3170 DWORD
RCreateServiceA(
3171 SC_RPC_HANDLE hSCManager
,
3172 LPSTR lpServiceName
,
3173 LPSTR lpDisplayName
,
3174 DWORD dwDesiredAccess
,
3175 DWORD dwServiceType
,
3177 DWORD dwErrorControl
,
3178 LPSTR lpBinaryPathName
,
3179 LPSTR lpLoadOrderGroup
,
3181 LPBYTE lpDependencies
,
3183 LPSTR lpServiceStartName
,
3186 LPSC_RPC_HANDLE lpServiceHandle
)
3189 return ERROR_CALL_NOT_IMPLEMENTED
;
3194 DWORD
REnumDependentServicesA(
3195 SC_RPC_HANDLE hService
,
3196 DWORD dwServiceState
,
3199 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3200 LPBOUNDED_DWORD_256K lpServicesReturned
)
3202 DWORD dwError
= ERROR_SUCCESS
;
3203 DWORD dwServicesReturned
= 0;
3204 DWORD dwServiceCount
;
3205 HKEY hServicesKey
= NULL
;
3206 LPSC_RPC_HANDLE hSCObject
;
3207 PSERVICE_HANDLE hSvc
;
3208 PSERVICE lpService
= NULL
;
3209 PSERVICE
*lpServicesArray
= NULL
;
3210 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3213 *pcbBytesNeeded
= 0;
3214 *lpServicesReturned
= 0;
3216 DPRINT("REnumDependentServicesA() called\n");
3218 hSCObject
= &hService
;
3219 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3220 lpService
= hSvc
->ServiceEntry
;
3222 /* Check access rights */
3223 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3224 SC_MANAGER_ENUMERATE_SERVICE
))
3226 DPRINT1("Insufficient access rights! 0x%lx\n",
3227 hSvc
->Handle
.DesiredAccess
);
3228 return ERROR_ACCESS_DENIED
;
3231 /* Open the Services Reg key */
3232 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3233 L
"System\\CurrentControlSet\\Services",
3238 if (dwError
!= ERROR_SUCCESS
) return dwError
;
3240 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3241 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3242 are the same for both. Verified in WINXP. */
3244 /* First determine the bytes needed and get the number of dependent services*/
3245 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3250 &dwServicesReturned
);
3251 if (dwError
!= ERROR_SUCCESS
)
3254 /* If buffer size is less than the bytes needed or pointer is null*/
3255 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3257 dwError
= ERROR_MORE_DATA
;