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 ****************************************************************/
18 /* GLOBALS *****************************************************************/
20 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
21 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
23 typedef struct _SCMGR_HANDLE
30 typedef struct _MANAGER_HANDLE
33 WCHAR DatabaseName
[1];
34 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
37 typedef struct _SERVICE_HANDLE
40 PSERVICE ServiceEntry
;
41 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
44 #define SC_MANAGER_READ \
45 (STANDARD_RIGHTS_READ | \
46 SC_MANAGER_QUERY_LOCK_STATUS | \
47 SC_MANAGER_ENUMERATE_SERVICE)
49 #define SC_MANAGER_WRITE \
50 (STANDARD_RIGHTS_WRITE | \
51 SC_MANAGER_MODIFY_BOOT_CONFIG | \
52 SC_MANAGER_CREATE_SERVICE)
54 #define SC_MANAGER_EXECUTE \
55 (STANDARD_RIGHTS_EXECUTE | \
57 SC_MANAGER_ENUMERATE_SERVICE | \
58 SC_MANAGER_CONNECT | \
59 SC_MANAGER_CREATE_SERVICE)
62 #define SERVICE_READ \
63 (STANDARD_RIGHTS_READ | \
64 SERVICE_INTERROGATE | \
65 SERVICE_ENUMERATE_DEPENDENTS | \
66 SERVICE_QUERY_STATUS | \
69 #define SERVICE_WRITE \
70 (STANDARD_RIGHTS_WRITE | \
71 SERVICE_CHANGE_CONFIG)
73 #define SERVICE_EXECUTE \
74 (STANDARD_RIGHTS_EXECUTE | \
75 SERVICE_USER_DEFINED_CONTROL | \
76 SERVICE_PAUSE_CONTINUE | \
80 #define TAG_ARRAY_SIZE 32
82 /* VARIABLES ***************************************************************/
84 static GENERIC_MAPPING
85 ScmManagerMapping
= {SC_MANAGER_READ
,
88 SC_MANAGER_ALL_ACCESS
};
90 static GENERIC_MAPPING
91 ScmServiceMapping
= {SERVICE_READ
,
97 /* FUNCTIONS ***************************************************************/
100 ScmStartRpcServer(VOID
)
104 DPRINT("ScmStartRpcServer() called\n");
106 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
110 if (Status
!= RPC_S_OK
)
112 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
116 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
119 if (Status
!= RPC_S_OK
)
121 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
125 Status
= RpcServerListen(1, 20, TRUE
);
126 if (Status
!= RPC_S_OK
)
128 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
132 DPRINT("ScmStartRpcServer() done\n");
137 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
142 if (lpDatabaseName
== NULL
)
143 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
145 if (_wcsicmp(lpDatabaseName
, SERVICES_FAILED_DATABASEW
) == 0)
147 DPRINT("Database %S, does not exist\n", lpDatabaseName
);
148 return ERROR_DATABASE_DOES_NOT_EXIST
;
150 else if (_wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
152 DPRINT("Invalid Database name %S.\n", lpDatabaseName
);
153 return ERROR_INVALID_NAME
;
156 Ptr
= HeapAlloc(GetProcessHeap(),
158 FIELD_OFFSET(MANAGER_HANDLE
, DatabaseName
[wcslen(lpDatabaseName
) + 1]));
160 return ERROR_NOT_ENOUGH_MEMORY
;
162 Ptr
->Handle
.Tag
= MANAGER_TAG
;
164 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
166 *Handle
= (SC_HANDLE
)Ptr
;
168 return ERROR_SUCCESS
;
173 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
178 Ptr
= HeapAlloc(GetProcessHeap(),
180 sizeof(SERVICE_HANDLE
));
182 return ERROR_NOT_ENOUGH_MEMORY
;
184 Ptr
->Handle
.Tag
= SERVICE_TAG
;
186 Ptr
->ServiceEntry
= lpServiceEntry
;
188 *Handle
= (SC_HANDLE
)Ptr
;
190 return ERROR_SUCCESS
;
194 static PMANAGER_HANDLE
195 ScmGetServiceManagerFromHandle(SC_RPC_HANDLE Handle
)
197 PMANAGER_HANDLE pManager
= NULL
;
201 if (((PMANAGER_HANDLE
)Handle
)->Handle
.Tag
== MANAGER_TAG
)
202 pManager
= (PMANAGER_HANDLE
)Handle
;
204 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
206 DPRINT1("Exception: Invalid Service Manager handle!\n");
214 static PSERVICE_HANDLE
215 ScmGetServiceFromHandle(SC_RPC_HANDLE Handle
)
217 PSERVICE_HANDLE pService
= NULL
;
221 if (((PSERVICE_HANDLE
)Handle
)->Handle
.Tag
== SERVICE_TAG
)
222 pService
= (PSERVICE_HANDLE
)Handle
;
224 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
226 DPRINT1("Exception: Invalid Service handle!\n");
235 ScmCheckAccess(SC_HANDLE Handle
,
236 DWORD dwDesiredAccess
)
238 PMANAGER_HANDLE hMgr
;
240 hMgr
= (PMANAGER_HANDLE
)Handle
;
241 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
243 RtlMapGenericMask(&dwDesiredAccess
,
246 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
248 return ERROR_SUCCESS
;
250 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
252 RtlMapGenericMask(&dwDesiredAccess
,
255 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
257 return ERROR_SUCCESS
;
260 return ERROR_INVALID_HANDLE
;
265 ScmAssignNewTag(PSERVICE lpService
)
269 DWORD dwGroupTagCount
= 0;
270 PDWORD pdwGroupTags
= NULL
;
272 DWORD dwTagUsedBase
= 1;
273 BOOLEAN TagUsed
[TAG_ARRAY_SIZE
];
277 PLIST_ENTRY ServiceEntry
;
278 PSERVICE CurrentService
;
280 ASSERT(lpService
!= NULL
);
281 ASSERT(lpService
->lpGroup
!= NULL
);
283 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
284 L
"System\\CurrentControlSet\\Control\\GroupOrderList",
289 if (dwError
!= ERROR_SUCCESS
)
292 /* query value length */
294 dwError
= RegQueryValueExW(hKey
,
295 lpService
->lpGroup
->szGroupName
,
301 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_MORE_DATA
)
304 pdwGroupTags
= HeapAlloc(GetProcessHeap(), 0, cbDataSize
);
307 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
311 dwError
= RegQueryValueExW(hKey
,
312 lpService
->lpGroup
->szGroupName
,
315 (LPBYTE
)pdwGroupTags
,
318 if (dwError
!= ERROR_SUCCESS
)
321 if (cbDataSize
< sizeof(pdwGroupTags
[0]))
324 dwGroupTagCount
= min(pdwGroupTags
[0], cbDataSize
/ sizeof(pdwGroupTags
[0]) - 1);
329 /* mark all tags as unused */
330 for (i
= 0; i
< TAG_ARRAY_SIZE
; i
++)
333 /* mark tags in GroupOrderList as used */
334 for (i
= 1; i
<= dwGroupTagCount
; i
++)
336 dwTagOffset
= pdwGroupTags
[i
] - dwTagUsedBase
;
337 if (dwTagOffset
>= 0 && dwTagOffset
< TAG_ARRAY_SIZE
)
338 TagUsed
[dwTagOffset
] = TRUE
;
341 /* mark tags in service list as used */
342 ServiceEntry
= lpService
->ServiceListEntry
.Flink
;
343 while (ServiceEntry
!= &lpService
->ServiceListEntry
)
345 ASSERT(ServiceEntry
!= NULL
);
346 CurrentService
= CONTAINING_RECORD(ServiceEntry
, SERVICE
, ServiceListEntry
);
347 if (CurrentService
->lpGroup
== lpService
->lpGroup
)
349 dwTagOffset
= CurrentService
->dwTag
- dwTagUsedBase
;
350 if (dwTagOffset
>= 0 && dwTagOffset
< TAG_ARRAY_SIZE
)
351 TagUsed
[dwTagOffset
] = TRUE
;
354 ServiceEntry
= ServiceEntry
->Flink
;
357 /* find unused tag, if any */
358 for (i
= 0; i
< TAG_ARRAY_SIZE
; i
++)
362 dwFreeTag
= dwTagUsedBase
+ i
;
367 dwTagUsedBase
+= TAG_ARRAY_SIZE
;
373 HeapFree(GetProcessHeap(), 0, pdwGroupTags
);
380 lpService
->dwTag
= dwFreeTag
;
381 DPRINT("Assigning new tag %lu to service %S in group %S\n",
382 lpService
->dwTag
, lpService
->lpServiceName
, lpService
->lpGroup
->szGroupName
);
383 dwError
= ERROR_SUCCESS
;
387 DPRINT1("Failed to assign new tag to service %S, error=%lu\n",
388 lpService
->lpServiceName
, dwError
);
395 /* Internal recursive function */
396 /* Need to search for every dependency on every service */
398 Int_EnumDependentServicesW(HKEY hServicesKey
,
400 DWORD dwServiceState
,
401 PSERVICE
*lpServices
,
402 LPDWORD pcbBytesNeeded
,
403 LPDWORD lpServicesReturned
)
405 DWORD dwError
= ERROR_SUCCESS
;
406 WCHAR szNameBuf
[MAX_PATH
];
407 WCHAR szValueBuf
[MAX_PATH
];
408 WCHAR
*lpszNameBuf
= szNameBuf
;
409 WCHAR
*lpszValueBuf
= szValueBuf
;
413 PSERVICE lpCurrentService
;
414 HKEY hServiceEnumKey
;
415 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
416 DWORD dwDependServiceStrPtr
= 0;
417 DWORD dwRequiredSize
= 0;
419 /* Get the number of service keys */
420 dwError
= RegQueryInfoKeyW(hServicesKey
,
432 if (dwError
!= ERROR_SUCCESS
)
434 DPRINT("ERROR! Unable to get number of services keys.\n");
438 /* Iterate the service keys to see if another service depends on the this service */
439 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
442 dwError
= RegEnumKeyExW(hServicesKey
,
450 if (dwError
!= ERROR_SUCCESS
)
453 /* Open the Service key */
454 dwError
= RegOpenKeyExW(hServicesKey
,
459 if (dwError
!= ERROR_SUCCESS
)
464 /* Check for the DependOnService Value */
465 dwError
= RegQueryValueExW(hServiceEnumKey
,
469 (LPBYTE
)lpszValueBuf
,
472 /* FIXME: Handle load order. */
474 /* If the service found has a DependOnService value */
475 if (dwError
== ERROR_SUCCESS
)
477 dwDependServiceStrPtr
= 0;
479 /* Can be more than one Dependencies in the DependOnService string */
480 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
482 if (_wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
484 /* Get the current enumed service pointer */
485 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
487 /* Check for valid Service */
488 if (!lpCurrentService
)
490 /* This should never happen! */
491 DPRINT("This should not happen at this point, report to Developer\n");
492 return ERROR_NOT_FOUND
;
495 /* Determine state the service is in */
496 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
497 dwCurrentServiceState
= SERVICE_INACTIVE
;
499 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
500 if ((dwCurrentServiceState
== dwServiceState
) ||
501 (dwServiceState
== SERVICE_STATE_ALL
))
503 /* Calculate the required size */
504 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
505 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
506 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
508 /* Add the size for service name and display name pointers */
509 dwRequiredSize
+= (2 * sizeof(PVOID
));
511 /* increase the BytesNeeded size */
512 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
514 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
517 /* Recursive call to check for its dependencies */
518 Int_EnumDependentServicesW(hServicesKey
,
525 /* If the lpServices is valid set the service pointer */
527 lpServices
[*lpServicesReturned
] = lpCurrentService
;
529 *lpServicesReturned
= *lpServicesReturned
+ 1;
533 dwDependServiceStrPtr
+= (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
536 else if (*pcbBytesNeeded
)
538 dwError
= ERROR_SUCCESS
;
541 RegCloseKey(hServiceEnumKey
);
549 DWORD
RCloseServiceHandle(
550 LPSC_RPC_HANDLE hSCObject
)
552 PMANAGER_HANDLE hManager
;
553 PSERVICE_HANDLE hService
;
557 DWORD pcbBytesNeeded
= 0;
558 DWORD dwServicesReturned
= 0;
560 DPRINT("RCloseServiceHandle() called\n");
562 DPRINT("hSCObject = %p\n", *hSCObject
);
565 return ERROR_INVALID_HANDLE
;
567 hManager
= ScmGetServiceManagerFromHandle(*hSCObject
);
568 hService
= ScmGetServiceFromHandle(*hSCObject
);
570 if (hManager
!= NULL
)
572 DPRINT("Found manager handle\n");
574 /* FIXME: add handle cleanup code */
576 HeapFree(GetProcessHeap(), 0, hManager
);
581 DPRINT("RCloseServiceHandle() done\n");
582 return ERROR_SUCCESS
;
584 else if (hService
!= NULL
)
586 DPRINT("Found service handle\n");
588 /* Lock the service database exlusively */
589 ScmLockDatabaseExclusive();
591 /* Get the pointer to the service record */
592 lpService
= hService
->ServiceEntry
;
594 /* FIXME: add handle cleanup code */
596 /* Free the handle */
597 HeapFree(GetProcessHeap(), 0, hService
);
600 ASSERT(lpService
->dwRefCount
> 0);
602 lpService
->dwRefCount
--;
603 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
604 lpService
->dwRefCount
);
606 if (lpService
->dwRefCount
== 0)
608 /* If this service has been marked for deletion */
609 if (lpService
->bDeleted
)
611 /* Open the Services Reg key */
612 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
613 L
"System\\CurrentControlSet\\Services",
615 KEY_SET_VALUE
| KEY_READ
,
617 if (dwError
!= ERROR_SUCCESS
)
619 DPRINT("Failed to open services key\n");
624 /* Call the internal function with NULL, just to get bytes we need */
625 Int_EnumDependentServicesW(hServicesKey
,
630 &dwServicesReturned
);
632 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service */
635 DPRINT("Deletion failed due to running dependencies.\n");
636 RegCloseKey(hServicesKey
);
638 return ERROR_SUCCESS
;
641 /* There are no references and no runnning dependencies,
642 it is now safe to delete the service */
644 /* Delete the Service Key */
645 dwError
= RegDeleteKeyW(hServicesKey
,
646 lpService
->lpServiceName
);
648 RegCloseKey(hServicesKey
);
650 if (dwError
!= ERROR_SUCCESS
)
652 DPRINT("Failed to Delete the Service Registry key\n");
657 /* Delete the Service */
658 ScmDeleteServiceRecord(lpService
);
666 DPRINT("RCloseServiceHandle() done\n");
667 return ERROR_SUCCESS
;
670 DPRINT("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
672 return ERROR_INVALID_HANDLE
;
677 DWORD
RControlService(
678 SC_RPC_HANDLE hService
,
680 LPSERVICE_STATUS lpServiceStatus
)
682 PSERVICE_HANDLE hSvc
;
684 ACCESS_MASK DesiredAccess
;
685 DWORD dwError
= ERROR_SUCCESS
;
686 DWORD pcbBytesNeeded
= 0;
687 DWORD dwServicesReturned
= 0;
688 DWORD dwControlsAccepted
;
689 DWORD dwCurrentState
;
690 HKEY hServicesKey
= NULL
;
692 DPRINT("RControlService() called\n");
695 return ERROR_SHUTDOWN_IN_PROGRESS
;
697 /* Check the service handle */
698 hSvc
= ScmGetServiceFromHandle(hService
);
701 DPRINT1("Invalid service handle!\n");
702 return ERROR_INVALID_HANDLE
;
706 /* Check the service entry point */
707 lpService
= hSvc
->ServiceEntry
;
708 if (lpService
== NULL
)
710 DPRINT1("lpService == NULL!\n");
711 return ERROR_INVALID_HANDLE
;
714 /* Check access rights */
717 case SERVICE_CONTROL_STOP
:
718 DesiredAccess
= SERVICE_STOP
;
721 case SERVICE_CONTROL_PAUSE
:
722 case SERVICE_CONTROL_CONTINUE
:
723 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
726 case SERVICE_INTERROGATE
:
727 DesiredAccess
= SERVICE_INTERROGATE
;
731 if (dwControl
>= 128 && dwControl
<= 255)
732 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
734 return ERROR_INVALID_PARAMETER
;
738 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
740 return ERROR_ACCESS_DENIED
;
742 if (dwControl
== SERVICE_CONTROL_STOP
)
744 /* Check if the service has dependencies running as windows
745 doesn't stop a service that does */
747 /* Open the Services Reg key */
748 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
749 L
"System\\CurrentControlSet\\Services",
753 if (dwError
!= ERROR_SUCCESS
)
755 DPRINT("Failed to open services key\n");
759 /* Call the internal function with NULL, just to get bytes we need */
760 Int_EnumDependentServicesW(hServicesKey
,
765 &dwServicesReturned
);
767 RegCloseKey(hServicesKey
);
769 /* If pcbBytesNeeded is not zero then there are services running that
770 are dependent on this service */
771 if (pcbBytesNeeded
!= 0)
773 DPRINT("Service has running dependencies. Failed to stop service.\n");
774 return ERROR_DEPENDENT_SERVICES_RUNNING
;
778 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
780 /* Send control code to the driver */
781 dwError
= ScmControlDriver(lpService
,
787 dwControlsAccepted
= lpService
->Status
.dwControlsAccepted
;
788 dwCurrentState
= lpService
->Status
.dwCurrentState
;
790 /* Check the current state before sending a control request */
791 switch (dwCurrentState
)
793 case SERVICE_STOP_PENDING
:
794 case SERVICE_STOPPED
:
795 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
797 case SERVICE_START_PENDING
:
800 case SERVICE_CONTROL_STOP
:
803 case SERVICE_CONTROL_INTERROGATE
:
804 RtlCopyMemory(lpServiceStatus
,
806 sizeof(SERVICE_STATUS
));
807 return ERROR_SUCCESS
;
810 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
815 /* Check if the control code is acceptable to the service */
818 case SERVICE_CONTROL_STOP
:
819 if ((dwControlsAccepted
& SERVICE_ACCEPT_STOP
) == 0)
820 return ERROR_INVALID_SERVICE_CONTROL
;
823 case SERVICE_CONTROL_PAUSE
:
824 case SERVICE_CONTROL_CONTINUE
:
825 if ((dwControlsAccepted
& SERVICE_ACCEPT_PAUSE_CONTINUE
) == 0)
826 return ERROR_INVALID_SERVICE_CONTROL
;
830 /* Send control code to the service */
831 dwError
= ScmControlService(lpService
,
834 /* Return service status information */
835 RtlCopyMemory(lpServiceStatus
,
837 sizeof(SERVICE_STATUS
));
840 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
841 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
848 DWORD
RDeleteService(
849 SC_RPC_HANDLE hService
)
851 PSERVICE_HANDLE hSvc
;
855 DPRINT("RDeleteService() called\n");
858 return ERROR_SHUTDOWN_IN_PROGRESS
;
860 hSvc
= ScmGetServiceFromHandle(hService
);
863 DPRINT1("Invalid service handle!\n");
864 return ERROR_INVALID_HANDLE
;
867 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
869 return ERROR_ACCESS_DENIED
;
871 lpService
= hSvc
->ServiceEntry
;
872 if (lpService
== NULL
)
874 DPRINT("lpService == NULL!\n");
875 return ERROR_INVALID_HANDLE
;
878 /* Lock the service database exclusively */
879 ScmLockDatabaseExclusive();
881 if (lpService
->bDeleted
)
883 DPRINT("The service has already been marked for delete!\n");
884 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
888 /* Mark service for delete */
889 lpService
->bDeleted
= TRUE
;
891 dwError
= ScmMarkServiceForDelete(lpService
);
894 /* Unlock the service database */
897 DPRINT("RDeleteService() done\n");
904 DWORD
RLockServiceDatabase(
905 SC_RPC_HANDLE hSCManager
,
906 LPSC_RPC_LOCK lpLock
)
908 PMANAGER_HANDLE hMgr
;
910 DPRINT("RLockServiceDatabase() called\n");
914 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
917 DPRINT1("Invalid service manager handle!\n");
918 return ERROR_INVALID_HANDLE
;
921 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
923 return ERROR_ACCESS_DENIED
;
925 // return ScmLockDatabase(0, hMgr->0xC, hLock);
927 /* FIXME: Lock the database */
928 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
930 return ERROR_SUCCESS
;
935 DWORD
RQueryServiceObjectSecurity(
936 SC_RPC_HANDLE hService
,
937 SECURITY_INFORMATION dwSecurityInformation
,
938 LPBYTE lpSecurityDescriptor
,
940 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
942 PSERVICE_HANDLE hSvc
;
944 ULONG DesiredAccess
= 0;
950 SECURITY_DESCRIPTOR ObjectDescriptor
;
952 DPRINT("RQueryServiceObjectSecurity() called\n");
954 hSvc
= ScmGetServiceFromHandle(hService
);
957 DPRINT1("Invalid service handle!\n");
958 return ERROR_INVALID_HANDLE
;
961 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
|
962 GROUP_SECURITY_INFORMATION
|
963 OWNER_SECURITY_INFORMATION
))
964 DesiredAccess
|= READ_CONTROL
;
966 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
967 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
969 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
972 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
973 return ERROR_ACCESS_DENIED
;
976 lpService
= hSvc
->ServiceEntry
;
977 if (lpService
== NULL
)
979 DPRINT("lpService == NULL!\n");
980 return ERROR_INVALID_HANDLE
;
983 /* Lock the service database */
984 ScmLockDatabaseShared();
988 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
990 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
991 dwSecurityInformation
,
992 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
996 /* Unlock the service database */
999 if (NT_SUCCESS(Status
))
1001 *pcbBytesNeeded
= dwBytesNeeded
;
1002 dwError
= STATUS_SUCCESS
;
1004 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
1006 *pcbBytesNeeded
= dwBytesNeeded
;
1007 dwError
= ERROR_INSUFFICIENT_BUFFER
;
1009 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
1011 dwError
= ERROR_GEN_FAILURE
;
1015 dwError
= RtlNtStatusToDosError(Status
);
1023 DWORD
RSetServiceObjectSecurity(
1024 SC_RPC_HANDLE hService
,
1025 DWORD dwSecurityInformation
,
1026 LPBYTE lpSecurityDescriptor
,
1027 DWORD dwSecuityDescriptorSize
)
1029 PSERVICE_HANDLE hSvc
;
1031 ULONG DesiredAccess
= 0;
1032 /* HANDLE hToken = NULL; */
1034 /* NTSTATUS Status; */
1037 DPRINT("RSetServiceObjectSecurity() called\n");
1039 hSvc
= ScmGetServiceFromHandle(hService
);
1042 DPRINT1("Invalid service handle!\n");
1043 return ERROR_INVALID_HANDLE
;
1046 if (dwSecurityInformation
== 0 ||
1047 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
1048 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
1049 return ERROR_INVALID_PARAMETER
;
1051 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
1052 return ERROR_INVALID_PARAMETER
;
1054 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
1055 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
1057 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
1058 DesiredAccess
|= WRITE_DAC
;
1060 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
1061 DesiredAccess
|= WRITE_OWNER
;
1063 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
1064 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
1065 return ERROR_INVALID_PARAMETER
;
1067 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
1068 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
1069 return ERROR_INVALID_PARAMETER
;
1071 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1074 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1075 return ERROR_ACCESS_DENIED
;
1078 lpService
= hSvc
->ServiceEntry
;
1079 if (lpService
== NULL
)
1081 DPRINT("lpService == NULL!\n");
1082 return ERROR_INVALID_HANDLE
;
1085 if (lpService
->bDeleted
)
1086 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1089 RpcImpersonateClient(NULL
);
1091 Status
= NtOpenThreadToken(NtCurrentThread(),
1095 if (!NT_SUCCESS(Status
))
1096 return RtlNtStatusToDosError(Status
);
1101 /* Lock the service database exclusive */
1102 ScmLockDatabaseExclusive();
1105 Status
= RtlSetSecurityObject(dwSecurityInformation
,
1106 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
1107 &lpService
->lpSecurityDescriptor
,
1110 if (!NT_SUCCESS(Status
))
1112 dwError
= RtlNtStatusToDosError(Status
);
1117 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
1118 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
1120 if (dwError
!= ERROR_SUCCESS
)
1124 dwError
= ERROR_SUCCESS
;
1125 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
1126 // lpService->lpSecurityDescriptor);
1128 RegFlushKey(hServiceKey
);
1129 RegCloseKey(hServiceKey
);
1138 /* Unlock service database */
1139 ScmUnlockDatabase();
1141 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1148 DWORD
RQueryServiceStatus(
1149 SC_RPC_HANDLE hService
,
1150 LPSERVICE_STATUS lpServiceStatus
)
1152 PSERVICE_HANDLE hSvc
;
1155 DPRINT("RQueryServiceStatus() called\n");
1158 return ERROR_SHUTDOWN_IN_PROGRESS
;
1160 hSvc
= ScmGetServiceFromHandle(hService
);
1163 DPRINT1("Invalid service handle!\n");
1164 return ERROR_INVALID_HANDLE
;
1167 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1168 SERVICE_QUERY_STATUS
))
1170 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1171 return ERROR_ACCESS_DENIED
;
1174 lpService
= hSvc
->ServiceEntry
;
1175 if (lpService
== NULL
)
1177 DPRINT("lpService == NULL!\n");
1178 return ERROR_INVALID_HANDLE
;
1181 /* Lock the service database shared */
1182 ScmLockDatabaseShared();
1184 /* Return service status information */
1185 RtlCopyMemory(lpServiceStatus
,
1187 sizeof(SERVICE_STATUS
));
1189 /* Unlock the service database */
1190 ScmUnlockDatabase();
1192 return ERROR_SUCCESS
;
1197 ScmIsValidServiceState(DWORD dwCurrentState
)
1199 switch (dwCurrentState
)
1201 case SERVICE_STOPPED
:
1202 case SERVICE_START_PENDING
:
1203 case SERVICE_STOP_PENDING
:
1204 case SERVICE_RUNNING
:
1205 case SERVICE_CONTINUE_PENDING
:
1206 case SERVICE_PAUSE_PENDING
:
1207 case SERVICE_PAUSED
:
1217 DWORD
RSetServiceStatus(
1218 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1219 LPSERVICE_STATUS lpServiceStatus
)
1223 DPRINT("RSetServiceStatus() called\n");
1224 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1225 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1226 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1227 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1228 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1229 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1230 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1231 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1233 if (hServiceStatus
== 0)
1235 DPRINT("hServiceStatus == NULL!\n");
1236 return ERROR_INVALID_HANDLE
;
1239 lpService
= (PSERVICE
)hServiceStatus
;
1240 if (lpService
== NULL
)
1242 DPRINT("lpService == NULL!\n");
1243 return ERROR_INVALID_HANDLE
;
1246 /* Check current state */
1247 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1249 DPRINT("Invalid service state!\n");
1250 return ERROR_INVALID_DATA
;
1253 /* Check service type */
1254 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1255 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1257 DPRINT("Invalid service type!\n");
1258 return ERROR_INVALID_DATA
;
1261 /* Check accepted controls */
1262 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1264 DPRINT("Invalid controls accepted!\n");
1265 return ERROR_INVALID_DATA
;
1268 /* Lock the service database exclusively */
1269 ScmLockDatabaseExclusive();
1271 RtlCopyMemory(&lpService
->Status
,
1273 sizeof(SERVICE_STATUS
));
1275 /* Unlock the service database */
1276 ScmUnlockDatabase();
1278 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1279 DPRINT("RSetServiceStatus() done\n");
1281 return ERROR_SUCCESS
;
1286 DWORD
RUnlockServiceDatabase(
1290 return ERROR_SUCCESS
;
1295 DWORD
RNotifyBootConfigStatus(
1296 SVCCTL_HANDLEW lpMachineName
,
1297 DWORD BootAcceptable
)
1299 DPRINT1("RNotifyBootConfigStatus(%p %lu) called\n", lpMachineName
, BootAcceptable
);
1300 return ERROR_SUCCESS
;
1303 // return ERROR_CALL_NOT_IMPLEMENTED;
1308 DWORD
RI_ScSetServiceBitsW(
1309 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1310 DWORD dwServiceBits
,
1312 int bUpdateImmediately
,
1316 return ERROR_CALL_NOT_IMPLEMENTED
;
1321 DWORD
RChangeServiceConfigW(
1322 SC_RPC_HANDLE hService
,
1323 DWORD dwServiceType
,
1325 DWORD dwErrorControl
,
1326 LPWSTR lpBinaryPathName
,
1327 LPWSTR lpLoadOrderGroup
,
1329 LPBYTE lpDependencies
,
1331 LPWSTR lpServiceStartName
,
1334 LPWSTR lpDisplayName
)
1336 DWORD dwError
= ERROR_SUCCESS
;
1337 PSERVICE_HANDLE hSvc
;
1338 PSERVICE lpService
= NULL
;
1339 HKEY hServiceKey
= NULL
;
1340 LPWSTR lpDisplayNameW
= NULL
;
1342 DPRINT("RChangeServiceConfigW() called\n");
1343 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1344 DPRINT("dwStartType = %lu\n", dwStartType
);
1345 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1346 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1347 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1348 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1351 return ERROR_SHUTDOWN_IN_PROGRESS
;
1353 hSvc
= ScmGetServiceFromHandle(hService
);
1356 DPRINT1("Invalid service handle!\n");
1357 return ERROR_INVALID_HANDLE
;
1360 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1361 SERVICE_CHANGE_CONFIG
))
1363 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1364 return ERROR_ACCESS_DENIED
;
1367 lpService
= hSvc
->ServiceEntry
;
1368 if (lpService
== NULL
)
1370 DPRINT("lpService == NULL!\n");
1371 return ERROR_INVALID_HANDLE
;
1374 /* Lock the service database exclusively */
1375 ScmLockDatabaseExclusive();
1377 if (lpService
->bDeleted
)
1379 DPRINT("The service has already been marked for delete!\n");
1380 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1384 /* Open the service key */
1385 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1388 if (dwError
!= ERROR_SUCCESS
)
1391 /* Write service data to the registry */
1392 /* Set the display name */
1393 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1395 RegSetValueExW(hServiceKey
,
1399 (LPBYTE
)lpDisplayName
,
1400 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1402 /* Update the display name */
1403 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
1405 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1406 if (lpDisplayNameW
== NULL
)
1408 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1412 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1413 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1415 lpService
->lpDisplayName
= lpDisplayNameW
;
1418 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1420 /* Set the service type */
1421 dwError
= RegSetValueExW(hServiceKey
,
1425 (LPBYTE
)&dwServiceType
,
1427 if (dwError
!= ERROR_SUCCESS
)
1430 lpService
->Status
.dwServiceType
= dwServiceType
;
1433 if (dwStartType
!= SERVICE_NO_CHANGE
)
1435 /* Set the start value */
1436 dwError
= RegSetValueExW(hServiceKey
,
1440 (LPBYTE
)&dwStartType
,
1442 if (dwError
!= ERROR_SUCCESS
)
1445 lpService
->dwStartType
= dwStartType
;
1448 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1450 /* Set the error control value */
1451 dwError
= RegSetValueExW(hServiceKey
,
1455 (LPBYTE
)&dwErrorControl
,
1457 if (dwError
!= ERROR_SUCCESS
)
1460 lpService
->dwErrorControl
= dwErrorControl
;
1464 /* FIXME: set the new ImagePath value */
1466 /* Set the image path */
1467 if (dwServiceType
& SERVICE_WIN32
)
1469 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1471 dwError
= RegSetValueExW(hServiceKey
,
1475 (LPBYTE
)lpBinaryPathName
,
1476 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1477 if (dwError
!= ERROR_SUCCESS
)
1481 else if (dwServiceType
& SERVICE_DRIVER
)
1483 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1485 dwError
= RegSetValueExW(hServiceKey
,
1489 (LPBYTE
)lpImagePath
,
1490 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1491 if (dwError
!= ERROR_SUCCESS
)
1497 /* Set the group name */
1498 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1500 dwError
= RegSetValueExW(hServiceKey
,
1504 (LPBYTE
)lpLoadOrderGroup
,
1505 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1506 if (dwError
!= ERROR_SUCCESS
)
1509 dwError
= ScmSetServiceGroup(lpService
,
1511 if (dwError
!= ERROR_SUCCESS
)
1515 if (lpdwTagId
!= NULL
)
1517 dwError
= ScmAssignNewTag(lpService
);
1518 if (dwError
!= ERROR_SUCCESS
)
1521 dwError
= RegSetValueExW(hServiceKey
,
1525 (LPBYTE
)&lpService
->dwTag
,
1527 if (dwError
!= ERROR_SUCCESS
)
1530 *lpdwTagId
= lpService
->dwTag
;
1533 /* Write dependencies */
1534 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1536 dwError
= ScmWriteDependencies(hServiceKey
,
1537 (LPWSTR
)lpDependencies
,
1539 if (dwError
!= ERROR_SUCCESS
)
1543 if (lpPassword
!= NULL
)
1545 /* FIXME: Write password */
1549 if (hServiceKey
!= NULL
)
1550 RegCloseKey(hServiceKey
);
1552 /* Unlock the service database */
1553 ScmUnlockDatabase();
1555 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1561 /* Create a path suitable for the bootloader out of the full path */
1563 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1565 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1568 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1569 OBJECT_ATTRIBUTES ObjectAttributes
;
1571 HANDLE SymbolicLinkHandle
;
1573 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1575 ServiceNameLen
= wcslen(CanonName
);
1577 /* First check, if it's already good */
1578 if (ServiceNameLen
> 12 &&
1579 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1581 *RelativeName
= HeapAlloc(GetProcessHeap(),
1583 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
1584 if (*RelativeName
== NULL
)
1586 DPRINT("Error allocating memory for boot driver name!\n");
1587 return ERROR_NOT_ENOUGH_MEMORY
;
1591 wcscpy(*RelativeName
, CanonName
);
1593 DPRINT("Bootdriver name %S\n", *RelativeName
);
1594 return ERROR_SUCCESS
;
1597 /* If it has %SystemRoot% prefix, substitute it to \System*/
1598 if (ServiceNameLen
> 13 &&
1599 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1601 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1602 *RelativeName
= HeapAlloc(GetProcessHeap(),
1604 ServiceNameLen
* sizeof(WCHAR
));
1606 if (*RelativeName
== NULL
)
1608 DPRINT("Error allocating memory for boot driver name!\n");
1609 return ERROR_NOT_ENOUGH_MEMORY
;
1613 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1614 wcscat(*RelativeName
, CanonName
+ 13);
1616 DPRINT("Bootdriver name %S\n", *RelativeName
);
1617 return ERROR_SUCCESS
;
1620 /* Get buffer size needed for expanding env strings */
1621 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1623 if (BufferSize
<= 1)
1625 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1626 return ERROR_INVALID_ENVIRONMENT
;
1629 /* Allocate memory, since the size is known now */
1630 Expanded
= HeapAlloc(GetProcessHeap(),
1632 (BufferSize
+ 1) * sizeof(WCHAR
));
1635 DPRINT("Error allocating memory for boot driver name!\n");
1636 return ERROR_NOT_ENOUGH_MEMORY
;
1640 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1643 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1644 HeapFree(GetProcessHeap(), 0, Expanded
);
1645 return ERROR_NOT_ENOUGH_MEMORY
;
1648 /* Convert to NY-style path */
1649 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1651 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1652 return ERROR_INVALID_ENVIRONMENT
;
1655 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1657 /* No need to keep the dos-path anymore */
1658 HeapFree(GetProcessHeap(), 0, Expanded
);
1660 /* Copy it to the allocated place */
1661 Expanded
= HeapAlloc(GetProcessHeap(),
1663 NtPathName
.Length
+ sizeof(UNICODE_NULL
));
1666 DPRINT("Error allocating memory for boot driver name!\n");
1667 return ERROR_NOT_ENOUGH_MEMORY
;
1670 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1671 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1672 Expanded
[ExpandedLen
] = UNICODE_NULL
;
1674 if (ServiceNameLen
> ExpandedLen
&&
1675 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1677 /* Only \SystemRoot\ is missing */
1678 *RelativeName
= HeapAlloc(GetProcessHeap(),
1680 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1681 if (*RelativeName
== NULL
)
1683 DPRINT("Error allocating memory for boot driver name!\n");
1684 HeapFree(GetProcessHeap(), 0, Expanded
);
1685 return ERROR_NOT_ENOUGH_MEMORY
;
1688 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1689 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1691 RtlFreeUnicodeString(&NtPathName
);
1692 return ERROR_SUCCESS
;
1695 /* The most complex case starts here */
1696 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1697 InitializeObjectAttributes(&ObjectAttributes
,
1699 OBJ_CASE_INSENSITIVE
,
1703 /* Open this symlink */
1704 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1706 if (NT_SUCCESS(Status
))
1708 LinkTarget
.Length
= 0;
1709 LinkTarget
.MaximumLength
= 0;
1711 DPRINT("Opened symbolic link object\n");
1713 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1714 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1716 /* Check if required buffer size is sane */
1717 if (BufferSize
> 0xFFFD)
1719 DPRINT("Too large buffer required\n");
1722 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1723 HeapFree(GetProcessHeap(), 0, Expanded
);
1724 return ERROR_NOT_ENOUGH_MEMORY
;
1727 /* Alloc the string */
1728 LinkTarget
.Length
= (USHORT
)BufferSize
;
1729 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(UNICODE_NULL
);
1730 LinkTarget
.Buffer
= HeapAlloc(GetProcessHeap(),
1732 LinkTarget
.MaximumLength
);
1733 if (!LinkTarget
.Buffer
)
1735 DPRINT("Unable to alloc buffer\n");
1736 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1737 HeapFree(GetProcessHeap(), 0, Expanded
);
1738 return ERROR_NOT_ENOUGH_MEMORY
;
1741 /* Do a real query now */
1742 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1743 if (NT_SUCCESS(Status
))
1745 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1747 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1748 if ((ServiceNameLen
> ExpandedLen
) &&
1749 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1751 *RelativeName
= HeapAlloc(GetProcessHeap(),
1753 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1755 if (*RelativeName
== NULL
)
1757 DPRINT("Unable to alloc buffer\n");
1758 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1759 HeapFree(GetProcessHeap(), 0, Expanded
);
1760 RtlFreeUnicodeString(&NtPathName
);
1761 return ERROR_NOT_ENOUGH_MEMORY
;
1764 /* Copy it over, substituting the first part
1766 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1767 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1770 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1771 HeapFree(GetProcessHeap(), 0, Expanded
);
1772 RtlFreeUnicodeString(&NtPathName
);
1774 /* Return success */
1775 return ERROR_SUCCESS
;
1779 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1780 HeapFree(GetProcessHeap(), 0, Expanded
);
1781 RtlFreeUnicodeString(&NtPathName
);
1782 return ERROR_INVALID_PARAMETER
;
1787 DPRINT("Error, Status = %08X\n", Status
);
1788 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1789 HeapFree(GetProcessHeap(), 0, Expanded
);
1790 RtlFreeUnicodeString(&NtPathName
);
1791 return ERROR_INVALID_PARAMETER
;
1796 DPRINT("Error, Status = %08X\n", Status
);
1797 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1798 HeapFree(GetProcessHeap(), 0, Expanded
);
1799 RtlFreeUnicodeString(&NtPathName
);
1800 return ERROR_INVALID_PARAMETER
;
1805 DPRINT("Error, Status = %08X\n", Status
);
1806 HeapFree(GetProcessHeap(), 0, Expanded
);
1807 return ERROR_INVALID_PARAMETER
;
1811 *RelativeName
= NULL
;
1812 return ERROR_INVALID_PARAMETER
;
1816 ScmCanonDriverImagePath(DWORD dwStartType
,
1817 const wchar_t *lpServiceName
,
1818 wchar_t **lpCanonName
)
1820 DWORD ServiceNameLen
, Result
;
1821 UNICODE_STRING NtServiceName
;
1822 WCHAR
*RelativeName
;
1823 const WCHAR
*SourceName
= lpServiceName
;
1825 /* Calculate the length of the service's name */
1826 ServiceNameLen
= wcslen(lpServiceName
);
1828 /* 12 is wcslen(L"\\SystemRoot\\") */
1829 if (ServiceNameLen
> 12 &&
1830 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1832 /* SystemRoot prefix is already included */
1833 *lpCanonName
= HeapAlloc(GetProcessHeap(),
1835 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
1837 if (*lpCanonName
== NULL
)
1839 DPRINT("Error allocating memory for canonized service name!\n");
1840 return ERROR_NOT_ENOUGH_MEMORY
;
1843 /* If it's a boot-time driver, it must be systemroot relative */
1844 if (dwStartType
== SERVICE_BOOT_START
)
1848 wcscpy(*lpCanonName
, SourceName
);
1850 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1854 /* Check if it has %SystemRoot% (len=13) */
1855 if (ServiceNameLen
> 13 &&
1856 !_wcsnicmp(L
"%SystemRoot%\\", lpServiceName
, 13))
1858 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1859 *lpCanonName
= HeapAlloc(GetProcessHeap(),
1861 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
1863 if (*lpCanonName
== NULL
)
1865 DPRINT("Error allocating memory for canonized service name!\n");
1866 return ERROR_NOT_ENOUGH_MEMORY
;
1869 /* If it's a boot-time driver, it must be systemroot relative */
1870 if (dwStartType
== SERVICE_BOOT_START
)
1871 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1873 wcscat(*lpCanonName
, lpServiceName
+ 13);
1875 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1879 /* Check if it's a relative path name */
1880 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1882 *lpCanonName
= HeapAlloc(GetProcessHeap(),
1884 (ServiceNameLen
+ 1) * sizeof(WCHAR
));
1886 if (*lpCanonName
== NULL
)
1888 DPRINT("Error allocating memory for canonized service name!\n");
1889 return ERROR_NOT_ENOUGH_MEMORY
;
1892 /* Just copy it over without changing */
1893 wcscpy(*lpCanonName
, lpServiceName
);
1898 /* It seems to be a DOS path, convert it */
1899 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1901 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
1902 return ERROR_INVALID_PARAMETER
;
1905 *lpCanonName
= HeapAlloc(GetProcessHeap(),
1907 NtServiceName
.Length
+ sizeof(WCHAR
));
1909 if (*lpCanonName
== NULL
)
1911 DPRINT("Error allocating memory for canonized service name!\n");
1912 RtlFreeUnicodeString(&NtServiceName
);
1913 return ERROR_NOT_ENOUGH_MEMORY
;
1916 /* Copy the string */
1917 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1919 /* The unicode string is not needed anymore */
1920 RtlFreeUnicodeString(&NtServiceName
);
1922 if (dwStartType
!= SERVICE_BOOT_START
)
1924 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1928 /* The service is boot-started, so must be relative */
1929 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1932 /* There is a problem, free name and return */
1933 HeapFree(GetProcessHeap(), 0, *lpCanonName
);
1934 DPRINT("Error converting named!\n");
1938 ASSERT(RelativeName
);
1940 /* Copy that string */
1941 wcscpy(*lpCanonName
, RelativeName
+ 12);
1943 /* Free the allocated buffer */
1944 HeapFree(GetProcessHeap(), 0, RelativeName
);
1946 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1954 DWORD
RCreateServiceW(
1955 SC_RPC_HANDLE hSCManager
,
1956 LPCWSTR lpServiceName
,
1957 LPCWSTR lpDisplayName
,
1958 DWORD dwDesiredAccess
,
1959 DWORD dwServiceType
,
1961 DWORD dwErrorControl
,
1962 LPCWSTR lpBinaryPathName
,
1963 LPCWSTR lpLoadOrderGroup
,
1965 LPBYTE lpDependencies
,
1967 LPCWSTR lpServiceStartName
,
1970 LPSC_RPC_HANDLE lpServiceHandle
)
1972 PMANAGER_HANDLE hManager
;
1973 DWORD dwError
= ERROR_SUCCESS
;
1974 PSERVICE lpService
= NULL
;
1975 SC_HANDLE hServiceHandle
= NULL
;
1976 LPWSTR lpImagePath
= NULL
;
1977 HKEY hServiceKey
= NULL
;
1978 LPWSTR lpObjectName
;
1980 DPRINT("RCreateServiceW() called\n");
1981 DPRINT("lpServiceName = %S\n", lpServiceName
);
1982 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1983 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1984 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1985 DPRINT("dwStartType = %lu\n", dwStartType
);
1986 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1987 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1988 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1989 DPRINT("lpdwTagId = %p\n", lpdwTagId
);
1992 return ERROR_SHUTDOWN_IN_PROGRESS
;
1994 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
1995 if (hManager
== NULL
)
1997 DPRINT1("Invalid service manager handle!\n");
1998 return ERROR_INVALID_HANDLE
;
2001 /* Check access rights */
2002 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2003 SC_MANAGER_CREATE_SERVICE
))
2005 DPRINT("Insufficient access rights! 0x%lx\n",
2006 hManager
->Handle
.DesiredAccess
);
2007 return ERROR_ACCESS_DENIED
;
2010 if (wcslen(lpServiceName
) == 0)
2012 return ERROR_INVALID_NAME
;
2015 if (wcslen(lpBinaryPathName
) == 0)
2017 return ERROR_INVALID_PARAMETER
;
2020 /* Check for invalid service type value */
2021 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2022 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
) &&
2023 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_OWN_PROCESS
) &&
2024 ((dwServiceType
& ~SERVICE_INTERACTIVE_PROCESS
) != SERVICE_WIN32_SHARE_PROCESS
))
2025 return ERROR_INVALID_PARAMETER
;
2027 /* Check for invalid start type value */
2028 if ((dwStartType
!= SERVICE_BOOT_START
) &&
2029 (dwStartType
!= SERVICE_SYSTEM_START
) &&
2030 (dwStartType
!= SERVICE_AUTO_START
) &&
2031 (dwStartType
!= SERVICE_DEMAND_START
) &&
2032 (dwStartType
!= SERVICE_DISABLED
))
2033 return ERROR_INVALID_PARAMETER
;
2035 /* Only drivers can be boot start or system start services */
2036 if ((dwStartType
== SERVICE_BOOT_START
) ||
2037 (dwStartType
== SERVICE_SYSTEM_START
))
2039 if ((dwServiceType
!= SERVICE_KERNEL_DRIVER
) &&
2040 (dwServiceType
!= SERVICE_FILE_SYSTEM_DRIVER
))
2041 return ERROR_INVALID_PARAMETER
;
2044 /* Check for invalid error control value */
2045 if ((dwErrorControl
!= SERVICE_ERROR_IGNORE
) &&
2046 (dwErrorControl
!= SERVICE_ERROR_NORMAL
) &&
2047 (dwErrorControl
!= SERVICE_ERROR_SEVERE
) &&
2048 (dwErrorControl
!= SERVICE_ERROR_CRITICAL
))
2049 return ERROR_INVALID_PARAMETER
;
2051 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
2052 (lpServiceStartName
))
2054 return ERROR_INVALID_PARAMETER
;
2057 if (lpdwTagId
&& (!lpLoadOrderGroup
|| !*lpLoadOrderGroup
))
2059 return ERROR_INVALID_PARAMETER
;
2062 /* Lock the service database exclusively */
2063 ScmLockDatabaseExclusive();
2065 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2068 /* Unlock the service database */
2069 ScmUnlockDatabase();
2071 /* check if it is marked for deletion */
2072 if (lpService
->bDeleted
)
2073 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2074 /* Return Error exist */
2075 return ERROR_SERVICE_EXISTS
;
2078 if (lpDisplayName
!= NULL
&&
2079 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
2081 /* Unlock the service database */
2082 ScmUnlockDatabase();
2084 return ERROR_DUPLICATE_SERVICE_NAME
;
2087 if (dwServiceType
& SERVICE_DRIVER
)
2089 dwError
= ScmCanonDriverImagePath(dwStartType
,
2092 if (dwError
!= ERROR_SUCCESS
)
2097 if (dwStartType
== SERVICE_BOOT_START
||
2098 dwStartType
== SERVICE_SYSTEM_START
)
2100 /* Unlock the service database */
2101 ScmUnlockDatabase();
2103 return ERROR_INVALID_PARAMETER
;
2107 /* Allocate a new service entry */
2108 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
2110 if (dwError
!= ERROR_SUCCESS
)
2113 /* Fill the new service entry */
2114 lpService
->Status
.dwServiceType
= dwServiceType
;
2115 lpService
->dwStartType
= dwStartType
;
2116 lpService
->dwErrorControl
= dwErrorControl
;
2118 /* Fill the display name */
2119 if (lpDisplayName
!= NULL
&&
2120 *lpDisplayName
!= 0 &&
2121 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
2123 lpService
->lpDisplayName
= HeapAlloc(GetProcessHeap(), 0,
2124 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2125 if (lpService
->lpDisplayName
== NULL
)
2127 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2130 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
2133 /* Assign the service to a group */
2134 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2136 dwError
= ScmSetServiceGroup(lpService
,
2138 if (dwError
!= ERROR_SUCCESS
)
2142 /* Assign a new tag */
2143 if (lpdwTagId
!= NULL
)
2145 dwError
= ScmAssignNewTag(lpService
);
2146 if (dwError
!= ERROR_SUCCESS
)
2150 /* Write service data to the registry */
2151 /* Create the service key */
2152 dwError
= ScmCreateServiceKey(lpServiceName
,
2155 if (dwError
!= ERROR_SUCCESS
)
2158 /* Set the display name */
2159 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2161 RegSetValueExW(hServiceKey
,
2165 (LPBYTE
)lpDisplayName
,
2166 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2169 /* Set the service type */
2170 dwError
= RegSetValueExW(hServiceKey
,
2174 (LPBYTE
)&dwServiceType
,
2176 if (dwError
!= ERROR_SUCCESS
)
2179 /* Set the start value */
2180 dwError
= RegSetValueExW(hServiceKey
,
2184 (LPBYTE
)&dwStartType
,
2186 if (dwError
!= ERROR_SUCCESS
)
2189 /* Set the error control value */
2190 dwError
= RegSetValueExW(hServiceKey
,
2194 (LPBYTE
)&dwErrorControl
,
2196 if (dwError
!= ERROR_SUCCESS
)
2199 /* Set the image path */
2200 if (dwServiceType
& SERVICE_WIN32
)
2202 dwError
= RegSetValueExW(hServiceKey
,
2206 (LPBYTE
)lpBinaryPathName
,
2207 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
2208 if (dwError
!= ERROR_SUCCESS
)
2211 else if (dwServiceType
& SERVICE_DRIVER
)
2213 dwError
= RegSetValueExW(hServiceKey
,
2217 (LPBYTE
)lpImagePath
,
2218 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2219 if (dwError
!= ERROR_SUCCESS
)
2223 /* Set the group name */
2224 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2226 dwError
= RegSetValueExW(hServiceKey
,
2230 (LPBYTE
)lpLoadOrderGroup
,
2231 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
2232 if (dwError
!= ERROR_SUCCESS
)
2236 if (lpdwTagId
!= NULL
)
2238 dwError
= RegSetValueExW(hServiceKey
,
2242 (LPBYTE
)&lpService
->dwTag
,
2244 if (dwError
!= ERROR_SUCCESS
)
2248 /* Write dependencies */
2249 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2251 dwError
= ScmWriteDependencies(hServiceKey
,
2252 (LPCWSTR
)lpDependencies
,
2254 if (dwError
!= ERROR_SUCCESS
)
2258 /* Write service start name */
2259 if (dwServiceType
& SERVICE_WIN32
)
2261 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2262 dwError
= RegSetValueExW(hServiceKey
,
2266 (LPBYTE
)lpObjectName
,
2267 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
2268 if (dwError
!= ERROR_SUCCESS
)
2272 if (lpPassword
!= NULL
)
2274 /* FIXME: Write password */
2277 dwError
= ScmCreateServiceHandle(lpService
,
2279 if (dwError
!= ERROR_SUCCESS
)
2282 dwError
= ScmCheckAccess(hServiceHandle
,
2284 if (dwError
!= ERROR_SUCCESS
)
2287 lpService
->dwRefCount
= 1;
2288 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2291 /* Unlock the service database */
2292 ScmUnlockDatabase();
2294 if (hServiceKey
!= NULL
)
2295 RegCloseKey(hServiceKey
);
2297 if (dwError
== ERROR_SUCCESS
)
2299 DPRINT("hService %p\n", hServiceHandle
);
2300 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2302 if (lpdwTagId
!= NULL
)
2303 *lpdwTagId
= lpService
->dwTag
;
2307 if (lpService
!= NULL
&&
2308 lpService
->lpServiceName
!= NULL
)
2310 /* Release the display name buffer */
2311 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2316 /* Remove the service handle */
2317 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2320 if (lpService
!= NULL
)
2322 /* FIXME: remove the service entry */
2326 if (lpImagePath
!= NULL
)
2327 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2329 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2336 DWORD
REnumDependentServicesW(
2337 SC_RPC_HANDLE hService
,
2338 DWORD dwServiceState
,
2341 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2342 LPBOUNDED_DWORD_256K lpServicesReturned
)
2344 DWORD dwError
= ERROR_SUCCESS
;
2345 DWORD dwServicesReturned
= 0;
2346 DWORD dwServiceCount
;
2347 HKEY hServicesKey
= NULL
;
2348 PSERVICE_HANDLE hSvc
;
2349 PSERVICE lpService
= NULL
;
2350 PSERVICE
*lpServicesArray
= NULL
;
2351 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2354 *pcbBytesNeeded
= 0;
2355 *lpServicesReturned
= 0;
2357 DPRINT("REnumDependentServicesW() called\n");
2359 hSvc
= ScmGetServiceFromHandle(hService
);
2362 DPRINT1("Invalid service handle!\n");
2363 return ERROR_INVALID_HANDLE
;
2366 lpService
= hSvc
->ServiceEntry
;
2368 /* Check access rights */
2369 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2370 SC_MANAGER_ENUMERATE_SERVICE
))
2372 DPRINT("Insufficient access rights! 0x%lx\n",
2373 hSvc
->Handle
.DesiredAccess
);
2374 return ERROR_ACCESS_DENIED
;
2377 /* Open the Services Reg key */
2378 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2379 L
"System\\CurrentControlSet\\Services",
2383 if (dwError
!= ERROR_SUCCESS
)
2386 /* First determine the bytes needed and get the number of dependent services */
2387 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2392 &dwServicesReturned
);
2393 if (dwError
!= ERROR_SUCCESS
)
2396 /* If buffer size is less than the bytes needed or pointer is null */
2397 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2399 dwError
= ERROR_MORE_DATA
;
2403 /* Allocate memory for array of service pointers */
2404 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2406 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2407 if (!lpServicesArray
)
2409 DPRINT1("Could not allocate a buffer!!\n");
2410 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2414 dwServicesReturned
= 0;
2415 *pcbBytesNeeded
= 0;
2417 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2422 &dwServicesReturned
);
2423 if (dwError
!= ERROR_SUCCESS
)
2428 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2429 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2431 /* Copy EnumDepenedentService to Buffer */
2432 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2434 lpService
= lpServicesArray
[dwServiceCount
];
2436 /* Copy status info */
2437 memcpy(&lpServicesPtr
->ServiceStatus
,
2439 sizeof(SERVICE_STATUS
));
2441 /* Copy display name */
2442 wcscpy(lpStr
, lpService
->lpDisplayName
);
2443 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2444 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2446 /* Copy service name */
2447 wcscpy(lpStr
, lpService
->lpServiceName
);
2448 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2449 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2454 *lpServicesReturned
= dwServicesReturned
;
2457 if (lpServicesArray
!= NULL
)
2458 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2460 RegCloseKey(hServicesKey
);
2462 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2469 DWORD
REnumServicesStatusW(
2470 SC_RPC_HANDLE hSCManager
,
2471 DWORD dwServiceType
,
2472 DWORD dwServiceState
,
2475 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2476 LPBOUNDED_DWORD_256K lpServicesReturned
,
2477 LPBOUNDED_DWORD_256K lpResumeHandle
)
2479 PMANAGER_HANDLE hManager
;
2481 DWORD dwError
= ERROR_SUCCESS
;
2482 PLIST_ENTRY ServiceEntry
;
2483 PSERVICE CurrentService
;
2485 DWORD dwRequiredSize
;
2486 DWORD dwServiceCount
;
2488 DWORD dwLastResumeCount
= 0;
2489 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2492 DPRINT("REnumServicesStatusW() called\n");
2495 return ERROR_SHUTDOWN_IN_PROGRESS
;
2497 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2498 if (hManager
== NULL
)
2500 DPRINT1("Invalid service manager handle!\n");
2501 return ERROR_INVALID_HANDLE
;
2505 *pcbBytesNeeded
= 0;
2506 *lpServicesReturned
= 0;
2508 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2510 DPRINT("Not a valid Service Type!\n");
2511 return ERROR_INVALID_PARAMETER
;
2514 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2516 DPRINT("Not a valid Service State!\n");
2517 return ERROR_INVALID_PARAMETER
;
2520 /* Check access rights */
2521 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2522 SC_MANAGER_ENUMERATE_SERVICE
))
2524 DPRINT("Insufficient access rights! 0x%lx\n",
2525 hManager
->Handle
.DesiredAccess
);
2526 return ERROR_ACCESS_DENIED
;
2530 dwLastResumeCount
= *lpResumeHandle
;
2532 /* Lock the service database shared */
2533 ScmLockDatabaseShared();
2535 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2536 if (lpService
== NULL
)
2538 dwError
= ERROR_SUCCESS
;
2545 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2546 ServiceEntry
!= &ServiceListHead
;
2547 ServiceEntry
= ServiceEntry
->Flink
)
2549 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2553 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2556 dwState
= SERVICE_ACTIVE
;
2557 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2558 dwState
= SERVICE_INACTIVE
;
2560 if ((dwState
& dwServiceState
) == 0)
2563 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2564 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2565 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2567 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2569 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2573 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2574 dwRequiredSize
+= dwSize
;
2576 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2579 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2580 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2583 ServiceEntry
!= &ServiceListHead
;
2584 ServiceEntry
= ServiceEntry
->Flink
)
2586 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2590 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2593 dwState
= SERVICE_ACTIVE
;
2594 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2595 dwState
= SERVICE_INACTIVE
;
2597 if ((dwState
& dwServiceState
) == 0)
2600 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2601 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2602 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2604 dwError
= ERROR_MORE_DATA
;
2607 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2610 *lpResumeHandle
= dwLastResumeCount
;
2612 *lpServicesReturned
= dwServiceCount
;
2613 *pcbBytesNeeded
= dwRequiredSize
;
2615 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2616 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2617 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2620 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2621 ServiceEntry
!= &ServiceListHead
;
2622 ServiceEntry
= ServiceEntry
->Flink
)
2624 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2628 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2631 dwState
= SERVICE_ACTIVE
;
2632 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2633 dwState
= SERVICE_INACTIVE
;
2635 if ((dwState
& dwServiceState
) == 0)
2638 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2639 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2640 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2642 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2645 /* Copy the service name */
2646 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2647 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2648 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2650 /* Copy the display name */
2651 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2652 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2653 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2655 /* Copy the status information */
2656 memcpy(&lpStatusPtr
->ServiceStatus
,
2657 &CurrentService
->Status
,
2658 sizeof(SERVICE_STATUS
));
2661 dwRequiredSize
+= dwSize
;
2666 *pcbBytesNeeded
= 0;
2667 if (lpResumeHandle
) *lpResumeHandle
= 0;
2671 /* Unlock the service database */
2672 ScmUnlockDatabase();
2674 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2681 DWORD
ROpenSCManagerW(
2682 LPWSTR lpMachineName
,
2683 LPWSTR lpDatabaseName
,
2684 DWORD dwDesiredAccess
,
2685 LPSC_RPC_HANDLE lpScHandle
)
2690 DPRINT("ROpenSCManagerW() called\n");
2691 DPRINT("lpMachineName = %p\n", lpMachineName
);
2692 DPRINT("lpMachineName: %S\n", lpMachineName
);
2693 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2694 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2695 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2698 return ERROR_SHUTDOWN_IN_PROGRESS
;
2701 return ERROR_INVALID_PARAMETER
;
2703 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2705 if (dwError
!= ERROR_SUCCESS
)
2707 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2711 /* Check the desired access */
2712 dwError
= ScmCheckAccess(hHandle
,
2713 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2714 if (dwError
!= ERROR_SUCCESS
)
2716 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2717 HeapFree(GetProcessHeap(), 0, hHandle
);
2721 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2722 DPRINT("*hScm = %p\n", *lpScHandle
);
2724 DPRINT("ROpenSCManagerW() done\n");
2726 return ERROR_SUCCESS
;
2731 DWORD
ROpenServiceW(
2732 SC_RPC_HANDLE hSCManager
,
2733 LPWSTR lpServiceName
,
2734 DWORD dwDesiredAccess
,
2735 LPSC_RPC_HANDLE lpServiceHandle
)
2738 PMANAGER_HANDLE hManager
;
2740 DWORD dwError
= ERROR_SUCCESS
;
2742 DPRINT("ROpenServiceW() called\n");
2743 DPRINT("hSCManager = %p\n", hSCManager
);
2744 DPRINT("lpServiceName = %p\n", lpServiceName
);
2745 DPRINT("lpServiceName: %S\n", lpServiceName
);
2746 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2749 return ERROR_SHUTDOWN_IN_PROGRESS
;
2751 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2752 if (hManager
== NULL
)
2754 DPRINT1("Invalid service manager handle!\n");
2755 return ERROR_INVALID_HANDLE
;
2758 if (!lpServiceHandle
)
2759 return ERROR_INVALID_PARAMETER
;
2762 return ERROR_INVALID_ADDRESS
;
2764 /* Lock the service database exclusive */
2765 ScmLockDatabaseExclusive();
2767 /* Get service database entry */
2768 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2769 if (lpService
== NULL
)
2771 DPRINT("Could not find a service!\n");
2772 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
2776 /* Create a service handle */
2777 dwError
= ScmCreateServiceHandle(lpService
,
2779 if (dwError
!= ERROR_SUCCESS
)
2781 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2785 /* Check the desired access */
2786 dwError
= ScmCheckAccess(hHandle
,
2788 if (dwError
!= ERROR_SUCCESS
)
2790 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2791 HeapFree(GetProcessHeap(), 0, hHandle
);
2795 lpService
->dwRefCount
++;
2796 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2798 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2799 DPRINT("*hService = %p\n", *lpServiceHandle
);
2802 /* Unlock the service database */
2803 ScmUnlockDatabase();
2805 DPRINT("ROpenServiceW() done\n");
2812 DWORD
RQueryServiceConfigW(
2813 SC_RPC_HANDLE hService
,
2814 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2816 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2818 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2819 DWORD dwError
= ERROR_SUCCESS
;
2820 PSERVICE_HANDLE hSvc
;
2821 PSERVICE lpService
= NULL
;
2822 HKEY hServiceKey
= NULL
;
2823 LPWSTR lpImagePath
= NULL
;
2824 LPWSTR lpServiceStartName
= NULL
;
2825 LPWSTR lpDependencies
= NULL
;
2826 DWORD dwDependenciesLength
= 0;
2827 DWORD dwRequiredSize
;
2828 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2829 WCHAR lpEmptyString
[] = {0,0};
2832 DPRINT("RQueryServiceConfigW() called\n");
2835 return ERROR_SHUTDOWN_IN_PROGRESS
;
2837 hSvc
= ScmGetServiceFromHandle(hService
);
2840 DPRINT1("Invalid service handle!\n");
2841 return ERROR_INVALID_HANDLE
;
2844 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2845 SERVICE_QUERY_CONFIG
))
2847 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2848 return ERROR_ACCESS_DENIED
;
2851 lpService
= hSvc
->ServiceEntry
;
2852 if (lpService
== NULL
)
2854 DPRINT("lpService == NULL!\n");
2855 return ERROR_INVALID_HANDLE
;
2858 /* Lock the service database shared */
2859 ScmLockDatabaseShared();
2861 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2864 if (dwError
!= ERROR_SUCCESS
)
2867 /* Read the image path */
2868 dwError
= ScmReadString(hServiceKey
,
2871 if (dwError
!= ERROR_SUCCESS
)
2874 /* Read the service start name */
2875 ScmReadString(hServiceKey
,
2877 &lpServiceStartName
);
2879 /* Read the dependencies */
2880 ScmReadDependencies(hServiceKey
,
2882 &dwDependenciesLength
);
2884 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2886 if (lpImagePath
!= NULL
)
2887 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2889 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2891 if (lpService
->lpGroup
!= NULL
)
2892 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2894 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2896 if (lpDependencies
!= NULL
)
2897 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2899 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2901 if (lpServiceStartName
!= NULL
)
2902 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2904 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2906 if (lpService
->lpDisplayName
!= NULL
)
2907 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2909 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2911 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2913 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2917 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2918 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2919 lpConfig
->dwStartType
= lpService
->dwStartType
;
2920 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2921 lpConfig
->dwTagId
= lpService
->dwTag
;
2923 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2925 /* Append the image path */
2926 if (lpImagePath
!= NULL
)
2928 wcscpy(lpStr
, lpImagePath
);
2932 wcscpy(lpStr
, lpEmptyString
);
2935 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2936 lpStr
+= (wcslen(lpStr
) + 1);
2938 /* Append the group name */
2939 if (lpService
->lpGroup
!= NULL
)
2941 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2945 wcscpy(lpStr
, lpEmptyString
);
2948 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2949 lpStr
+= (wcslen(lpStr
) + 1);
2951 /* Append Dependencies */
2952 if (lpDependencies
!= NULL
)
2956 dwDependenciesLength
* sizeof(WCHAR
));
2960 wcscpy(lpStr
, lpEmptyString
);
2963 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2964 if (lpDependencies
!= NULL
)
2965 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2967 lpStr
+= (wcslen(lpStr
) + 1);
2969 /* Append the service start name */
2970 if (lpServiceStartName
!= NULL
)
2972 wcscpy(lpStr
, lpServiceStartName
);
2976 wcscpy(lpStr
, lpEmptyString
);
2979 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2980 lpStr
+= (wcslen(lpStr
) + 1);
2982 /* Append the display name */
2983 if (lpService
->lpDisplayName
!= NULL
)
2985 wcscpy(lpStr
, lpService
->lpDisplayName
);
2989 wcscpy(lpStr
, lpEmptyString
);
2992 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2995 if (pcbBytesNeeded
!= NULL
)
2996 *pcbBytesNeeded
= dwRequiredSize
;
2999 /* Unlock the service database */
3000 ScmUnlockDatabase();
3002 if (lpImagePath
!= NULL
)
3003 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3005 if (lpServiceStartName
!= NULL
)
3006 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3008 if (lpDependencies
!= NULL
)
3009 HeapFree(GetProcessHeap(), 0, lpDependencies
);
3011 if (hServiceKey
!= NULL
)
3012 RegCloseKey(hServiceKey
);
3014 DPRINT("RQueryServiceConfigW() done\n");
3021 DWORD
RQueryServiceLockStatusW(
3022 SC_RPC_HANDLE hSCManager
,
3023 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
3025 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3028 return ERROR_CALL_NOT_IMPLEMENTED
;
3033 DWORD
RStartServiceW(
3034 SC_RPC_HANDLE hService
,
3036 LPSTRING_PTRSW argv
)
3038 DWORD dwError
= ERROR_SUCCESS
;
3039 PSERVICE_HANDLE hSvc
;
3040 PSERVICE lpService
= NULL
;
3043 DPRINT("RStartServiceW(%p %lu %p) called\n", hService
, argc
, argv
);
3044 DPRINT(" argc: %lu\n", argc
);
3047 for (i
= 0; i
< argc
; i
++)
3049 DPRINT(" argv[%lu]: %S\n", i
, argv
[i
]);
3054 return ERROR_SHUTDOWN_IN_PROGRESS
;
3056 hSvc
= ScmGetServiceFromHandle(hService
);
3059 DPRINT1("Invalid service handle!\n");
3060 return ERROR_INVALID_HANDLE
;
3063 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3066 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3067 return ERROR_ACCESS_DENIED
;
3070 lpService
= hSvc
->ServiceEntry
;
3071 if (lpService
== NULL
)
3073 DPRINT("lpService == NULL!\n");
3074 return ERROR_INVALID_HANDLE
;
3077 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3078 return ERROR_SERVICE_DISABLED
;
3080 if (lpService
->bDeleted
)
3081 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3083 /* Start the service */
3084 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
3091 DWORD
RGetServiceDisplayNameW(
3092 SC_RPC_HANDLE hSCManager
,
3093 LPCWSTR lpServiceName
,
3094 LPWSTR lpDisplayName
,
3097 // PMANAGER_HANDLE hManager;
3102 DPRINT("RGetServiceDisplayNameW() called\n");
3103 DPRINT("hSCManager = %p\n", hSCManager
);
3104 DPRINT("lpServiceName: %S\n", lpServiceName
);
3105 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3106 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3108 // hManager = (PMANAGER_HANDLE)hSCManager;
3109 // if (hManager->Handle.Tag != MANAGER_TAG)
3111 // DPRINT("Invalid manager handle!\n");
3112 // return ERROR_INVALID_HANDLE;
3115 /* Get service database entry */
3116 lpService
= ScmGetServiceEntryByName(lpServiceName
);
3117 if (lpService
== NULL
)
3119 DPRINT("Could not find a service!\n");
3121 /* If the service could not be found and lpcchBuffer is less than 2, windows
3122 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3123 if (*lpcchBuffer
< 2)
3126 if (lpDisplayName
!= NULL
)
3128 *lpDisplayName
= '\0';
3132 return ERROR_SERVICE_DOES_NOT_EXIST
;
3135 if (!lpService
->lpDisplayName
)
3137 dwLength
= wcslen(lpService
->lpServiceName
);
3139 if (lpDisplayName
!= NULL
&&
3140 *lpcchBuffer
> dwLength
)
3142 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
3147 dwLength
= wcslen(lpService
->lpDisplayName
);
3149 if (lpDisplayName
!= NULL
&&
3150 *lpcchBuffer
> dwLength
)
3152 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
3156 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3158 *lpcchBuffer
= dwLength
;
3165 DWORD
RGetServiceKeyNameW(
3166 SC_RPC_HANDLE hSCManager
,
3167 LPCWSTR lpDisplayName
,
3168 LPWSTR lpServiceName
,
3171 // PMANAGER_HANDLE hManager;
3176 DPRINT("RGetServiceKeyNameW() called\n");
3177 DPRINT("hSCManager = %p\n", hSCManager
);
3178 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
3179 DPRINT("lpServiceName: %p\n", lpServiceName
);
3180 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3182 // hManager = (PMANAGER_HANDLE)hSCManager;
3183 // if (hManager->Handle.Tag != MANAGER_TAG)
3185 // DPRINT("Invalid manager handle!\n");
3186 // return ERROR_INVALID_HANDLE;
3189 /* Get service database entry */
3190 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
3191 if (lpService
== NULL
)
3193 DPRINT("Could not find a service!\n");
3195 /* If the service could not be found and lpcchBuffer is less than 2, windows
3196 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3197 if (*lpcchBuffer
< 2)
3200 if (lpServiceName
!= NULL
)
3202 *lpServiceName
= '\0';
3206 return ERROR_SERVICE_DOES_NOT_EXIST
;
3209 dwLength
= wcslen(lpService
->lpServiceName
);
3211 if (lpServiceName
!= NULL
&&
3212 *lpcchBuffer
> dwLength
)
3214 wcscpy(lpServiceName
, lpService
->lpServiceName
);
3215 *lpcchBuffer
= dwLength
;
3216 return ERROR_SUCCESS
;
3219 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3221 *lpcchBuffer
= dwLength
;
3228 DWORD
RI_ScSetServiceBitsA(
3229 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3230 DWORD dwServiceBits
,
3232 int bUpdateImmediately
,
3236 return ERROR_CALL_NOT_IMPLEMENTED
;
3241 DWORD
RChangeServiceConfigA(
3242 SC_RPC_HANDLE hService
,
3243 DWORD dwServiceType
,
3245 DWORD dwErrorControl
,
3246 LPSTR lpBinaryPathName
,
3247 LPSTR lpLoadOrderGroup
,
3249 LPSTR lpDependencies
,
3251 LPSTR lpServiceStartName
,
3254 LPSTR lpDisplayName
)
3256 DWORD dwError
= ERROR_SUCCESS
;
3257 PSERVICE_HANDLE hSvc
;
3258 PSERVICE lpService
= NULL
;
3259 HKEY hServiceKey
= NULL
;
3260 LPWSTR lpDisplayNameW
= NULL
;
3261 // LPWSTR lpBinaryPathNameW = NULL;
3262 LPWSTR lpLoadOrderGroupW
= NULL
;
3263 LPWSTR lpDependenciesW
= NULL
;
3264 // LPWSTR lpPasswordW = NULL;
3266 DPRINT("RChangeServiceConfigA() called\n");
3267 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3268 DPRINT("dwStartType = %lu\n", dwStartType
);
3269 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3270 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3271 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3272 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3275 return ERROR_SHUTDOWN_IN_PROGRESS
;
3277 hSvc
= ScmGetServiceFromHandle(hService
);
3280 DPRINT1("Invalid service handle!\n");
3281 return ERROR_INVALID_HANDLE
;
3284 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3285 SERVICE_CHANGE_CONFIG
))
3287 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3288 return ERROR_ACCESS_DENIED
;
3291 lpService
= hSvc
->ServiceEntry
;
3292 if (lpService
== NULL
)
3294 DPRINT("lpService == NULL!\n");
3295 return ERROR_INVALID_HANDLE
;
3298 /* Lock the service database exclusively */
3299 ScmLockDatabaseExclusive();
3301 if (lpService
->bDeleted
)
3303 DPRINT("The service has already been marked for delete!\n");
3304 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
3308 /* Open the service key */
3309 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3312 if (dwError
!= ERROR_SUCCESS
)
3315 /* Write service data to the registry */
3317 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3319 /* Set the display name */
3320 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3322 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3323 if (lpDisplayNameW
== NULL
)
3325 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3329 MultiByteToWideChar(CP_ACP
,
3334 strlen(lpDisplayName
) + 1);
3336 RegSetValueExW(hServiceKey
,
3340 (LPBYTE
)lpDisplayNameW
,
3341 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3343 /* Update lpService->lpDisplayName */
3344 if (lpService
->lpDisplayName
)
3345 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3347 lpService
->lpDisplayName
= lpDisplayNameW
;
3350 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3352 /* Set the service type */
3353 dwError
= RegSetValueExW(hServiceKey
,
3357 (LPBYTE
)&dwServiceType
,
3359 if (dwError
!= ERROR_SUCCESS
)
3362 lpService
->Status
.dwServiceType
= dwServiceType
;
3365 if (dwStartType
!= SERVICE_NO_CHANGE
)
3367 /* Set the start value */
3368 dwError
= RegSetValueExW(hServiceKey
,
3372 (LPBYTE
)&dwStartType
,
3374 if (dwError
!= ERROR_SUCCESS
)
3377 lpService
->dwStartType
= dwStartType
;
3380 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3382 /* Set the error control value */
3383 dwError
= RegSetValueExW(hServiceKey
,
3387 (LPBYTE
)&dwErrorControl
,
3389 if (dwError
!= ERROR_SUCCESS
)
3392 lpService
->dwErrorControl
= dwErrorControl
;
3396 /* FIXME: set the new ImagePath value */
3398 /* Set the image path */
3399 if (dwServiceType
& SERVICE_WIN32
)
3401 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3403 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3404 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, strlen(lpBinaryPathName
)+1);
3405 dwError
= RegSetValueExW(hServiceKey
,
3409 (LPBYTE
)lpBinaryPathNameW
,
3410 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3411 if (dwError
!= ERROR_SUCCESS
)
3415 else if (dwServiceType
& SERVICE_DRIVER
)
3417 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3419 dwError
= RegSetValueExW(hServiceKey
,
3423 (LPBYTE
)lpImagePath
,
3424 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3425 if (dwError
!= ERROR_SUCCESS
)
3431 /* Set the group name */
3432 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3434 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3436 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3437 if (lpLoadOrderGroupW
== NULL
)
3439 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3443 MultiByteToWideChar(CP_ACP
,
3448 strlen(lpLoadOrderGroup
) + 1);
3450 dwError
= RegSetValueExW(hServiceKey
,
3454 (LPBYTE
)lpLoadOrderGroupW
,
3455 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3456 if (dwError
!= ERROR_SUCCESS
)
3458 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3462 dwError
= ScmSetServiceGroup(lpService
,
3465 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3467 if (dwError
!= ERROR_SUCCESS
)
3471 if (lpdwTagId
!= NULL
)
3473 dwError
= ScmAssignNewTag(lpService
);
3474 if (dwError
!= ERROR_SUCCESS
)
3477 dwError
= RegSetValueExW(hServiceKey
,
3481 (LPBYTE
)&lpService
->dwTag
,
3483 if (dwError
!= ERROR_SUCCESS
)
3486 *lpdwTagId
= lpService
->dwTag
;
3489 /* Write dependencies */
3490 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3492 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3494 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3495 if (lpDependenciesW
== NULL
)
3497 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3501 MultiByteToWideChar(CP_ACP
,
3506 strlen(lpDependencies
) + 1);
3508 dwError
= ScmWriteDependencies(hServiceKey
,
3509 (LPWSTR
)lpDependenciesW
,
3512 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3515 if (lpPassword
!= NULL
)
3517 /* FIXME: Write password */
3521 /* Unlock the service database */
3522 ScmUnlockDatabase();
3524 if (hServiceKey
!= NULL
)
3525 RegCloseKey(hServiceKey
);
3527 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3534 DWORD
RCreateServiceA(
3535 SC_RPC_HANDLE hSCManager
,
3536 LPSTR lpServiceName
,
3537 LPSTR lpDisplayName
,
3538 DWORD dwDesiredAccess
,
3539 DWORD dwServiceType
,
3541 DWORD dwErrorControl
,
3542 LPSTR lpBinaryPathName
,
3543 LPSTR lpLoadOrderGroup
,
3545 LPBYTE lpDependencies
,
3547 LPSTR lpServiceStartName
,
3550 LPSC_RPC_HANDLE lpServiceHandle
)
3552 DWORD dwError
= ERROR_SUCCESS
;
3553 LPWSTR lpServiceNameW
= NULL
;
3554 LPWSTR lpDisplayNameW
= NULL
;
3555 LPWSTR lpBinaryPathNameW
= NULL
;
3556 LPWSTR lpLoadOrderGroupW
= NULL
;
3557 LPWSTR lpDependenciesW
= NULL
;
3558 LPWSTR lpServiceStartNameW
= NULL
;
3559 DWORD dwDependenciesLength
= 0;
3566 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3567 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3568 if (!lpServiceNameW
)
3570 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3573 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3578 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3579 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3580 if (!lpDisplayNameW
)
3582 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3585 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3588 if (lpBinaryPathName
)
3590 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3591 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3592 if (!lpBinaryPathNameW
)
3594 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3597 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3600 if (lpLoadOrderGroup
)
3602 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3603 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3604 if (!lpLoadOrderGroupW
)
3606 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3609 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3614 lpStr
= (LPCSTR
)lpDependencies
;
3617 dwLength
= strlen(lpStr
) + 1;
3618 dwDependenciesLength
+= dwLength
;
3619 lpStr
= lpStr
+ dwLength
;
3621 dwDependenciesLength
++;
3623 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3624 if (!lpDependenciesW
)
3626 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3629 MultiByteToWideChar(CP_ACP
, 0, (LPCSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3632 if (lpServiceStartName
)
3634 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3635 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3636 if (!lpServiceStartNameW
)
3638 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3641 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3644 dwError
= RCreateServiceW(hSCManager
,
3654 (LPBYTE
)lpDependenciesW
,
3655 dwDependenciesLength
,
3656 lpServiceStartNameW
,
3662 if (lpServiceNameW
!=NULL
)
3663 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3665 if (lpDisplayNameW
!= NULL
)
3666 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3668 if (lpBinaryPathNameW
!= NULL
)
3669 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3671 if (lpLoadOrderGroupW
!= NULL
)
3672 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3674 if (lpDependenciesW
!= NULL
)
3675 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3677 if (lpServiceStartNameW
!= NULL
)
3678 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3685 DWORD
REnumDependentServicesA(
3686 SC_RPC_HANDLE hService
,
3687 DWORD dwServiceState
,
3690 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3691 LPBOUNDED_DWORD_256K lpServicesReturned
)
3693 DWORD dwError
= ERROR_SUCCESS
;
3694 DWORD dwServicesReturned
= 0;
3695 DWORD dwServiceCount
;
3696 HKEY hServicesKey
= NULL
;
3697 PSERVICE_HANDLE hSvc
;
3698 PSERVICE lpService
= NULL
;
3699 PSERVICE
*lpServicesArray
= NULL
;
3700 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3703 *pcbBytesNeeded
= 0;
3704 *lpServicesReturned
= 0;
3706 DPRINT("REnumDependentServicesA() called\n");
3708 hSvc
= ScmGetServiceFromHandle(hService
);
3711 DPRINT1("Invalid service handle!\n");
3712 return ERROR_INVALID_HANDLE
;
3715 lpService
= hSvc
->ServiceEntry
;
3717 /* Check access rights */
3718 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3719 SC_MANAGER_ENUMERATE_SERVICE
))
3721 DPRINT("Insufficient access rights! 0x%lx\n",
3722 hSvc
->Handle
.DesiredAccess
);
3723 return ERROR_ACCESS_DENIED
;
3726 /* Open the Services Reg key */
3727 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3728 L
"System\\CurrentControlSet\\Services",
3733 if (dwError
!= ERROR_SUCCESS
)
3736 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3737 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3738 are the same for both. Verified in WINXP. */
3740 /* First determine the bytes needed and get the number of dependent services*/
3741 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3746 &dwServicesReturned
);
3747 if (dwError
!= ERROR_SUCCESS
)
3750 /* If buffer size is less than the bytes needed or pointer is null*/
3751 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3753 dwError
= ERROR_MORE_DATA
;
3757 /* Allocate memory for array of service pointers */
3758 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3760 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3761 if (!lpServicesArray
)
3763 DPRINT("Could not allocate a buffer!!\n");
3764 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3768 dwServicesReturned
= 0;
3769 *pcbBytesNeeded
= 0;
3771 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3776 &dwServicesReturned
);
3777 if (dwError
!= ERROR_SUCCESS
)
3782 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3783 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3785 /* Copy EnumDepenedentService to Buffer */
3786 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3788 lpService
= lpServicesArray
[dwServiceCount
];
3790 /* Copy the status info */
3791 memcpy(&lpServicesPtr
->ServiceStatus
,
3793 sizeof(SERVICE_STATUS
));
3795 /* Copy display name */
3796 WideCharToMultiByte(CP_ACP
,
3798 lpService
->lpDisplayName
,
3801 wcslen(lpService
->lpDisplayName
),
3804 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3805 lpStr
+= strlen(lpStr
) + 1;
3807 /* Copy service name */
3808 WideCharToMultiByte(CP_ACP
,
3810 lpService
->lpServiceName
,
3813 wcslen(lpService
->lpServiceName
),
3816 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3817 lpStr
+= strlen(lpStr
) + 1;
3822 *lpServicesReturned
= dwServicesReturned
;
3825 if (lpServicesArray
)
3826 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3828 RegCloseKey(hServicesKey
);
3830 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3837 DWORD
REnumServicesStatusA(
3838 SC_RPC_HANDLE hSCManager
,
3839 DWORD dwServiceType
,
3840 DWORD dwServiceState
,
3843 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3844 LPBOUNDED_DWORD_256K lpServicesReturned
,
3845 LPBOUNDED_DWORD_256K lpResumeHandle
)
3847 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3848 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3849 LPWSTR lpStringPtrW
;
3852 DWORD dwServiceCount
;
3854 DPRINT("REnumServicesStatusA() called\n");
3856 if ((dwBufSize
> 0) && (lpBuffer
))
3858 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3861 DPRINT("Failed to allocate buffer!\n");
3862 return ERROR_NOT_ENOUGH_MEMORY
;
3866 dwError
= REnumServicesStatusW(hSCManager
,
3869 (LPBYTE
)lpStatusPtrW
,
3875 /* if no services were returned then we are Done */
3876 if (*lpServicesReturned
== 0)
3879 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3880 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3881 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3882 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3883 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3885 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3887 /* Copy the service name */
3888 WideCharToMultiByte(CP_ACP
,
3893 wcslen(lpStringPtrW
),
3897 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3898 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3899 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3901 /* Copy the display name */
3902 WideCharToMultiByte(CP_ACP
,
3907 wcslen(lpStringPtrW
),
3911 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3912 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3913 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3915 /* Copy the status information */
3916 memcpy(&lpStatusPtrA
->ServiceStatus
,
3917 &lpStatusPtrW
->ServiceStatus
,
3918 sizeof(SERVICE_STATUS
));
3925 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3927 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3934 DWORD
ROpenSCManagerA(
3935 LPSTR lpMachineName
,
3936 LPSTR lpDatabaseName
,
3937 DWORD dwDesiredAccess
,
3938 LPSC_RPC_HANDLE lpScHandle
)
3940 UNICODE_STRING MachineName
;
3941 UNICODE_STRING DatabaseName
;
3944 DPRINT("ROpenSCManagerA() called\n");
3947 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3951 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3954 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3955 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3960 RtlFreeUnicodeString(&MachineName
);
3963 RtlFreeUnicodeString(&DatabaseName
);
3970 DWORD
ROpenServiceA(
3971 SC_RPC_HANDLE hSCManager
,
3972 LPSTR lpServiceName
,
3973 DWORD dwDesiredAccess
,
3974 LPSC_RPC_HANDLE lpServiceHandle
)
3976 UNICODE_STRING ServiceName
;
3979 DPRINT("ROpenServiceA() called\n");
3982 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3985 dwError
= ROpenServiceW(hSCManager
,
3986 lpServiceName
? ServiceName
.Buffer
: NULL
,
3991 RtlFreeUnicodeString(&ServiceName
);
3998 DWORD
RQueryServiceConfigA(
3999 SC_RPC_HANDLE hService
,
4000 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
4002 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4004 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
4005 DWORD dwError
= ERROR_SUCCESS
;
4006 PSERVICE_HANDLE hSvc
;
4007 PSERVICE lpService
= NULL
;
4008 HKEY hServiceKey
= NULL
;
4009 LPWSTR lpImagePath
= NULL
;
4010 LPWSTR lpServiceStartName
= NULL
;
4011 LPWSTR lpDependencies
= NULL
;
4012 DWORD dwDependenciesLength
= 0;
4013 DWORD dwRequiredSize
;
4014 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
4015 CHAR lpEmptyString
[]={0,0};
4018 DPRINT("RQueryServiceConfigA() called\n");
4021 return ERROR_SHUTDOWN_IN_PROGRESS
;
4023 hSvc
= ScmGetServiceFromHandle(hService
);
4026 DPRINT1("Invalid service handle!\n");
4027 return ERROR_INVALID_HANDLE
;
4030 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4031 SERVICE_QUERY_CONFIG
))
4033 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4034 return ERROR_ACCESS_DENIED
;
4037 lpService
= hSvc
->ServiceEntry
;
4038 if (lpService
== NULL
)
4040 DPRINT("lpService == NULL!\n");
4041 return ERROR_INVALID_HANDLE
;
4044 /* Lock the service database shared */
4045 ScmLockDatabaseShared();
4047 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4050 if (dwError
!= ERROR_SUCCESS
)
4053 /* Read the image path */
4054 dwError
= ScmReadString(hServiceKey
,
4057 if (dwError
!= ERROR_SUCCESS
)
4060 /* Read the service start name */
4061 ScmReadString(hServiceKey
,
4063 &lpServiceStartName
);
4065 /* Read the dependencies */
4066 ScmReadDependencies(hServiceKey
,
4068 &dwDependenciesLength
);
4070 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
4072 if (lpImagePath
!= NULL
)
4073 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
4075 dwRequiredSize
+= 2;
4077 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
4078 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
4080 dwRequiredSize
+= 2;
4082 /* Add Dependencies length */
4083 if (lpDependencies
!= NULL
)
4084 dwRequiredSize
+= dwDependenciesLength
;
4086 dwRequiredSize
+= 2;
4088 if (lpServiceStartName
!= NULL
)
4089 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
4091 dwRequiredSize
+= 2;
4093 if (lpService
->lpDisplayName
!= NULL
)
4094 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
4096 dwRequiredSize
+= 2;
4098 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
4100 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4104 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
4105 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
4106 lpConfig
->dwStartType
= lpService
->dwStartType
;
4107 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
4108 lpConfig
->dwTagId
= lpService
->dwTag
;
4110 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
4112 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
4117 WideCharToMultiByte(CP_ACP
,
4122 wcslen(lpImagePath
) + 1,
4128 strcpy(lpStr
, lpEmptyString
);
4131 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4132 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
4134 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
4136 WideCharToMultiByte(CP_ACP
,
4138 lpService
->lpGroup
->lpGroupName
,
4141 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
4147 strcpy(lpStr
, lpEmptyString
);
4150 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4151 lpStr
+= (strlen(lpStr
) + 1);
4153 /* Append Dependencies */
4156 WideCharToMultiByte(CP_ACP
,
4159 dwDependenciesLength
,
4161 dwDependenciesLength
,
4167 strcpy(lpStr
, lpEmptyString
);
4170 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4172 lpStr
+= dwDependenciesLength
;
4174 lpStr
+= (strlen(lpStr
) + 1);
4176 if (lpServiceStartName
)
4178 WideCharToMultiByte(CP_ACP
,
4183 wcslen(lpServiceStartName
) + 1,
4189 strcpy(lpStr
, lpEmptyString
);
4192 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4193 lpStr
+= (strlen(lpStr
) + 1);
4195 if (lpService
->lpDisplayName
)
4197 WideCharToMultiByte(CP_ACP
,
4199 lpService
->lpDisplayName
,
4202 wcslen(lpService
->lpDisplayName
) + 1,
4208 strcpy(lpStr
, lpEmptyString
);
4211 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4214 if (pcbBytesNeeded
!= NULL
)
4215 *pcbBytesNeeded
= dwRequiredSize
;
4218 /* Unlock the service database */
4219 ScmUnlockDatabase();
4221 if (lpImagePath
!= NULL
)
4222 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4224 if (lpServiceStartName
!= NULL
)
4225 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4227 if (lpDependencies
!= NULL
)
4228 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4230 if (hServiceKey
!= NULL
)
4231 RegCloseKey(hServiceKey
);
4233 DPRINT("RQueryServiceConfigA() done\n");
4240 DWORD
RQueryServiceLockStatusA(
4241 SC_RPC_HANDLE hSCManager
,
4242 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
4244 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4247 return ERROR_CALL_NOT_IMPLEMENTED
;
4252 DWORD
RStartServiceA(
4253 SC_RPC_HANDLE hService
,
4255 LPSTRING_PTRSA argv
)
4257 DWORD dwError
= ERROR_SUCCESS
;
4258 PSERVICE_HANDLE hSvc
;
4259 PSERVICE lpService
= NULL
;
4260 LPWSTR
*lpVector
= NULL
;
4264 DPRINT("RStartServiceA() called\n");
4267 return ERROR_SHUTDOWN_IN_PROGRESS
;
4269 hSvc
= ScmGetServiceFromHandle(hService
);
4272 DPRINT1("Invalid service handle!\n");
4273 return ERROR_INVALID_HANDLE
;
4276 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4279 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4280 return ERROR_ACCESS_DENIED
;
4283 lpService
= hSvc
->ServiceEntry
;
4284 if (lpService
== NULL
)
4286 DPRINT("lpService == NULL!\n");
4287 return ERROR_INVALID_HANDLE
;
4290 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4291 return ERROR_SERVICE_DISABLED
;
4293 if (lpService
->bDeleted
)
4294 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4296 /* Build a Unicode argument vector */
4299 lpVector
= HeapAlloc(GetProcessHeap(),
4301 argc
* sizeof(LPWSTR
));
4302 if (lpVector
== NULL
)
4303 return ERROR_NOT_ENOUGH_MEMORY
;
4305 for (i
= 0; i
< argc
; i
++)
4307 dwLength
= MultiByteToWideChar(CP_ACP
,
4314 lpVector
[i
] = HeapAlloc(GetProcessHeap(),
4316 dwLength
* sizeof(WCHAR
));
4317 if (lpVector
[i
] == NULL
)
4319 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
4323 MultiByteToWideChar(CP_ACP
,
4332 /* Start the service */
4333 dwError
= ScmStartService(lpService
, argc
, lpVector
);
4336 /* Free the Unicode argument vector */
4337 if (lpVector
!= NULL
)
4339 for (i
= 0; i
< argc
; i
++)
4341 if (lpVector
[i
] != NULL
)
4342 HeapFree(GetProcessHeap(), 0, lpVector
[i
]);
4344 HeapFree(GetProcessHeap(), 0, lpVector
);
4352 DWORD
RGetServiceDisplayNameA(
4353 SC_RPC_HANDLE hSCManager
,
4354 LPCSTR lpServiceName
,
4355 LPSTR lpDisplayName
,
4356 LPBOUNDED_DWORD_4K lpcchBuffer
)
4358 // PMANAGER_HANDLE hManager;
4359 PSERVICE lpService
= NULL
;
4362 LPWSTR lpServiceNameW
;
4364 DPRINT("RGetServiceDisplayNameA() called\n");
4365 DPRINT("hSCManager = %p\n", hSCManager
);
4366 DPRINT("lpServiceName: %s\n", lpServiceName
);
4367 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4368 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4370 // hManager = (PMANAGER_HANDLE)hSCManager;
4371 // if (hManager->Handle.Tag != MANAGER_TAG)
4373 // DPRINT("Invalid manager handle!\n");
4374 // return ERROR_INVALID_HANDLE;
4377 if (lpServiceName
!= NULL
)
4379 dwLength
= strlen(lpServiceName
) + 1;
4380 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4382 dwLength
* sizeof(WCHAR
));
4383 if (!lpServiceNameW
)
4384 return ERROR_NOT_ENOUGH_MEMORY
;
4386 MultiByteToWideChar(CP_ACP
,
4393 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4395 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4398 if (lpService
== NULL
)
4400 DPRINT("Could not find a service!\n");
4402 /* If the service could not be found and lpcchBuffer is 0, windows
4403 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4404 if (*lpcchBuffer
== 0)
4407 if (lpDisplayName
!= NULL
)
4409 *lpDisplayName
= '\0';
4412 return ERROR_SERVICE_DOES_NOT_EXIST
;
4415 if (!lpService
->lpDisplayName
)
4417 dwLength
= wcslen(lpService
->lpServiceName
);
4418 if (lpDisplayName
!= NULL
&&
4419 *lpcchBuffer
> dwLength
)
4421 WideCharToMultiByte(CP_ACP
,
4423 lpService
->lpServiceName
,
4424 wcslen(lpService
->lpServiceName
),
4429 return ERROR_SUCCESS
;
4434 dwLength
= wcslen(lpService
->lpDisplayName
);
4435 if (lpDisplayName
!= NULL
&&
4436 *lpcchBuffer
> dwLength
)
4438 WideCharToMultiByte(CP_ACP
,
4440 lpService
->lpDisplayName
,
4441 wcslen(lpService
->lpDisplayName
),
4446 return ERROR_SUCCESS
;
4450 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4452 *lpcchBuffer
= dwLength
* 2;
4459 DWORD
RGetServiceKeyNameA(
4460 SC_RPC_HANDLE hSCManager
,
4461 LPCSTR lpDisplayName
,
4462 LPSTR lpServiceName
,
4463 LPBOUNDED_DWORD_4K lpcchBuffer
)
4468 LPWSTR lpDisplayNameW
;
4470 DPRINT("RGetServiceKeyNameA() called\n");
4471 DPRINT("hSCManager = %p\n", hSCManager
);
4472 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4473 DPRINT("lpServiceName: %p\n", lpServiceName
);
4474 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4476 dwLength
= strlen(lpDisplayName
) + 1;
4477 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4479 dwLength
* sizeof(WCHAR
));
4480 if (!lpDisplayNameW
)
4481 return ERROR_NOT_ENOUGH_MEMORY
;
4483 MultiByteToWideChar(CP_ACP
,
4490 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4492 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4494 if (lpService
== NULL
)
4496 DPRINT("Could not find the service!\n");
4498 /* If the service could not be found and lpcchBuffer is 0,
4499 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4500 if (*lpcchBuffer
== 0)
4503 if (lpServiceName
!= NULL
)
4505 *lpServiceName
= '\0';
4509 return ERROR_SERVICE_DOES_NOT_EXIST
;
4512 dwLength
= wcslen(lpService
->lpServiceName
);
4513 if (lpServiceName
!= NULL
&&
4514 *lpcchBuffer
> dwLength
)
4516 WideCharToMultiByte(CP_ACP
,
4518 lpService
->lpServiceName
,
4519 wcslen(lpService
->lpServiceName
),
4524 return ERROR_SUCCESS
;
4527 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4529 *lpcchBuffer
= dwLength
* 2;
4536 DWORD
RI_ScGetCurrentGroupStateW(
4537 SC_RPC_HANDLE hSCManager
,
4538 LPWSTR lpLoadOrderGroup
,
4542 return ERROR_CALL_NOT_IMPLEMENTED
;
4547 DWORD
REnumServiceGroupW(
4548 SC_RPC_HANDLE hSCManager
,
4549 DWORD dwServiceType
,
4550 DWORD dwServiceState
,
4553 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4554 LPBOUNDED_DWORD_256K lpServicesReturned
,
4555 LPBOUNDED_DWORD_256K lpResumeIndex
,
4556 LPCWSTR pszGroupName
)
4559 return ERROR_CALL_NOT_IMPLEMENTED
;
4564 // WARNING: This function is untested
4567 DWORD
RChangeServiceConfig2A(
4568 SC_RPC_HANDLE hService
,
4569 SC_RPC_CONFIG_INFOA Info
)
4571 SC_RPC_CONFIG_INFOW InfoW
;
4572 DWORD dwRet
, dwLength
;
4575 DPRINT("RChangeServiceConfig2A() called\n");
4576 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4578 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4580 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4582 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4583 //LPSERVICE_DESCRIPTIONA lpServiceDescriptonA;
4585 //lpServiceDescriptonA = Info.psd;
4587 ///if (lpServiceDescriptonA &&
4588 ///lpServiceDescriptonA->lpDescription)
4590 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4592 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4594 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4595 if (!lpServiceDescriptonW
)
4597 return ERROR_NOT_ENOUGH_MEMORY
;
4600 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4602 MultiByteToWideChar(CP_ACP
,
4606 lpServiceDescriptonW
->lpDescription
,
4609 ptr
= lpServiceDescriptonW
;
4610 InfoW
.psd
= lpServiceDescriptonW
;
4613 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4615 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4616 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4617 DWORD dwRebootLen
= 0;
4618 DWORD dwCommandLen
= 0;
4620 lpServiceFailureActionsA
= Info
.psfa
;
4622 if (lpServiceFailureActionsA
)
4624 if (lpServiceFailureActionsA
->lpRebootMsg
)
4626 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4628 if (lpServiceFailureActionsA
->lpCommand
)
4630 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4632 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4634 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4637 if (!lpServiceFailureActionsW
)
4639 return ERROR_NOT_ENOUGH_MEMORY
;
4642 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4643 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4644 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4646 if (lpServiceFailureActionsA
->lpRebootMsg
)
4648 MultiByteToWideChar(CP_ACP
,
4650 lpServiceFailureActionsA
->lpRebootMsg
,
4652 lpServiceFailureActionsW
->lpRebootMsg
,
4656 if (lpServiceFailureActionsA
->lpCommand
)
4658 MultiByteToWideChar(CP_ACP
,
4660 lpServiceFailureActionsA
->lpCommand
,
4662 lpServiceFailureActionsW
->lpCommand
,
4666 ptr
= lpServiceFailureActionsW
;
4670 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4672 HeapFree(GetProcessHeap(), 0, ptr
);
4679 DWORD
RChangeServiceConfig2W(
4680 SC_RPC_HANDLE hService
,
4681 SC_RPC_CONFIG_INFOW Info
)
4683 DWORD dwError
= ERROR_SUCCESS
;
4684 PSERVICE_HANDLE hSvc
;
4685 PSERVICE lpService
= NULL
;
4686 HKEY hServiceKey
= NULL
;
4688 DPRINT("RChangeServiceConfig2W() called\n");
4689 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4692 return ERROR_SHUTDOWN_IN_PROGRESS
;
4694 hSvc
= ScmGetServiceFromHandle(hService
);
4697 DPRINT1("Invalid service handle!\n");
4698 return ERROR_INVALID_HANDLE
;
4701 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4702 SERVICE_CHANGE_CONFIG
))
4704 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4705 return ERROR_ACCESS_DENIED
;
4708 lpService
= hSvc
->ServiceEntry
;
4709 if (lpService
== NULL
)
4711 DPRINT("lpService == NULL!\n");
4712 return ERROR_INVALID_HANDLE
;
4715 /* Lock the service database exclusively */
4716 ScmLockDatabaseExclusive();
4718 if (lpService
->bDeleted
)
4720 DPRINT("The service has already been marked for delete!\n");
4721 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
4725 /* Open the service key */
4726 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4729 if (dwError
!= ERROR_SUCCESS
)
4732 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4734 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4736 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4737 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4739 if (lpServiceDescription
!= NULL
&&
4740 lpServiceDescription
->lpDescription
!= NULL
)
4742 DPRINT("Setting value %S\n", lpServiceDescription
->lpDescription
);
4743 dwError
= RegSetValueExW(hServiceKey
,
4747 (LPBYTE
)lpServiceDescription
->lpDescription
,
4748 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4749 if (dwError
!= ERROR_SUCCESS
)
4753 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4756 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4761 /* Unlock the service database */
4762 ScmUnlockDatabase();
4764 if (hServiceKey
!= NULL
)
4765 RegCloseKey(hServiceKey
);
4767 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4774 DWORD
RQueryServiceConfig2A(
4775 SC_RPC_HANDLE hService
,
4779 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4781 DWORD dwError
= ERROR_SUCCESS
;
4782 PSERVICE_HANDLE hSvc
;
4783 PSERVICE lpService
= NULL
;
4784 HKEY hServiceKey
= NULL
;
4785 LPWSTR lpDescriptionW
= NULL
;
4786 LPSTR lpDescription
= NULL
;
4788 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4789 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4792 return ERROR_INVALID_ADDRESS
;
4795 return ERROR_SHUTDOWN_IN_PROGRESS
;
4797 hSvc
= ScmGetServiceFromHandle(hService
);
4800 DPRINT1("Invalid service handle!\n");
4801 return ERROR_INVALID_HANDLE
;
4804 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4805 SERVICE_QUERY_CONFIG
))
4807 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4808 return ERROR_ACCESS_DENIED
;
4811 lpService
= hSvc
->ServiceEntry
;
4812 if (lpService
== NULL
)
4814 DPRINT("lpService == NULL!\n");
4815 return ERROR_INVALID_HANDLE
;
4818 /* Lock the service database shared */
4819 ScmLockDatabaseShared();
4821 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4824 if (dwError
!= ERROR_SUCCESS
)
4827 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4829 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4832 dwError
= ScmReadString(hServiceKey
,
4835 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4838 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4839 if (dwError
== ERROR_SUCCESS
)
4840 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4842 if (cbBufSize
< *pcbBytesNeeded
)
4844 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4848 if (dwError
== ERROR_SUCCESS
)
4850 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4852 WideCharToMultiByte(CP_ACP
,
4857 wcslen(lpDescriptionW
),
4860 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4864 lpServiceDescription
->lpDescription
= NULL
;
4865 dwError
= ERROR_SUCCESS
;
4869 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4872 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4877 /* Unlock the service database */
4878 ScmUnlockDatabase();
4880 if (lpDescription
!= NULL
)
4881 HeapFree(GetProcessHeap(), 0, lpDescription
);
4883 if (hServiceKey
!= NULL
)
4884 RegCloseKey(hServiceKey
);
4886 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4893 DWORD
RQueryServiceConfig2W(
4894 SC_RPC_HANDLE hService
,
4898 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4900 DWORD dwError
= ERROR_SUCCESS
;
4901 PSERVICE_HANDLE hSvc
;
4902 PSERVICE lpService
= NULL
;
4903 HKEY hServiceKey
= NULL
;
4904 DWORD dwRequiredSize
;
4905 LPWSTR lpDescription
= NULL
;
4906 LPWSTR lpFailureCommand
= NULL
;
4907 LPWSTR lpRebootMessage
= NULL
;
4909 DPRINT("RQueryServiceConfig2W() called\n");
4912 return ERROR_INVALID_ADDRESS
;
4915 return ERROR_SHUTDOWN_IN_PROGRESS
;
4917 hSvc
= ScmGetServiceFromHandle(hService
);
4920 DPRINT1("Invalid service handle!\n");
4921 return ERROR_INVALID_HANDLE
;
4924 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4925 SERVICE_QUERY_CONFIG
))
4927 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4928 return ERROR_ACCESS_DENIED
;
4931 lpService
= hSvc
->ServiceEntry
;
4932 if (lpService
== NULL
)
4934 DPRINT("lpService == NULL!\n");
4935 return ERROR_INVALID_HANDLE
;
4938 /* Lock the service database shared */
4939 ScmLockDatabaseShared();
4941 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4944 if (dwError
!= ERROR_SUCCESS
)
4947 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4949 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4952 dwError
= ScmReadString(hServiceKey
,
4955 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4958 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONW
);
4959 if (dwError
== ERROR_SUCCESS
)
4960 *pcbBytesNeeded
+= ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4962 if (cbBufSize
< *pcbBytesNeeded
)
4964 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4968 if (dwError
== ERROR_SUCCESS
)
4970 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4971 wcscpy(lpStr
, lpDescription
);
4972 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4976 lpServiceDescription
->lpDescription
= NULL
;
4977 dwError
= ERROR_SUCCESS
;
4980 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4983 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
4987 dwError
= ScmReadString(hServiceKey
,
4991 dwError
= ScmReadString(hServiceKey
,
4995 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
4997 if (lpFailureCommand
)
4998 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
5000 if (lpRebootMessage
)
5001 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
5003 if (cbBufSize
< dwRequiredSize
)
5005 *pcbBytesNeeded
= dwRequiredSize
;
5006 dwError
= ERROR_INSUFFICIENT_BUFFER
;
5010 lpFailureActions
->cActions
= 0;
5011 lpFailureActions
->dwResetPeriod
= 0;
5012 lpFailureActions
->lpCommand
= NULL
;
5013 lpFailureActions
->lpRebootMsg
= NULL
;
5014 lpFailureActions
->lpsaActions
= NULL
;
5016 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
5017 if (lpRebootMessage
)
5019 wcscpy(lpStr
, lpRebootMessage
);
5020 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
5021 lpStr
+= wcslen(lpRebootMessage
) + 1;
5024 if (lpFailureCommand
)
5026 wcscpy(lpStr
, lpFailureCommand
);
5027 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
5028 lpStr
+= wcslen(lpRebootMessage
) + 1;
5030 dwError
= STATUS_SUCCESS
;
5035 /* Unlock the service database */
5036 ScmUnlockDatabase();
5038 if (lpDescription
!= NULL
)
5039 HeapFree(GetProcessHeap(), 0, lpDescription
);
5041 if (lpRebootMessage
!= NULL
)
5042 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
5044 if (lpFailureCommand
!= NULL
)
5045 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
5047 if (hServiceKey
!= NULL
)
5048 RegCloseKey(hServiceKey
);
5050 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
5057 DWORD
RQueryServiceStatusEx(
5058 SC_RPC_HANDLE hService
,
5059 SC_STATUS_TYPE InfoLevel
,
5062 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5064 LPSERVICE_STATUS_PROCESS lpStatus
;
5065 PSERVICE_HANDLE hSvc
;
5068 DPRINT("RQueryServiceStatusEx() called\n");
5071 return ERROR_SHUTDOWN_IN_PROGRESS
;
5073 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
5074 return ERROR_INVALID_LEVEL
;
5076 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
5078 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
5079 return ERROR_INSUFFICIENT_BUFFER
;
5081 hSvc
= ScmGetServiceFromHandle(hService
);
5084 DPRINT1("Invalid service handle!\n");
5085 return ERROR_INVALID_HANDLE
;
5088 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5089 SERVICE_QUERY_STATUS
))
5091 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5092 return ERROR_ACCESS_DENIED
;
5095 lpService
= hSvc
->ServiceEntry
;
5096 if (lpService
== NULL
)
5098 DPRINT("lpService == NULL!\n");
5099 return ERROR_INVALID_HANDLE
;
5102 /* Lock the service database shared */
5103 ScmLockDatabaseShared();
5105 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
5107 /* Return service status information */
5108 RtlCopyMemory(lpStatus
,
5110 sizeof(SERVICE_STATUS
));
5112 lpStatus
->dwProcessId
= (lpService
->lpImage
!= NULL
) ? lpService
->lpImage
->dwProcessId
: 0; /* FIXME */
5113 lpStatus
->dwServiceFlags
= 0; /* FIXME */
5115 /* Unlock the service database */
5116 ScmUnlockDatabase();
5118 return ERROR_SUCCESS
;
5123 DWORD
REnumServicesStatusExA(
5124 SC_RPC_HANDLE hSCManager
,
5125 SC_ENUM_TYPE InfoLevel
,
5126 DWORD dwServiceType
,
5127 DWORD dwServiceState
,
5130 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5131 LPBOUNDED_DWORD_256K lpServicesReturned
,
5132 LPBOUNDED_DWORD_256K lpResumeIndex
,
5133 LPCSTR pszGroupName
)
5135 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
5136 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
5137 LPWSTR lpStringPtrW
;
5139 LPWSTR pszGroupNameW
= NULL
;
5141 DWORD dwServiceCount
;
5143 DPRINT("REnumServicesStatusExA() called\n");
5147 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
5150 DPRINT("Failed to allocate buffer!\n");
5151 return ERROR_NOT_ENOUGH_MEMORY
;
5154 MultiByteToWideChar(CP_ACP
,
5159 strlen(pszGroupName
) + 1);
5162 if ((cbBufSize
> 0) && (lpBuffer
))
5164 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
5167 DPRINT("Failed to allocate buffer!\n");
5168 return ERROR_NOT_ENOUGH_MEMORY
;
5172 dwError
= REnumServicesStatusExW(hSCManager
,
5176 (LPBYTE
)lpStatusPtrW
,
5183 /* if no services were returned then we are Done */
5184 if (*lpServicesReturned
== 0)
5187 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
5188 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
5189 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
5190 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
5191 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5193 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
5195 /* Copy the service name */
5196 WideCharToMultiByte(CP_ACP
,
5201 wcslen(lpStringPtrW
),
5205 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5206 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5207 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5209 /* Copy the display name */
5210 WideCharToMultiByte(CP_ACP
,
5215 wcslen(lpStringPtrW
),
5219 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5220 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5221 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5223 /* Copy the status information */
5224 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
5225 &lpStatusPtrW
->ServiceStatusProcess
,
5226 sizeof(SERVICE_STATUS
));
5228 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
5229 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5235 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
5238 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
5240 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
5247 DWORD
REnumServicesStatusExW(
5248 SC_RPC_HANDLE hSCManager
,
5249 SC_ENUM_TYPE InfoLevel
,
5250 DWORD dwServiceType
,
5251 DWORD dwServiceState
,
5254 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5255 LPBOUNDED_DWORD_256K lpServicesReturned
,
5256 LPBOUNDED_DWORD_256K lpResumeIndex
,
5257 LPCWSTR pszGroupName
)
5259 PMANAGER_HANDLE hManager
;
5261 DWORD dwError
= ERROR_SUCCESS
;
5262 PLIST_ENTRY ServiceEntry
;
5263 PSERVICE CurrentService
;
5265 DWORD dwRequiredSize
;
5266 DWORD dwServiceCount
;
5268 DWORD dwLastResumeCount
= 0;
5269 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
5272 DPRINT("REnumServicesStatusExW() called\n");
5275 return ERROR_SHUTDOWN_IN_PROGRESS
;
5277 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
5278 return ERROR_INVALID_LEVEL
;
5280 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
5281 if (hManager
== NULL
)
5283 DPRINT1("Invalid service manager handle!\n");
5284 return ERROR_INVALID_HANDLE
;
5287 *pcbBytesNeeded
= 0;
5288 *lpServicesReturned
= 0;
5290 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
5292 DPRINT("Not a valid Service Type!\n");
5293 return ERROR_INVALID_PARAMETER
;
5296 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
5298 DPRINT("Not a valid Service State!\n");
5299 return ERROR_INVALID_PARAMETER
;
5302 /* Check access rights */
5303 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
5304 SC_MANAGER_ENUMERATE_SERVICE
))
5306 DPRINT("Insufficient access rights! 0x%lx\n",
5307 hManager
->Handle
.DesiredAccess
);
5308 return ERROR_ACCESS_DENIED
;
5312 dwLastResumeCount
= *lpResumeIndex
;
5314 /* Lock the service database shared */
5315 ScmLockDatabaseShared();
5317 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
5318 if (lpService
== NULL
)
5320 dwError
= ERROR_SUCCESS
;
5327 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5328 ServiceEntry
!= &ServiceListHead
;
5329 ServiceEntry
= ServiceEntry
->Flink
)
5331 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5335 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5338 dwState
= SERVICE_ACTIVE
;
5339 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5340 dwState
= SERVICE_INACTIVE
;
5342 if ((dwState
& dwServiceState
) == 0)
5347 if (*pszGroupName
== 0)
5349 if (CurrentService
->lpGroup
!= NULL
)
5354 if ((CurrentService
->lpGroup
== NULL
) ||
5355 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5360 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5361 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5362 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5364 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5366 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5367 dwRequiredSize
+= dwSize
;
5369 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5373 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5379 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5380 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5383 ServiceEntry
!= &ServiceListHead
;
5384 ServiceEntry
= ServiceEntry
->Flink
)
5386 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5390 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5393 dwState
= SERVICE_ACTIVE
;
5394 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5395 dwState
= SERVICE_INACTIVE
;
5397 if ((dwState
& dwServiceState
) == 0)
5402 if (*pszGroupName
== 0)
5404 if (CurrentService
->lpGroup
!= NULL
)
5409 if ((CurrentService
->lpGroup
== NULL
) ||
5410 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5415 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5416 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5417 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5419 dwError
= ERROR_MORE_DATA
;
5422 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5425 *lpResumeIndex
= dwLastResumeCount
;
5427 *lpServicesReturned
= dwServiceCount
;
5428 *pcbBytesNeeded
= dwRequiredSize
;
5430 /* If there was no services that matched */
5431 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5433 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5437 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5438 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5439 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5442 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5443 ServiceEntry
!= &ServiceListHead
;
5444 ServiceEntry
= ServiceEntry
->Flink
)
5446 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5450 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5453 dwState
= SERVICE_ACTIVE
;
5454 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5455 dwState
= SERVICE_INACTIVE
;
5457 if ((dwState
& dwServiceState
) == 0)
5462 if (*pszGroupName
== 0)
5464 if (CurrentService
->lpGroup
!= NULL
)
5469 if ((CurrentService
->lpGroup
== NULL
) ||
5470 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5475 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5476 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5477 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5479 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5481 /* Copy the service name */
5483 CurrentService
->lpServiceName
);
5484 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5485 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5487 /* Copy the display name */
5489 CurrentService
->lpDisplayName
);
5490 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5491 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5493 /* Copy the status information */
5494 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5495 &CurrentService
->Status
,
5496 sizeof(SERVICE_STATUS
));
5497 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
=
5498 (CurrentService
->lpImage
!= NULL
) ? CurrentService
->lpImage
->dwProcessId
: 0; /* FIXME */
5499 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5502 dwRequiredSize
+= dwSize
;
5512 *pcbBytesNeeded
= 0;
5518 /* Unlock the service database */
5519 ScmUnlockDatabase();
5521 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5528 DWORD
RSendTSMessage(
5529 handle_t BindingHandle
) /* FIXME */
5532 return ERROR_CALL_NOT_IMPLEMENTED
;
5537 DWORD
RCreateServiceWOW64A(
5538 handle_t BindingHandle
,
5539 LPSTR lpServiceName
,
5540 LPSTR lpDisplayName
,
5541 DWORD dwDesiredAccess
,
5542 DWORD dwServiceType
,
5544 DWORD dwErrorControl
,
5545 LPSTR lpBinaryPathName
,
5546 LPSTR lpLoadOrderGroup
,
5548 LPBYTE lpDependencies
,
5550 LPSTR lpServiceStartName
,
5553 LPSC_RPC_HANDLE lpServiceHandle
)
5556 return ERROR_CALL_NOT_IMPLEMENTED
;
5561 DWORD
RCreateServiceWOW64W(
5562 handle_t BindingHandle
,
5563 LPWSTR lpServiceName
,
5564 LPWSTR lpDisplayName
,
5565 DWORD dwDesiredAccess
,
5566 DWORD dwServiceType
,
5568 DWORD dwErrorControl
,
5569 LPWSTR lpBinaryPathName
,
5570 LPWSTR lpLoadOrderGroup
,
5572 LPBYTE lpDependencies
,
5574 LPWSTR lpServiceStartName
,
5577 LPSC_RPC_HANDLE lpServiceHandle
)
5580 return ERROR_CALL_NOT_IMPLEMENTED
;
5585 DWORD
RQueryServiceTagInfo(
5586 handle_t BindingHandle
) /* FIXME */
5589 return ERROR_CALL_NOT_IMPLEMENTED
;
5594 DWORD
RNotifyServiceStatusChange(
5595 SC_RPC_HANDLE hService
,
5596 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5597 GUID
*pClientProcessGuid
,
5598 GUID
*pSCMProcessGuid
,
5599 PBOOL pfCreateRemoteQueue
,
5600 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5603 return ERROR_CALL_NOT_IMPLEMENTED
;
5608 DWORD
RGetNotifyResults(
5609 SC_NOTIFY_RPC_HANDLE hNotify
,
5610 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5613 return ERROR_CALL_NOT_IMPLEMENTED
;
5618 DWORD
RCloseNotifyHandle(
5619 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5623 return ERROR_CALL_NOT_IMPLEMENTED
;
5628 DWORD
RControlServiceExA(
5629 SC_RPC_HANDLE hService
,
5634 return ERROR_CALL_NOT_IMPLEMENTED
;
5639 DWORD
RControlServiceExW(
5640 SC_RPC_HANDLE hService
,
5645 return ERROR_CALL_NOT_IMPLEMENTED
;
5650 DWORD
RSendPnPMessage(
5651 handle_t BindingHandle
) /* FIXME */
5654 return ERROR_CALL_NOT_IMPLEMENTED
;
5659 DWORD
RValidatePnPService(
5660 handle_t BindingHandle
) /* FIXME */
5663 return ERROR_CALL_NOT_IMPLEMENTED
;
5668 DWORD
ROpenServiceStatusHandle(
5669 handle_t BindingHandle
) /* FIXME */
5672 return ERROR_CALL_NOT_IMPLEMENTED
;
5678 handle_t BindingHandle
) /* FIXME */
5681 return ERROR_CALL_NOT_IMPLEMENTED
;
5685 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5687 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5691 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5693 HeapFree(GetProcessHeap(), 0, ptr
);
5697 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5702 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5707 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)