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
= (MANAGER_HANDLE
*) HeapAlloc(GetProcessHeap(),
158 sizeof(MANAGER_HANDLE
) + (wcslen(lpDatabaseName
) + 1) * sizeof(WCHAR
));
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
= (SERVICE_HANDLE
*) 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
= (LPWSTR
)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
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1582 if (*RelativeName
== NULL
)
1584 DPRINT("Error allocating memory for boot driver name!\n");
1585 return ERROR_NOT_ENOUGH_MEMORY
;
1589 wcscpy(*RelativeName
, CanonName
);
1591 DPRINT("Bootdriver name %S\n", *RelativeName
);
1592 return ERROR_SUCCESS
;
1595 /* If it has %SystemRoot% prefix, substitute it to \System*/
1596 if (ServiceNameLen
> 13 &&
1597 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1599 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1600 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1602 if (*RelativeName
== NULL
)
1604 DPRINT("Error allocating memory for boot driver name!\n");
1605 return ERROR_NOT_ENOUGH_MEMORY
;
1609 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1610 wcscat(*RelativeName
, CanonName
+ 13);
1612 DPRINT("Bootdriver name %S\n", *RelativeName
);
1613 return ERROR_SUCCESS
;
1616 /* Get buffer size needed for expanding env strings */
1617 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1619 if (BufferSize
<= 1)
1621 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1622 return ERROR_INVALID_ENVIRONMENT
;
1625 /* Allocate memory, since the size is known now */
1626 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1629 DPRINT("Error allocating memory for boot driver name!\n");
1630 return ERROR_NOT_ENOUGH_MEMORY
;
1634 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1637 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1638 LocalFree(Expanded
);
1639 return ERROR_NOT_ENOUGH_MEMORY
;
1642 /* Convert to NY-style path */
1643 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1645 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1646 return ERROR_INVALID_ENVIRONMENT
;
1649 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1651 /* No need to keep the dos-path anymore */
1652 LocalFree(Expanded
);
1654 /* Copy it to the allocated place */
1655 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1658 DPRINT("Error allocating memory for boot driver name!\n");
1659 return ERROR_NOT_ENOUGH_MEMORY
;
1662 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1663 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1664 Expanded
[ExpandedLen
] = 0;
1666 if (ServiceNameLen
> ExpandedLen
&&
1667 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1669 /* Only \SystemRoot\ is missing */
1670 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1671 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1672 if (*RelativeName
== NULL
)
1674 DPRINT("Error allocating memory for boot driver name!\n");
1675 LocalFree(Expanded
);
1676 return ERROR_NOT_ENOUGH_MEMORY
;
1679 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1680 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1682 RtlFreeUnicodeString(&NtPathName
);
1683 return ERROR_SUCCESS
;
1686 /* The most complex case starts here */
1687 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1688 InitializeObjectAttributes(&ObjectAttributes
,
1690 OBJ_CASE_INSENSITIVE
,
1694 /* Open this symlink */
1695 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1697 if (NT_SUCCESS(Status
))
1699 LinkTarget
.Length
= 0;
1700 LinkTarget
.MaximumLength
= 0;
1702 DPRINT("Opened symbolic link object\n");
1704 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1705 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1707 /* Check if required buffer size is sane */
1708 if (BufferSize
> 0xFFFD)
1710 DPRINT("Too large buffer required\n");
1713 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1714 LocalFree(Expanded
);
1715 return ERROR_NOT_ENOUGH_MEMORY
;
1718 /* Alloc the string */
1719 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1720 if (!LinkTarget
.Buffer
)
1722 DPRINT("Unable to alloc buffer\n");
1723 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1724 LocalFree(Expanded
);
1725 return ERROR_NOT_ENOUGH_MEMORY
;
1728 /* Do a real query now */
1729 LinkTarget
.Length
= (USHORT
)BufferSize
;
1730 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1732 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1733 if (NT_SUCCESS(Status
))
1735 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1737 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1738 if ((ServiceNameLen
> ExpandedLen
) &&
1739 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1741 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1742 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1744 if (*RelativeName
== NULL
)
1746 DPRINT("Unable to alloc buffer\n");
1747 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1748 LocalFree(Expanded
);
1749 RtlFreeUnicodeString(&NtPathName
);
1750 return ERROR_NOT_ENOUGH_MEMORY
;
1753 /* Copy it over, substituting the first part
1755 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1756 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1759 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1760 LocalFree(Expanded
);
1761 RtlFreeUnicodeString(&NtPathName
);
1763 /* Return success */
1764 return ERROR_SUCCESS
;
1768 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1769 LocalFree(Expanded
);
1770 RtlFreeUnicodeString(&NtPathName
);
1771 return ERROR_INVALID_PARAMETER
;
1776 DPRINT("Error, Status = %08X\n", Status
);
1777 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1778 LocalFree(Expanded
);
1779 RtlFreeUnicodeString(&NtPathName
);
1780 return ERROR_INVALID_PARAMETER
;
1785 DPRINT("Error, Status = %08X\n", Status
);
1786 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1787 LocalFree(Expanded
);
1788 RtlFreeUnicodeString(&NtPathName
);
1789 return ERROR_INVALID_PARAMETER
;
1794 DPRINT("Error, Status = %08X\n", Status
);
1795 LocalFree(Expanded
);
1796 return ERROR_INVALID_PARAMETER
;
1800 *RelativeName
= NULL
;
1801 return ERROR_INVALID_PARAMETER
;
1805 ScmCanonDriverImagePath(DWORD dwStartType
,
1806 const wchar_t *lpServiceName
,
1807 wchar_t **lpCanonName
)
1809 DWORD ServiceNameLen
, Result
;
1810 UNICODE_STRING NtServiceName
;
1811 WCHAR
*RelativeName
;
1812 const WCHAR
*SourceName
= lpServiceName
;
1814 /* Calculate the length of the service's name */
1815 ServiceNameLen
= wcslen(lpServiceName
);
1817 /* 12 is wcslen(L"\\SystemRoot\\") */
1818 if (ServiceNameLen
> 12 &&
1819 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1821 /* SystemRoot prefix is already included */
1823 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1825 if (*lpCanonName
== NULL
)
1827 DPRINT("Error allocating memory for canonized service name!\n");
1828 return ERROR_NOT_ENOUGH_MEMORY
;
1831 /* If it's a boot-time driver, it must be systemroot relative */
1832 if (dwStartType
== SERVICE_BOOT_START
)
1836 wcscpy(*lpCanonName
, SourceName
);
1838 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1842 /* Check if it has %SystemRoot% (len=13) */
1843 if (ServiceNameLen
> 13 &&
1844 !_wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1846 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1847 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1849 if (*lpCanonName
== NULL
)
1851 DPRINT("Error allocating memory for canonized service name!\n");
1852 return ERROR_NOT_ENOUGH_MEMORY
;
1855 /* If it's a boot-time driver, it must be systemroot relative */
1856 if (dwStartType
== SERVICE_BOOT_START
)
1857 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1859 wcscat(*lpCanonName
, lpServiceName
+ 13);
1861 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1865 /* Check if it's a relative path name */
1866 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1868 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1870 if (*lpCanonName
== NULL
)
1872 DPRINT("Error allocating memory for canonized service name!\n");
1873 return ERROR_NOT_ENOUGH_MEMORY
;
1876 /* Just copy it over without changing */
1877 wcscpy(*lpCanonName
, lpServiceName
);
1882 /* It seems to be a DOS path, convert it */
1883 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1885 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
1886 return ERROR_INVALID_PARAMETER
;
1889 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1891 if (*lpCanonName
== NULL
)
1893 DPRINT("Error allocating memory for canonized service name!\n");
1894 RtlFreeUnicodeString(&NtServiceName
);
1895 return ERROR_NOT_ENOUGH_MEMORY
;
1898 /* Copy the string */
1899 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1901 /* The unicode string is not needed anymore */
1902 RtlFreeUnicodeString(&NtServiceName
);
1904 if (dwStartType
!= SERVICE_BOOT_START
)
1906 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1910 /* The service is boot-started, so must be relative */
1911 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1914 /* There is a problem, free name and return */
1915 LocalFree(*lpCanonName
);
1916 DPRINT("Error converting named!\n");
1920 ASSERT(RelativeName
);
1922 /* Copy that string */
1923 wcscpy(*lpCanonName
, RelativeName
+ 12);
1925 /* Free the allocated buffer */
1926 LocalFree(RelativeName
);
1928 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1936 DWORD
RCreateServiceW(
1937 SC_RPC_HANDLE hSCManager
,
1938 LPCWSTR lpServiceName
,
1939 LPCWSTR lpDisplayName
,
1940 DWORD dwDesiredAccess
,
1941 DWORD dwServiceType
,
1943 DWORD dwErrorControl
,
1944 LPCWSTR lpBinaryPathName
,
1945 LPCWSTR lpLoadOrderGroup
,
1947 LPBYTE lpDependencies
,
1949 LPCWSTR lpServiceStartName
,
1952 LPSC_RPC_HANDLE lpServiceHandle
)
1954 PMANAGER_HANDLE hManager
;
1955 DWORD dwError
= ERROR_SUCCESS
;
1956 PSERVICE lpService
= NULL
;
1957 SC_HANDLE hServiceHandle
= NULL
;
1958 LPWSTR lpImagePath
= NULL
;
1959 HKEY hServiceKey
= NULL
;
1960 LPWSTR lpObjectName
;
1962 DPRINT("RCreateServiceW() called\n");
1963 DPRINT("lpServiceName = %S\n", lpServiceName
);
1964 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1965 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1966 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1967 DPRINT("dwStartType = %lu\n", dwStartType
);
1968 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1969 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1970 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1971 DPRINT("lpdwTagId = %p\n", lpdwTagId
);
1974 return ERROR_SHUTDOWN_IN_PROGRESS
;
1976 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
1977 if (hManager
== NULL
)
1979 DPRINT1("Invalid service manager handle!\n");
1980 return ERROR_INVALID_HANDLE
;
1983 /* Check access rights */
1984 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1985 SC_MANAGER_CREATE_SERVICE
))
1987 DPRINT("Insufficient access rights! 0x%lx\n",
1988 hManager
->Handle
.DesiredAccess
);
1989 return ERROR_ACCESS_DENIED
;
1992 if (wcslen(lpServiceName
) == 0)
1994 return ERROR_INVALID_NAME
;
1997 if (wcslen(lpBinaryPathName
) == 0)
1999 return ERROR_INVALID_PARAMETER
;
2002 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
2003 (lpServiceStartName
))
2005 return ERROR_INVALID_PARAMETER
;
2008 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
2009 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
2010 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
2012 return ERROR_INVALID_PARAMETER
;
2015 if (dwStartType
> SERVICE_DISABLED
)
2017 return ERROR_INVALID_PARAMETER
;
2020 if (lpdwTagId
&& (!lpLoadOrderGroup
|| !*lpLoadOrderGroup
))
2022 return ERROR_INVALID_PARAMETER
;
2025 /* Lock the service database exclusively */
2026 ScmLockDatabaseExclusive();
2028 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2031 /* Unlock the service database */
2032 ScmUnlockDatabase();
2034 /* check if it is marked for deletion */
2035 if (lpService
->bDeleted
)
2036 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2037 /* Return Error exist */
2038 return ERROR_SERVICE_EXISTS
;
2041 if (lpDisplayName
!= NULL
&&
2042 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
2044 /* Unlock the service database */
2045 ScmUnlockDatabase();
2047 return ERROR_DUPLICATE_SERVICE_NAME
;
2050 if (dwServiceType
& SERVICE_DRIVER
)
2052 dwError
= ScmCanonDriverImagePath(dwStartType
,
2055 if (dwError
!= ERROR_SUCCESS
)
2060 if (dwStartType
== SERVICE_BOOT_START
||
2061 dwStartType
== SERVICE_SYSTEM_START
)
2063 /* Unlock the service database */
2064 ScmUnlockDatabase();
2066 return ERROR_INVALID_PARAMETER
;
2070 /* Allocate a new service entry */
2071 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
2073 if (dwError
!= ERROR_SUCCESS
)
2076 /* Fill the new service entry */
2077 lpService
->Status
.dwServiceType
= dwServiceType
;
2078 lpService
->dwStartType
= dwStartType
;
2079 lpService
->dwErrorControl
= dwErrorControl
;
2081 /* Fill the display name */
2082 if (lpDisplayName
!= NULL
&&
2083 *lpDisplayName
!= 0 &&
2084 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
2086 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
2087 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2088 if (lpService
->lpDisplayName
== NULL
)
2090 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2093 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
2096 /* Assign the service to a group */
2097 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2099 dwError
= ScmSetServiceGroup(lpService
,
2101 if (dwError
!= ERROR_SUCCESS
)
2105 /* Assign a new tag */
2106 if (lpdwTagId
!= NULL
)
2108 dwError
= ScmAssignNewTag(lpService
);
2109 if (dwError
!= ERROR_SUCCESS
)
2113 /* Write service data to the registry */
2114 /* Create the service key */
2115 dwError
= ScmCreateServiceKey(lpServiceName
,
2118 if (dwError
!= ERROR_SUCCESS
)
2121 /* Set the display name */
2122 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2124 RegSetValueExW(hServiceKey
,
2128 (LPBYTE
)lpDisplayName
,
2129 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2132 /* Set the service type */
2133 dwError
= RegSetValueExW(hServiceKey
,
2137 (LPBYTE
)&dwServiceType
,
2139 if (dwError
!= ERROR_SUCCESS
)
2142 /* Set the start value */
2143 dwError
= RegSetValueExW(hServiceKey
,
2147 (LPBYTE
)&dwStartType
,
2149 if (dwError
!= ERROR_SUCCESS
)
2152 /* Set the error control value */
2153 dwError
= RegSetValueExW(hServiceKey
,
2157 (LPBYTE
)&dwErrorControl
,
2159 if (dwError
!= ERROR_SUCCESS
)
2162 /* Set the image path */
2163 if (dwServiceType
& SERVICE_WIN32
)
2165 dwError
= RegSetValueExW(hServiceKey
,
2169 (LPBYTE
)lpBinaryPathName
,
2170 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
2171 if (dwError
!= ERROR_SUCCESS
)
2174 else if (dwServiceType
& SERVICE_DRIVER
)
2176 dwError
= RegSetValueExW(hServiceKey
,
2180 (LPBYTE
)lpImagePath
,
2181 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2182 if (dwError
!= ERROR_SUCCESS
)
2186 /* Set the group name */
2187 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2189 dwError
= RegSetValueExW(hServiceKey
,
2193 (LPBYTE
)lpLoadOrderGroup
,
2194 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
2195 if (dwError
!= ERROR_SUCCESS
)
2199 if (lpdwTagId
!= NULL
)
2201 dwError
= RegSetValueExW(hServiceKey
,
2205 (LPBYTE
)&lpService
->dwTag
,
2207 if (dwError
!= ERROR_SUCCESS
)
2211 /* Write dependencies */
2212 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2214 dwError
= ScmWriteDependencies(hServiceKey
,
2215 (LPWSTR
)lpDependencies
,
2217 if (dwError
!= ERROR_SUCCESS
)
2221 /* Write service start name */
2222 if (dwServiceType
& SERVICE_WIN32
)
2224 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2225 dwError
= RegSetValueExW(hServiceKey
,
2229 (LPBYTE
)lpObjectName
,
2230 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
2231 if (dwError
!= ERROR_SUCCESS
)
2235 if (lpPassword
!= NULL
)
2237 /* FIXME: Write password */
2240 dwError
= ScmCreateServiceHandle(lpService
,
2242 if (dwError
!= ERROR_SUCCESS
)
2245 dwError
= ScmCheckAccess(hServiceHandle
,
2247 if (dwError
!= ERROR_SUCCESS
)
2250 lpService
->dwRefCount
= 1;
2251 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2254 /* Unlock the service database */
2255 ScmUnlockDatabase();
2257 if (hServiceKey
!= NULL
)
2258 RegCloseKey(hServiceKey
);
2260 if (dwError
== ERROR_SUCCESS
)
2262 DPRINT("hService %p\n", hServiceHandle
);
2263 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2265 if (lpdwTagId
!= NULL
)
2266 *lpdwTagId
= lpService
->dwTag
;
2270 /* Release the display name buffer */
2271 if (lpService
->lpServiceName
!= NULL
)
2272 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2276 /* Remove the service handle */
2277 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2280 if (lpService
!= NULL
)
2282 /* FIXME: remove the service entry */
2286 if (lpImagePath
!= NULL
)
2287 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2289 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2296 DWORD
REnumDependentServicesW(
2297 SC_RPC_HANDLE hService
,
2298 DWORD dwServiceState
,
2301 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2302 LPBOUNDED_DWORD_256K lpServicesReturned
)
2304 DWORD dwError
= ERROR_SUCCESS
;
2305 DWORD dwServicesReturned
= 0;
2306 DWORD dwServiceCount
;
2307 HKEY hServicesKey
= NULL
;
2308 PSERVICE_HANDLE hSvc
;
2309 PSERVICE lpService
= NULL
;
2310 PSERVICE
*lpServicesArray
= NULL
;
2311 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2314 *pcbBytesNeeded
= 0;
2315 *lpServicesReturned
= 0;
2317 DPRINT("REnumDependentServicesW() called\n");
2319 hSvc
= ScmGetServiceFromHandle(hService
);
2322 DPRINT1("Invalid service handle!\n");
2323 return ERROR_INVALID_HANDLE
;
2326 lpService
= hSvc
->ServiceEntry
;
2328 /* Check access rights */
2329 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2330 SC_MANAGER_ENUMERATE_SERVICE
))
2332 DPRINT("Insufficient access rights! 0x%lx\n",
2333 hSvc
->Handle
.DesiredAccess
);
2334 return ERROR_ACCESS_DENIED
;
2337 /* Open the Services Reg key */
2338 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2339 L
"System\\CurrentControlSet\\Services",
2343 if (dwError
!= ERROR_SUCCESS
)
2346 /* First determine the bytes needed and get the number of dependent services */
2347 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2352 &dwServicesReturned
);
2353 if (dwError
!= ERROR_SUCCESS
)
2356 /* If buffer size is less than the bytes needed or pointer is null */
2357 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2359 dwError
= ERROR_MORE_DATA
;
2363 /* Allocate memory for array of service pointers */
2364 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2366 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2367 if (!lpServicesArray
)
2369 DPRINT("Could not allocate a buffer!!\n");
2370 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2374 dwServicesReturned
= 0;
2375 *pcbBytesNeeded
= 0;
2377 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2382 &dwServicesReturned
);
2383 if (dwError
!= ERROR_SUCCESS
)
2388 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2389 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2391 /* Copy EnumDepenedentService to Buffer */
2392 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2394 lpService
= lpServicesArray
[dwServiceCount
];
2396 /* Copy status info */
2397 memcpy(&lpServicesPtr
->ServiceStatus
,
2399 sizeof(SERVICE_STATUS
));
2401 /* Copy display name */
2402 wcscpy(lpStr
, lpService
->lpDisplayName
);
2403 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2404 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2406 /* Copy service name */
2407 wcscpy(lpStr
, lpService
->lpServiceName
);
2408 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2409 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2414 *lpServicesReturned
= dwServicesReturned
;
2417 if (lpServicesArray
!= NULL
)
2418 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2420 RegCloseKey(hServicesKey
);
2422 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2429 DWORD
REnumServicesStatusW(
2430 SC_RPC_HANDLE hSCManager
,
2431 DWORD dwServiceType
,
2432 DWORD dwServiceState
,
2435 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2436 LPBOUNDED_DWORD_256K lpServicesReturned
,
2437 LPBOUNDED_DWORD_256K lpResumeHandle
)
2439 PMANAGER_HANDLE hManager
;
2441 DWORD dwError
= ERROR_SUCCESS
;
2442 PLIST_ENTRY ServiceEntry
;
2443 PSERVICE CurrentService
;
2445 DWORD dwRequiredSize
;
2446 DWORD dwServiceCount
;
2448 DWORD dwLastResumeCount
= 0;
2449 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2452 DPRINT("REnumServicesStatusW() called\n");
2455 return ERROR_SHUTDOWN_IN_PROGRESS
;
2457 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2458 if (hManager
== NULL
)
2460 DPRINT1("Invalid service manager handle!\n");
2461 return ERROR_INVALID_HANDLE
;
2465 *pcbBytesNeeded
= 0;
2466 *lpServicesReturned
= 0;
2468 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2470 DPRINT("Not a valid Service Type!\n");
2471 return ERROR_INVALID_PARAMETER
;
2474 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2476 DPRINT("Not a valid Service State!\n");
2477 return ERROR_INVALID_PARAMETER
;
2480 /* Check access rights */
2481 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2482 SC_MANAGER_ENUMERATE_SERVICE
))
2484 DPRINT("Insufficient access rights! 0x%lx\n",
2485 hManager
->Handle
.DesiredAccess
);
2486 return ERROR_ACCESS_DENIED
;
2490 dwLastResumeCount
= *lpResumeHandle
;
2492 /* Lock the service database shared */
2493 ScmLockDatabaseShared();
2495 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2496 if (lpService
== NULL
)
2498 dwError
= ERROR_SUCCESS
;
2505 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2506 ServiceEntry
!= &ServiceListHead
;
2507 ServiceEntry
= ServiceEntry
->Flink
)
2509 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2513 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2516 dwState
= SERVICE_ACTIVE
;
2517 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2518 dwState
= SERVICE_INACTIVE
;
2520 if ((dwState
& dwServiceState
) == 0)
2523 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2524 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2525 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2527 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2529 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2533 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2534 dwRequiredSize
+= dwSize
;
2536 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2539 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2540 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2543 ServiceEntry
!= &ServiceListHead
;
2544 ServiceEntry
= ServiceEntry
->Flink
)
2546 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2550 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2553 dwState
= SERVICE_ACTIVE
;
2554 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2555 dwState
= SERVICE_INACTIVE
;
2557 if ((dwState
& dwServiceState
) == 0)
2560 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2561 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2562 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2564 dwError
= ERROR_MORE_DATA
;
2567 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2570 *lpResumeHandle
= dwLastResumeCount
;
2572 *lpServicesReturned
= dwServiceCount
;
2573 *pcbBytesNeeded
= dwRequiredSize
;
2575 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2576 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2577 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2580 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2581 ServiceEntry
!= &ServiceListHead
;
2582 ServiceEntry
= ServiceEntry
->Flink
)
2584 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2588 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2591 dwState
= SERVICE_ACTIVE
;
2592 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2593 dwState
= SERVICE_INACTIVE
;
2595 if ((dwState
& dwServiceState
) == 0)
2598 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2599 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2600 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2602 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2605 /* Copy the service name */
2606 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2607 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2608 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2610 /* Copy the display name */
2611 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2612 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2613 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2615 /* Copy the status information */
2616 memcpy(&lpStatusPtr
->ServiceStatus
,
2617 &CurrentService
->Status
,
2618 sizeof(SERVICE_STATUS
));
2621 dwRequiredSize
+= dwSize
;
2626 *pcbBytesNeeded
= 0;
2627 if (lpResumeHandle
) *lpResumeHandle
= 0;
2631 /* Unlock the service database */
2632 ScmUnlockDatabase();
2634 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2641 DWORD
ROpenSCManagerW(
2642 LPWSTR lpMachineName
,
2643 LPWSTR lpDatabaseName
,
2644 DWORD dwDesiredAccess
,
2645 LPSC_RPC_HANDLE lpScHandle
)
2650 DPRINT("ROpenSCManagerW() called\n");
2651 DPRINT("lpMachineName = %p\n", lpMachineName
);
2652 DPRINT("lpMachineName: %S\n", lpMachineName
);
2653 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2654 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2655 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2658 return ERROR_SHUTDOWN_IN_PROGRESS
;
2661 return ERROR_INVALID_PARAMETER
;
2663 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2665 if (dwError
!= ERROR_SUCCESS
)
2667 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2671 /* Check the desired access */
2672 dwError
= ScmCheckAccess(hHandle
,
2673 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2674 if (dwError
!= ERROR_SUCCESS
)
2676 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2677 HeapFree(GetProcessHeap(), 0, hHandle
);
2681 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2682 DPRINT("*hScm = %p\n", *lpScHandle
);
2684 DPRINT("ROpenSCManagerW() done\n");
2686 return ERROR_SUCCESS
;
2691 DWORD
ROpenServiceW(
2692 SC_RPC_HANDLE hSCManager
,
2693 LPWSTR lpServiceName
,
2694 DWORD dwDesiredAccess
,
2695 LPSC_RPC_HANDLE lpServiceHandle
)
2698 PMANAGER_HANDLE hManager
;
2700 DWORD dwError
= ERROR_SUCCESS
;
2702 DPRINT("ROpenServiceW() called\n");
2703 DPRINT("hSCManager = %p\n", hSCManager
);
2704 DPRINT("lpServiceName = %p\n", lpServiceName
);
2705 DPRINT("lpServiceName: %S\n", lpServiceName
);
2706 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2709 return ERROR_SHUTDOWN_IN_PROGRESS
;
2711 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2712 if (hManager
== NULL
)
2714 DPRINT1("Invalid service manager handle!\n");
2715 return ERROR_INVALID_HANDLE
;
2718 if (!lpServiceHandle
)
2719 return ERROR_INVALID_PARAMETER
;
2722 return ERROR_INVALID_ADDRESS
;
2724 /* Lock the service database exclusive */
2725 ScmLockDatabaseExclusive();
2727 /* Get service database entry */
2728 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2729 if (lpService
== NULL
)
2731 DPRINT("Could not find a service!\n");
2732 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
2736 /* Create a service handle */
2737 dwError
= ScmCreateServiceHandle(lpService
,
2739 if (dwError
!= ERROR_SUCCESS
)
2741 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2745 /* Check the desired access */
2746 dwError
= ScmCheckAccess(hHandle
,
2748 if (dwError
!= ERROR_SUCCESS
)
2750 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2751 HeapFree(GetProcessHeap(), 0, hHandle
);
2755 lpService
->dwRefCount
++;
2756 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2758 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2759 DPRINT("*hService = %p\n", *lpServiceHandle
);
2762 /* Unlock the service database */
2763 ScmUnlockDatabase();
2765 DPRINT("ROpenServiceW() done\n");
2772 DWORD
RQueryServiceConfigW(
2773 SC_RPC_HANDLE hService
,
2774 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2776 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2778 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2779 DWORD dwError
= ERROR_SUCCESS
;
2780 PSERVICE_HANDLE hSvc
;
2781 PSERVICE lpService
= NULL
;
2782 HKEY hServiceKey
= NULL
;
2783 LPWSTR lpImagePath
= NULL
;
2784 LPWSTR lpServiceStartName
= NULL
;
2785 LPWSTR lpDependencies
= NULL
;
2786 DWORD dwDependenciesLength
= 0;
2787 DWORD dwRequiredSize
;
2788 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2789 WCHAR lpEmptyString
[] = {0,0};
2792 DPRINT("RQueryServiceConfigW() called\n");
2795 return ERROR_SHUTDOWN_IN_PROGRESS
;
2797 hSvc
= ScmGetServiceFromHandle(hService
);
2800 DPRINT1("Invalid service handle!\n");
2801 return ERROR_INVALID_HANDLE
;
2804 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2805 SERVICE_QUERY_CONFIG
))
2807 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2808 return ERROR_ACCESS_DENIED
;
2811 lpService
= hSvc
->ServiceEntry
;
2812 if (lpService
== NULL
)
2814 DPRINT("lpService == NULL!\n");
2815 return ERROR_INVALID_HANDLE
;
2818 /* Lock the service database shared */
2819 ScmLockDatabaseShared();
2821 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2824 if (dwError
!= ERROR_SUCCESS
)
2827 /* Read the image path */
2828 dwError
= ScmReadString(hServiceKey
,
2831 if (dwError
!= ERROR_SUCCESS
)
2834 /* Read the service start name */
2835 ScmReadString(hServiceKey
,
2837 &lpServiceStartName
);
2839 /* Read the dependencies */
2840 ScmReadDependencies(hServiceKey
,
2842 &dwDependenciesLength
);
2844 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2846 if (lpImagePath
!= NULL
)
2847 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2849 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2851 if (lpService
->lpGroup
!= NULL
)
2852 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2854 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2856 if (lpDependencies
!= NULL
)
2857 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2859 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2861 if (lpServiceStartName
!= NULL
)
2862 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2864 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2866 if (lpService
->lpDisplayName
!= NULL
)
2867 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2869 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2871 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2873 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2877 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2878 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2879 lpConfig
->dwStartType
= lpService
->dwStartType
;
2880 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2881 lpConfig
->dwTagId
= lpService
->dwTag
;
2883 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2885 /* Append the image path */
2886 if (lpImagePath
!= NULL
)
2888 wcscpy(lpStr
, lpImagePath
);
2892 wcscpy(lpStr
, lpEmptyString
);
2895 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2896 lpStr
+= (wcslen(lpStr
) + 1);
2898 /* Append the group name */
2899 if (lpService
->lpGroup
!= NULL
)
2901 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2905 wcscpy(lpStr
, lpEmptyString
);
2908 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2909 lpStr
+= (wcslen(lpStr
) + 1);
2911 /* Append Dependencies */
2912 if (lpDependencies
!= NULL
)
2916 dwDependenciesLength
* sizeof(WCHAR
));
2920 wcscpy(lpStr
, lpEmptyString
);
2923 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2924 if (lpDependencies
!= NULL
)
2925 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2927 lpStr
+= (wcslen(lpStr
) + 1);
2929 /* Append the service start name */
2930 if (lpServiceStartName
!= NULL
)
2932 wcscpy(lpStr
, lpServiceStartName
);
2936 wcscpy(lpStr
, lpEmptyString
);
2939 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2940 lpStr
+= (wcslen(lpStr
) + 1);
2942 /* Append the display name */
2943 if (lpService
->lpDisplayName
!= NULL
)
2945 wcscpy(lpStr
, lpService
->lpDisplayName
);
2949 wcscpy(lpStr
, lpEmptyString
);
2952 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2955 if (pcbBytesNeeded
!= NULL
)
2956 *pcbBytesNeeded
= dwRequiredSize
;
2959 /* Unlock the service database */
2960 ScmUnlockDatabase();
2962 if (lpImagePath
!= NULL
)
2963 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2965 if (lpServiceStartName
!= NULL
)
2966 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2968 if (lpDependencies
!= NULL
)
2969 HeapFree(GetProcessHeap(), 0, lpDependencies
);
2971 if (hServiceKey
!= NULL
)
2972 RegCloseKey(hServiceKey
);
2974 DPRINT("RQueryServiceConfigW() done\n");
2981 DWORD
RQueryServiceLockStatusW(
2982 SC_RPC_HANDLE hSCManager
,
2983 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2985 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2988 return ERROR_CALL_NOT_IMPLEMENTED
;
2993 DWORD
RStartServiceW(
2994 SC_RPC_HANDLE hService
,
2996 LPSTRING_PTRSW argv
)
2998 DWORD dwError
= ERROR_SUCCESS
;
2999 PSERVICE_HANDLE hSvc
;
3000 PSERVICE lpService
= NULL
;
3003 DPRINT("RStartServiceW(%p %lu %p) called\n", hService
, argc
, argv
);
3004 DPRINT(" argc: %lu\n", argc
);
3007 for (i
= 0; i
< argc
; i
++)
3009 DPRINT(" argv[%lu]: %S\n", i
, argv
[i
]);
3014 return ERROR_SHUTDOWN_IN_PROGRESS
;
3016 hSvc
= ScmGetServiceFromHandle(hService
);
3019 DPRINT1("Invalid service handle!\n");
3020 return ERROR_INVALID_HANDLE
;
3023 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3026 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3027 return ERROR_ACCESS_DENIED
;
3030 lpService
= hSvc
->ServiceEntry
;
3031 if (lpService
== NULL
)
3033 DPRINT("lpService == NULL!\n");
3034 return ERROR_INVALID_HANDLE
;
3037 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3038 return ERROR_SERVICE_DISABLED
;
3040 if (lpService
->bDeleted
)
3041 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3043 /* Start the service */
3044 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
3051 DWORD
RGetServiceDisplayNameW(
3052 SC_RPC_HANDLE hSCManager
,
3053 LPCWSTR lpServiceName
,
3054 LPWSTR lpDisplayName
,
3057 // PMANAGER_HANDLE hManager;
3062 DPRINT("RGetServiceDisplayNameW() called\n");
3063 DPRINT("hSCManager = %p\n", hSCManager
);
3064 DPRINT("lpServiceName: %S\n", lpServiceName
);
3065 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3066 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3068 // hManager = (PMANAGER_HANDLE)hSCManager;
3069 // if (hManager->Handle.Tag != MANAGER_TAG)
3071 // DPRINT("Invalid manager handle!\n");
3072 // return ERROR_INVALID_HANDLE;
3075 /* Get service database entry */
3076 lpService
= ScmGetServiceEntryByName(lpServiceName
);
3077 if (lpService
== NULL
)
3079 DPRINT("Could not find a service!\n");
3081 /* If the service could not be found and lpcchBuffer is less than 2, windows
3082 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3083 if (*lpcchBuffer
< 2)
3086 if (lpDisplayName
!= NULL
)
3088 *lpDisplayName
= '\0';
3092 return ERROR_SERVICE_DOES_NOT_EXIST
;
3095 if (!lpService
->lpDisplayName
)
3097 dwLength
= wcslen(lpService
->lpServiceName
);
3099 if (lpDisplayName
!= NULL
&&
3100 *lpcchBuffer
> dwLength
)
3102 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
3107 dwLength
= wcslen(lpService
->lpDisplayName
);
3109 if (lpDisplayName
!= NULL
&&
3110 *lpcchBuffer
> dwLength
)
3112 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
3116 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3118 *lpcchBuffer
= dwLength
;
3125 DWORD
RGetServiceKeyNameW(
3126 SC_RPC_HANDLE hSCManager
,
3127 LPCWSTR lpDisplayName
,
3128 LPWSTR lpServiceName
,
3131 // PMANAGER_HANDLE hManager;
3136 DPRINT("RGetServiceKeyNameW() called\n");
3137 DPRINT("hSCManager = %p\n", hSCManager
);
3138 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
3139 DPRINT("lpServiceName: %p\n", lpServiceName
);
3140 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3142 // hManager = (PMANAGER_HANDLE)hSCManager;
3143 // if (hManager->Handle.Tag != MANAGER_TAG)
3145 // DPRINT("Invalid manager handle!\n");
3146 // return ERROR_INVALID_HANDLE;
3149 /* Get service database entry */
3150 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
3151 if (lpService
== NULL
)
3153 DPRINT("Could not find a service!\n");
3155 /* If the service could not be found and lpcchBuffer is less than 2, windows
3156 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3157 if (*lpcchBuffer
< 2)
3160 if (lpServiceName
!= NULL
)
3162 *lpServiceName
= '\0';
3166 return ERROR_SERVICE_DOES_NOT_EXIST
;
3169 dwLength
= wcslen(lpService
->lpServiceName
);
3171 if (lpServiceName
!= NULL
&&
3172 *lpcchBuffer
> dwLength
)
3174 wcscpy(lpServiceName
, lpService
->lpServiceName
);
3175 *lpcchBuffer
= dwLength
;
3176 return ERROR_SUCCESS
;
3179 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3181 *lpcchBuffer
= dwLength
;
3188 DWORD
RI_ScSetServiceBitsA(
3189 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3190 DWORD dwServiceBits
,
3192 int bUpdateImmediately
,
3196 return ERROR_CALL_NOT_IMPLEMENTED
;
3201 DWORD
RChangeServiceConfigA(
3202 SC_RPC_HANDLE hService
,
3203 DWORD dwServiceType
,
3205 DWORD dwErrorControl
,
3206 LPSTR lpBinaryPathName
,
3207 LPSTR lpLoadOrderGroup
,
3209 LPSTR lpDependencies
,
3211 LPSTR lpServiceStartName
,
3214 LPSTR lpDisplayName
)
3216 DWORD dwError
= ERROR_SUCCESS
;
3217 PSERVICE_HANDLE hSvc
;
3218 PSERVICE lpService
= NULL
;
3219 HKEY hServiceKey
= NULL
;
3220 LPWSTR lpDisplayNameW
= NULL
;
3221 // LPWSTR lpBinaryPathNameW = NULL;
3222 LPWSTR lpLoadOrderGroupW
= NULL
;
3223 LPWSTR lpDependenciesW
= NULL
;
3224 // LPWSTR lpPasswordW = NULL;
3226 DPRINT("RChangeServiceConfigA() called\n");
3227 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3228 DPRINT("dwStartType = %lu\n", dwStartType
);
3229 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3230 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3231 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3232 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3235 return ERROR_SHUTDOWN_IN_PROGRESS
;
3237 hSvc
= ScmGetServiceFromHandle(hService
);
3240 DPRINT1("Invalid service handle!\n");
3241 return ERROR_INVALID_HANDLE
;
3244 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3245 SERVICE_CHANGE_CONFIG
))
3247 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3248 return ERROR_ACCESS_DENIED
;
3251 lpService
= hSvc
->ServiceEntry
;
3252 if (lpService
== NULL
)
3254 DPRINT("lpService == NULL!\n");
3255 return ERROR_INVALID_HANDLE
;
3258 /* Lock the service database exclusively */
3259 ScmLockDatabaseExclusive();
3261 if (lpService
->bDeleted
)
3263 DPRINT("The service has already been marked for delete!\n");
3264 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
3268 /* Open the service key */
3269 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3272 if (dwError
!= ERROR_SUCCESS
)
3275 /* Write service data to the registry */
3277 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3279 /* Set the display name */
3280 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3282 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3283 if (lpDisplayNameW
== NULL
)
3285 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3289 MultiByteToWideChar(CP_ACP
,
3294 strlen(lpDisplayName
) + 1);
3296 RegSetValueExW(hServiceKey
,
3300 (LPBYTE
)lpDisplayNameW
,
3301 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3303 /* Update lpService->lpDisplayName */
3304 if (lpService
->lpDisplayName
)
3305 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3307 lpService
->lpDisplayName
= lpDisplayNameW
;
3310 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3312 /* Set the service type */
3313 dwError
= RegSetValueExW(hServiceKey
,
3317 (LPBYTE
)&dwServiceType
,
3319 if (dwError
!= ERROR_SUCCESS
)
3322 lpService
->Status
.dwServiceType
= dwServiceType
;
3325 if (dwStartType
!= SERVICE_NO_CHANGE
)
3327 /* Set the start value */
3328 dwError
= RegSetValueExW(hServiceKey
,
3332 (LPBYTE
)&dwStartType
,
3334 if (dwError
!= ERROR_SUCCESS
)
3337 lpService
->dwStartType
= dwStartType
;
3340 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3342 /* Set the error control value */
3343 dwError
= RegSetValueExW(hServiceKey
,
3347 (LPBYTE
)&dwErrorControl
,
3349 if (dwError
!= ERROR_SUCCESS
)
3352 lpService
->dwErrorControl
= dwErrorControl
;
3356 /* FIXME: set the new ImagePath value */
3358 /* Set the image path */
3359 if (dwServiceType
& SERVICE_WIN32
)
3361 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3363 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3364 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, strlen(lpBinaryPathName
)+1);
3365 dwError
= RegSetValueExW(hServiceKey
,
3369 (LPBYTE
)lpBinaryPathNameW
,
3370 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3371 if (dwError
!= ERROR_SUCCESS
)
3375 else if (dwServiceType
& SERVICE_DRIVER
)
3377 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3379 dwError
= RegSetValueExW(hServiceKey
,
3383 (LPBYTE
)lpImagePath
,
3384 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3385 if (dwError
!= ERROR_SUCCESS
)
3391 /* Set the group name */
3392 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3394 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3396 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3397 if (lpLoadOrderGroupW
== NULL
)
3399 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3403 MultiByteToWideChar(CP_ACP
,
3408 strlen(lpLoadOrderGroup
) + 1);
3410 dwError
= RegSetValueExW(hServiceKey
,
3414 (LPBYTE
)lpLoadOrderGroupW
,
3415 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3416 if (dwError
!= ERROR_SUCCESS
)
3418 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3422 dwError
= ScmSetServiceGroup(lpService
,
3425 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3427 if (dwError
!= ERROR_SUCCESS
)
3431 if (lpdwTagId
!= NULL
)
3433 dwError
= ScmAssignNewTag(lpService
);
3434 if (dwError
!= ERROR_SUCCESS
)
3437 dwError
= RegSetValueExW(hServiceKey
,
3441 (LPBYTE
)&lpService
->dwTag
,
3443 if (dwError
!= ERROR_SUCCESS
)
3446 *lpdwTagId
= lpService
->dwTag
;
3449 /* Write dependencies */
3450 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3452 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3454 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3455 if (lpDependenciesW
== NULL
)
3457 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3461 MultiByteToWideChar(CP_ACP
,
3466 strlen(lpDependencies
) + 1);
3468 dwError
= ScmWriteDependencies(hServiceKey
,
3469 (LPWSTR
)lpDependenciesW
,
3472 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3475 if (lpPassword
!= NULL
)
3477 /* FIXME: Write password */
3481 /* Unlock the service database */
3482 ScmUnlockDatabase();
3484 if (hServiceKey
!= NULL
)
3485 RegCloseKey(hServiceKey
);
3487 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3494 DWORD
RCreateServiceA(
3495 SC_RPC_HANDLE hSCManager
,
3496 LPSTR lpServiceName
,
3497 LPSTR lpDisplayName
,
3498 DWORD dwDesiredAccess
,
3499 DWORD dwServiceType
,
3501 DWORD dwErrorControl
,
3502 LPSTR lpBinaryPathName
,
3503 LPSTR lpLoadOrderGroup
,
3505 LPBYTE lpDependencies
,
3507 LPSTR lpServiceStartName
,
3510 LPSC_RPC_HANDLE lpServiceHandle
)
3512 DWORD dwError
= ERROR_SUCCESS
;
3513 LPWSTR lpServiceNameW
= NULL
;
3514 LPWSTR lpDisplayNameW
= NULL
;
3515 LPWSTR lpBinaryPathNameW
= NULL
;
3516 LPWSTR lpLoadOrderGroupW
= NULL
;
3517 LPWSTR lpDependenciesW
= NULL
;
3518 LPWSTR lpServiceStartNameW
= NULL
;
3519 DWORD dwDependenciesLength
= 0;
3526 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3527 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3528 if (!lpServiceNameW
)
3530 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3533 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3538 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3539 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3540 if (!lpDisplayNameW
)
3542 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3545 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3548 if (lpBinaryPathName
)
3550 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3551 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3552 if (!lpBinaryPathNameW
)
3554 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3557 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3560 if (lpLoadOrderGroup
)
3562 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3563 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3564 if (!lpLoadOrderGroupW
)
3566 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3569 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3574 lpStr
= (LPSTR
)lpDependencies
;
3577 dwLength
= strlen(lpStr
) + 1;
3578 dwDependenciesLength
+= dwLength
;
3579 lpStr
= lpStr
+ dwLength
;
3581 dwDependenciesLength
++;
3583 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3584 if (!lpDependenciesW
)
3586 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3589 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3592 if (lpServiceStartName
)
3594 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3595 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3596 if (!lpServiceStartNameW
)
3598 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3601 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3604 dwError
= RCreateServiceW(hSCManager
,
3614 (LPBYTE
)lpDependenciesW
,
3615 dwDependenciesLength
,
3616 lpServiceStartNameW
,
3622 if (lpServiceNameW
!=NULL
)
3623 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3625 if (lpDisplayNameW
!= NULL
)
3626 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3628 if (lpBinaryPathNameW
!= NULL
)
3629 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3631 if (lpLoadOrderGroupW
!= NULL
)
3632 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3634 if (lpDependenciesW
!= NULL
)
3635 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3637 if (lpServiceStartNameW
!= NULL
)
3638 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3645 DWORD
REnumDependentServicesA(
3646 SC_RPC_HANDLE hService
,
3647 DWORD dwServiceState
,
3650 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3651 LPBOUNDED_DWORD_256K lpServicesReturned
)
3653 DWORD dwError
= ERROR_SUCCESS
;
3654 DWORD dwServicesReturned
= 0;
3655 DWORD dwServiceCount
;
3656 HKEY hServicesKey
= NULL
;
3657 PSERVICE_HANDLE hSvc
;
3658 PSERVICE lpService
= NULL
;
3659 PSERVICE
*lpServicesArray
= NULL
;
3660 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3663 *pcbBytesNeeded
= 0;
3664 *lpServicesReturned
= 0;
3666 DPRINT("REnumDependentServicesA() called\n");
3668 hSvc
= ScmGetServiceFromHandle(hService
);
3671 DPRINT1("Invalid service handle!\n");
3672 return ERROR_INVALID_HANDLE
;
3675 lpService
= hSvc
->ServiceEntry
;
3677 /* Check access rights */
3678 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3679 SC_MANAGER_ENUMERATE_SERVICE
))
3681 DPRINT("Insufficient access rights! 0x%lx\n",
3682 hSvc
->Handle
.DesiredAccess
);
3683 return ERROR_ACCESS_DENIED
;
3686 /* Open the Services Reg key */
3687 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3688 L
"System\\CurrentControlSet\\Services",
3693 if (dwError
!= ERROR_SUCCESS
)
3696 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3697 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3698 are the same for both. Verified in WINXP. */
3700 /* First determine the bytes needed and get the number of dependent services*/
3701 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3706 &dwServicesReturned
);
3707 if (dwError
!= ERROR_SUCCESS
)
3710 /* If buffer size is less than the bytes needed or pointer is null*/
3711 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3713 dwError
= ERROR_MORE_DATA
;
3717 /* Allocate memory for array of service pointers */
3718 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3720 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3721 if (!lpServicesArray
)
3723 DPRINT("Could not allocate a buffer!!\n");
3724 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3728 dwServicesReturned
= 0;
3729 *pcbBytesNeeded
= 0;
3731 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3736 &dwServicesReturned
);
3737 if (dwError
!= ERROR_SUCCESS
)
3742 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3743 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3745 /* Copy EnumDepenedentService to Buffer */
3746 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3748 lpService
= lpServicesArray
[dwServiceCount
];
3750 /* Copy the status info */
3751 memcpy(&lpServicesPtr
->ServiceStatus
,
3753 sizeof(SERVICE_STATUS
));
3755 /* Copy display name */
3756 WideCharToMultiByte(CP_ACP
,
3758 lpService
->lpDisplayName
,
3761 wcslen(lpService
->lpDisplayName
),
3764 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3765 lpStr
+= strlen(lpStr
) + 1;
3767 /* Copy service name */
3768 WideCharToMultiByte(CP_ACP
,
3770 lpService
->lpServiceName
,
3773 wcslen(lpService
->lpServiceName
),
3776 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3777 lpStr
+= strlen(lpStr
) + 1;
3782 *lpServicesReturned
= dwServicesReturned
;
3785 if (lpServicesArray
)
3786 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3788 RegCloseKey(hServicesKey
);
3790 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3797 DWORD
REnumServicesStatusA(
3798 SC_RPC_HANDLE hSCManager
,
3799 DWORD dwServiceType
,
3800 DWORD dwServiceState
,
3803 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3804 LPBOUNDED_DWORD_256K lpServicesReturned
,
3805 LPBOUNDED_DWORD_256K lpResumeHandle
)
3807 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3808 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3809 LPWSTR lpStringPtrW
;
3812 DWORD dwServiceCount
;
3814 DPRINT("REnumServicesStatusA() called\n");
3816 if ((dwBufSize
> 0) && (lpBuffer
))
3818 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3821 DPRINT("Failed to allocate buffer!\n");
3822 return ERROR_NOT_ENOUGH_MEMORY
;
3826 dwError
= REnumServicesStatusW(hSCManager
,
3829 (LPBYTE
)lpStatusPtrW
,
3835 /* if no services were returned then we are Done */
3836 if (*lpServicesReturned
== 0)
3839 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3840 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3841 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3842 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3843 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3845 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3847 /* Copy the service name */
3848 WideCharToMultiByte(CP_ACP
,
3853 wcslen(lpStringPtrW
),
3857 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3858 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3859 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3861 /* Copy the display name */
3862 WideCharToMultiByte(CP_ACP
,
3867 wcslen(lpStringPtrW
),
3871 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3872 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3873 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3875 /* Copy the status information */
3876 memcpy(&lpStatusPtrA
->ServiceStatus
,
3877 &lpStatusPtrW
->ServiceStatus
,
3878 sizeof(SERVICE_STATUS
));
3885 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3887 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3894 DWORD
ROpenSCManagerA(
3895 LPSTR lpMachineName
,
3896 LPSTR lpDatabaseName
,
3897 DWORD dwDesiredAccess
,
3898 LPSC_RPC_HANDLE lpScHandle
)
3900 UNICODE_STRING MachineName
;
3901 UNICODE_STRING DatabaseName
;
3904 DPRINT("ROpenSCManagerA() called\n");
3907 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3911 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3914 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3915 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3920 RtlFreeUnicodeString(&MachineName
);
3923 RtlFreeUnicodeString(&DatabaseName
);
3930 DWORD
ROpenServiceA(
3931 SC_RPC_HANDLE hSCManager
,
3932 LPSTR lpServiceName
,
3933 DWORD dwDesiredAccess
,
3934 LPSC_RPC_HANDLE lpServiceHandle
)
3936 UNICODE_STRING ServiceName
;
3939 DPRINT("ROpenServiceA() called\n");
3942 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3945 dwError
= ROpenServiceW(hSCManager
,
3946 lpServiceName
? ServiceName
.Buffer
: NULL
,
3951 RtlFreeUnicodeString(&ServiceName
);
3958 DWORD
RQueryServiceConfigA(
3959 SC_RPC_HANDLE hService
,
3960 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3962 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3964 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3965 DWORD dwError
= ERROR_SUCCESS
;
3966 PSERVICE_HANDLE hSvc
;
3967 PSERVICE lpService
= NULL
;
3968 HKEY hServiceKey
= NULL
;
3969 LPWSTR lpImagePath
= NULL
;
3970 LPWSTR lpServiceStartName
= NULL
;
3971 LPWSTR lpDependencies
= NULL
;
3972 DWORD dwDependenciesLength
= 0;
3973 DWORD dwRequiredSize
;
3974 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3975 CHAR lpEmptyString
[]={0,0};
3978 DPRINT("RQueryServiceConfigA() called\n");
3981 return ERROR_SHUTDOWN_IN_PROGRESS
;
3983 hSvc
= ScmGetServiceFromHandle(hService
);
3986 DPRINT1("Invalid service handle!\n");
3987 return ERROR_INVALID_HANDLE
;
3990 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3991 SERVICE_QUERY_CONFIG
))
3993 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3994 return ERROR_ACCESS_DENIED
;
3997 lpService
= hSvc
->ServiceEntry
;
3998 if (lpService
== NULL
)
4000 DPRINT("lpService == NULL!\n");
4001 return ERROR_INVALID_HANDLE
;
4004 /* Lock the service database shared */
4005 ScmLockDatabaseShared();
4007 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4010 if (dwError
!= ERROR_SUCCESS
)
4013 /* Read the image path */
4014 dwError
= ScmReadString(hServiceKey
,
4017 if (dwError
!= ERROR_SUCCESS
)
4020 /* Read the service start name */
4021 ScmReadString(hServiceKey
,
4023 &lpServiceStartName
);
4025 /* Read the dependencies */
4026 ScmReadDependencies(hServiceKey
,
4028 &dwDependenciesLength
);
4030 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
4032 if (lpImagePath
!= NULL
)
4033 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
4035 dwRequiredSize
+= 2;
4037 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
4038 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
4040 dwRequiredSize
+= 2;
4042 /* Add Dependencies length */
4043 if (lpDependencies
!= NULL
)
4044 dwRequiredSize
+= dwDependenciesLength
;
4046 dwRequiredSize
+= 2;
4048 if (lpServiceStartName
!= NULL
)
4049 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
4051 dwRequiredSize
+= 2;
4053 if (lpService
->lpDisplayName
!= NULL
)
4054 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
4056 dwRequiredSize
+= 2;
4058 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
4060 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4064 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
4065 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
4066 lpConfig
->dwStartType
= lpService
->dwStartType
;
4067 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
4068 lpConfig
->dwTagId
= lpService
->dwTag
;
4070 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
4072 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
4077 WideCharToMultiByte(CP_ACP
,
4082 wcslen(lpImagePath
) + 1,
4088 strcpy(lpStr
, lpEmptyString
);
4091 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4092 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
4094 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
4096 WideCharToMultiByte(CP_ACP
,
4098 lpService
->lpGroup
->lpGroupName
,
4101 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
4107 strcpy(lpStr
, lpEmptyString
);
4110 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4111 lpStr
+= (strlen(lpStr
) + 1);
4113 /* Append Dependencies */
4116 WideCharToMultiByte(CP_ACP
,
4119 dwDependenciesLength
,
4121 dwDependenciesLength
,
4127 strcpy(lpStr
, lpEmptyString
);
4130 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4132 lpStr
+= dwDependenciesLength
;
4134 lpStr
+= (strlen(lpStr
) + 1);
4136 if (lpServiceStartName
)
4138 WideCharToMultiByte(CP_ACP
,
4143 wcslen(lpServiceStartName
) + 1,
4149 strcpy(lpStr
, lpEmptyString
);
4152 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4153 lpStr
+= (strlen(lpStr
) + 1);
4155 if (lpService
->lpDisplayName
)
4157 WideCharToMultiByte(CP_ACP
,
4159 lpService
->lpDisplayName
,
4162 wcslen(lpService
->lpDisplayName
) + 1,
4168 strcpy(lpStr
, lpEmptyString
);
4171 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4174 if (pcbBytesNeeded
!= NULL
)
4175 *pcbBytesNeeded
= dwRequiredSize
;
4178 /* Unlock the service database */
4179 ScmUnlockDatabase();
4181 if (lpImagePath
!= NULL
)
4182 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4184 if (lpServiceStartName
!= NULL
)
4185 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4187 if (lpDependencies
!= NULL
)
4188 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4190 if (hServiceKey
!= NULL
)
4191 RegCloseKey(hServiceKey
);
4193 DPRINT("RQueryServiceConfigA() done\n");
4200 DWORD
RQueryServiceLockStatusA(
4201 SC_RPC_HANDLE hSCManager
,
4202 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
4204 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4207 return ERROR_CALL_NOT_IMPLEMENTED
;
4212 DWORD
RStartServiceA(
4213 SC_RPC_HANDLE hService
,
4215 LPSTRING_PTRSA argv
)
4217 DWORD dwError
= ERROR_SUCCESS
;
4218 PSERVICE_HANDLE hSvc
;
4219 PSERVICE lpService
= NULL
;
4220 LPWSTR
*lpVector
= NULL
;
4224 DPRINT("RStartServiceA() called\n");
4227 return ERROR_SHUTDOWN_IN_PROGRESS
;
4229 hSvc
= ScmGetServiceFromHandle(hService
);
4232 DPRINT1("Invalid service handle!\n");
4233 return ERROR_INVALID_HANDLE
;
4236 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4239 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4240 return ERROR_ACCESS_DENIED
;
4243 lpService
= hSvc
->ServiceEntry
;
4244 if (lpService
== NULL
)
4246 DPRINT("lpService == NULL!\n");
4247 return ERROR_INVALID_HANDLE
;
4250 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4251 return ERROR_SERVICE_DISABLED
;
4253 if (lpService
->bDeleted
)
4254 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4256 /* Build a Unicode argument vector */
4259 lpVector
= HeapAlloc(GetProcessHeap(),
4261 argc
* sizeof(LPWSTR
));
4262 if (lpVector
== NULL
)
4263 return ERROR_NOT_ENOUGH_MEMORY
;
4265 for (i
= 0; i
< argc
; i
++)
4267 dwLength
= MultiByteToWideChar(CP_ACP
,
4274 lpVector
[i
] = HeapAlloc(GetProcessHeap(),
4276 dwLength
* sizeof(WCHAR
));
4277 if (lpVector
[i
] == NULL
)
4279 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
4283 MultiByteToWideChar(CP_ACP
,
4292 /* Start the service */
4293 dwError
= ScmStartService(lpService
, argc
, lpVector
);
4296 /* Free the Unicode argument vector */
4297 if (lpVector
!= NULL
)
4299 for (i
= 0; i
< argc
; i
++)
4301 if (lpVector
[i
] != NULL
)
4302 HeapFree(GetProcessHeap(), 0, lpVector
[i
]);
4304 HeapFree(GetProcessHeap(), 0, lpVector
);
4312 DWORD
RGetServiceDisplayNameA(
4313 SC_RPC_HANDLE hSCManager
,
4314 LPCSTR lpServiceName
,
4315 LPSTR lpDisplayName
,
4316 LPBOUNDED_DWORD_4K lpcchBuffer
)
4318 // PMANAGER_HANDLE hManager;
4319 PSERVICE lpService
= NULL
;
4322 LPWSTR lpServiceNameW
;
4324 DPRINT("RGetServiceDisplayNameA() called\n");
4325 DPRINT("hSCManager = %p\n", hSCManager
);
4326 DPRINT("lpServiceName: %s\n", lpServiceName
);
4327 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4328 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4330 // hManager = (PMANAGER_HANDLE)hSCManager;
4331 // if (hManager->Handle.Tag != MANAGER_TAG)
4333 // DPRINT("Invalid manager handle!\n");
4334 // return ERROR_INVALID_HANDLE;
4337 if (lpServiceName
!= NULL
)
4339 dwLength
= strlen(lpServiceName
) + 1;
4340 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4342 dwLength
* sizeof(WCHAR
));
4343 if (!lpServiceNameW
)
4344 return ERROR_NOT_ENOUGH_MEMORY
;
4346 MultiByteToWideChar(CP_ACP
,
4353 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4355 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4358 if (lpService
== NULL
)
4360 DPRINT("Could not find a service!\n");
4362 /* If the service could not be found and lpcchBuffer is 0, windows
4363 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4364 if (*lpcchBuffer
== 0)
4367 if (lpDisplayName
!= NULL
)
4369 *lpDisplayName
= '\0';
4372 return ERROR_SERVICE_DOES_NOT_EXIST
;
4375 if (!lpService
->lpDisplayName
)
4377 dwLength
= wcslen(lpService
->lpServiceName
);
4378 if (lpDisplayName
!= NULL
&&
4379 *lpcchBuffer
> dwLength
)
4381 WideCharToMultiByte(CP_ACP
,
4383 lpService
->lpServiceName
,
4384 wcslen(lpService
->lpServiceName
),
4389 return ERROR_SUCCESS
;
4394 dwLength
= wcslen(lpService
->lpDisplayName
);
4395 if (lpDisplayName
!= NULL
&&
4396 *lpcchBuffer
> dwLength
)
4398 WideCharToMultiByte(CP_ACP
,
4400 lpService
->lpDisplayName
,
4401 wcslen(lpService
->lpDisplayName
),
4406 return ERROR_SUCCESS
;
4410 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4412 *lpcchBuffer
= dwLength
* 2;
4419 DWORD
RGetServiceKeyNameA(
4420 SC_RPC_HANDLE hSCManager
,
4421 LPCSTR lpDisplayName
,
4422 LPSTR lpServiceName
,
4423 LPBOUNDED_DWORD_4K lpcchBuffer
)
4428 LPWSTR lpDisplayNameW
;
4430 DPRINT("RGetServiceKeyNameA() called\n");
4431 DPRINT("hSCManager = %p\n", hSCManager
);
4432 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4433 DPRINT("lpServiceName: %p\n", lpServiceName
);
4434 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4436 dwLength
= strlen(lpDisplayName
) + 1;
4437 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4439 dwLength
* sizeof(WCHAR
));
4440 if (!lpDisplayNameW
)
4441 return ERROR_NOT_ENOUGH_MEMORY
;
4443 MultiByteToWideChar(CP_ACP
,
4450 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4452 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4454 if (lpService
== NULL
)
4456 DPRINT("Could not find the service!\n");
4458 /* If the service could not be found and lpcchBuffer is 0,
4459 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4460 if (*lpcchBuffer
== 0)
4463 if (lpServiceName
!= NULL
)
4465 *lpServiceName
= '\0';
4469 return ERROR_SERVICE_DOES_NOT_EXIST
;
4472 dwLength
= wcslen(lpService
->lpServiceName
);
4473 if (lpServiceName
!= NULL
&&
4474 *lpcchBuffer
> dwLength
)
4476 WideCharToMultiByte(CP_ACP
,
4478 lpService
->lpServiceName
,
4479 wcslen(lpService
->lpServiceName
),
4484 return ERROR_SUCCESS
;
4487 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4489 *lpcchBuffer
= dwLength
* 2;
4496 DWORD
RI_ScGetCurrentGroupStateW(
4497 SC_RPC_HANDLE hSCManager
,
4498 LPWSTR lpLoadOrderGroup
,
4502 return ERROR_CALL_NOT_IMPLEMENTED
;
4507 DWORD
REnumServiceGroupW(
4508 SC_RPC_HANDLE hSCManager
,
4509 DWORD dwServiceType
,
4510 DWORD dwServiceState
,
4513 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4514 LPBOUNDED_DWORD_256K lpServicesReturned
,
4515 LPBOUNDED_DWORD_256K lpResumeIndex
,
4516 LPCWSTR pszGroupName
)
4519 return ERROR_CALL_NOT_IMPLEMENTED
;
4524 // WARNING: This function is untested
4527 DWORD
RChangeServiceConfig2A(
4528 SC_RPC_HANDLE hService
,
4529 SC_RPC_CONFIG_INFOA Info
)
4531 SC_RPC_CONFIG_INFOW InfoW
;
4532 DWORD dwRet
, dwLength
;
4535 DPRINT("RChangeServiceConfig2A() called\n");
4536 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4538 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4540 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4542 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4543 //LPSERVICE_DESCRIPTIONA lpServiceDescriptonA;
4545 //lpServiceDescriptonA = Info.psd;
4547 ///if (lpServiceDescriptonA &&
4548 ///lpServiceDescriptonA->lpDescription)
4550 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4552 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4554 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4555 if (!lpServiceDescriptonW
)
4557 return ERROR_NOT_ENOUGH_MEMORY
;
4560 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4562 MultiByteToWideChar(CP_ACP
,
4566 lpServiceDescriptonW
->lpDescription
,
4569 ptr
= lpServiceDescriptonW
;
4570 InfoW
.psd
= lpServiceDescriptonW
;
4573 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4575 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4576 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4577 DWORD dwRebootLen
= 0;
4578 DWORD dwCommandLen
= 0;
4580 lpServiceFailureActionsA
= Info
.psfa
;
4582 if (lpServiceFailureActionsA
)
4584 if (lpServiceFailureActionsA
->lpRebootMsg
)
4586 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4588 if (lpServiceFailureActionsA
->lpCommand
)
4590 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4592 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4594 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4597 if (!lpServiceFailureActionsW
)
4599 return ERROR_NOT_ENOUGH_MEMORY
;
4602 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4603 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4604 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4606 if (lpServiceFailureActionsA
->lpRebootMsg
)
4608 MultiByteToWideChar(CP_ACP
,
4610 lpServiceFailureActionsA
->lpRebootMsg
,
4612 lpServiceFailureActionsW
->lpRebootMsg
,
4616 if (lpServiceFailureActionsA
->lpCommand
)
4618 MultiByteToWideChar(CP_ACP
,
4620 lpServiceFailureActionsA
->lpCommand
,
4622 lpServiceFailureActionsW
->lpCommand
,
4626 ptr
= lpServiceFailureActionsW
;
4630 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4632 HeapFree(GetProcessHeap(), 0, ptr
);
4639 DWORD
RChangeServiceConfig2W(
4640 SC_RPC_HANDLE hService
,
4641 SC_RPC_CONFIG_INFOW Info
)
4643 DWORD dwError
= ERROR_SUCCESS
;
4644 PSERVICE_HANDLE hSvc
;
4645 PSERVICE lpService
= NULL
;
4646 HKEY hServiceKey
= NULL
;
4648 DPRINT("RChangeServiceConfig2W() called\n");
4649 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4652 return ERROR_SHUTDOWN_IN_PROGRESS
;
4654 hSvc
= ScmGetServiceFromHandle(hService
);
4657 DPRINT1("Invalid service handle!\n");
4658 return ERROR_INVALID_HANDLE
;
4661 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4662 SERVICE_CHANGE_CONFIG
))
4664 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4665 return ERROR_ACCESS_DENIED
;
4668 lpService
= hSvc
->ServiceEntry
;
4669 if (lpService
== NULL
)
4671 DPRINT("lpService == NULL!\n");
4672 return ERROR_INVALID_HANDLE
;
4675 /* Lock the service database exclusively */
4676 ScmLockDatabaseExclusive();
4678 if (lpService
->bDeleted
)
4680 DPRINT("The service has already been marked for delete!\n");
4681 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
4685 /* Open the service key */
4686 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4689 if (dwError
!= ERROR_SUCCESS
)
4692 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4694 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4696 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4697 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4699 if (lpServiceDescription
!= NULL
&&
4700 lpServiceDescription
->lpDescription
!= NULL
)
4702 DPRINT("Setting value %S\n", lpServiceDescription
->lpDescription
);
4703 dwError
= RegSetValueExW(hServiceKey
,
4707 (LPBYTE
)lpServiceDescription
->lpDescription
,
4708 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4709 if (dwError
!= ERROR_SUCCESS
)
4713 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4716 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4721 /* Unlock the service database */
4722 ScmUnlockDatabase();
4724 if (hServiceKey
!= NULL
)
4725 RegCloseKey(hServiceKey
);
4727 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4734 DWORD
RQueryServiceConfig2A(
4735 SC_RPC_HANDLE hService
,
4739 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4741 DWORD dwError
= ERROR_SUCCESS
;
4742 PSERVICE_HANDLE hSvc
;
4743 PSERVICE lpService
= NULL
;
4744 HKEY hServiceKey
= NULL
;
4745 LPWSTR lpDescriptionW
= NULL
;
4746 LPSTR lpDescription
= NULL
;
4748 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4749 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4752 return ERROR_INVALID_ADDRESS
;
4755 return ERROR_SHUTDOWN_IN_PROGRESS
;
4757 hSvc
= ScmGetServiceFromHandle(hService
);
4760 DPRINT1("Invalid service handle!\n");
4761 return ERROR_INVALID_HANDLE
;
4764 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4765 SERVICE_QUERY_CONFIG
))
4767 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4768 return ERROR_ACCESS_DENIED
;
4771 lpService
= hSvc
->ServiceEntry
;
4772 if (lpService
== NULL
)
4774 DPRINT("lpService == NULL!\n");
4775 return ERROR_INVALID_HANDLE
;
4778 /* Lock the service database shared */
4779 ScmLockDatabaseShared();
4781 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4784 if (dwError
!= ERROR_SUCCESS
)
4787 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4789 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4792 dwError
= ScmReadString(hServiceKey
,
4795 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4798 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4799 if (dwError
== ERROR_SUCCESS
)
4800 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4802 if (cbBufSize
< *pcbBytesNeeded
)
4804 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4808 if (dwError
== ERROR_SUCCESS
)
4810 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4812 WideCharToMultiByte(CP_ACP
,
4817 wcslen(lpDescriptionW
),
4820 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4824 lpServiceDescription
->lpDescription
= NULL
;
4825 dwError
= ERROR_SUCCESS
;
4829 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4832 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4837 /* Unlock the service database */
4838 ScmUnlockDatabase();
4840 if (lpDescription
!= NULL
)
4841 HeapFree(GetProcessHeap(), 0, lpDescription
);
4843 if (hServiceKey
!= NULL
)
4844 RegCloseKey(hServiceKey
);
4846 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4853 DWORD
RQueryServiceConfig2W(
4854 SC_RPC_HANDLE hService
,
4858 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4860 DWORD dwError
= ERROR_SUCCESS
;
4861 PSERVICE_HANDLE hSvc
;
4862 PSERVICE lpService
= NULL
;
4863 HKEY hServiceKey
= NULL
;
4864 DWORD dwRequiredSize
;
4865 LPWSTR lpDescription
= NULL
;
4866 LPWSTR lpFailureCommand
= NULL
;
4867 LPWSTR lpRebootMessage
= NULL
;
4869 DPRINT("RQueryServiceConfig2W() called\n");
4872 return ERROR_INVALID_ADDRESS
;
4875 return ERROR_SHUTDOWN_IN_PROGRESS
;
4877 hSvc
= ScmGetServiceFromHandle(hService
);
4880 DPRINT1("Invalid service handle!\n");
4881 return ERROR_INVALID_HANDLE
;
4884 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4885 SERVICE_QUERY_CONFIG
))
4887 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4888 return ERROR_ACCESS_DENIED
;
4891 lpService
= hSvc
->ServiceEntry
;
4892 if (lpService
== NULL
)
4894 DPRINT("lpService == NULL!\n");
4895 return ERROR_INVALID_HANDLE
;
4898 /* Lock the service database shared */
4899 ScmLockDatabaseShared();
4901 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4904 if (dwError
!= ERROR_SUCCESS
)
4907 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4909 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4912 dwError
= ScmReadString(hServiceKey
,
4915 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4918 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONW
);
4919 if (dwError
== ERROR_SUCCESS
)
4920 *pcbBytesNeeded
+= ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4922 if (cbBufSize
< *pcbBytesNeeded
)
4924 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4928 if (dwError
== ERROR_SUCCESS
)
4930 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4931 wcscpy(lpStr
, lpDescription
);
4932 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4936 lpServiceDescription
->lpDescription
= NULL
;
4937 dwError
= ERROR_SUCCESS
;
4940 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4943 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
4947 dwError
= ScmReadString(hServiceKey
,
4951 dwError
= ScmReadString(hServiceKey
,
4955 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
4957 if (lpFailureCommand
)
4958 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
4960 if (lpRebootMessage
)
4961 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
4963 if (cbBufSize
< dwRequiredSize
)
4965 *pcbBytesNeeded
= dwRequiredSize
;
4966 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4970 lpFailureActions
->cActions
= 0;
4971 lpFailureActions
->dwResetPeriod
= 0;
4972 lpFailureActions
->lpCommand
= NULL
;
4973 lpFailureActions
->lpRebootMsg
= NULL
;
4974 lpFailureActions
->lpsaActions
= NULL
;
4976 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
4977 if (lpRebootMessage
)
4979 wcscpy(lpStr
, lpRebootMessage
);
4980 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
4981 lpStr
+= wcslen(lpRebootMessage
) + 1;
4984 if (lpFailureCommand
)
4986 wcscpy(lpStr
, lpFailureCommand
);
4987 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
4988 lpStr
+= wcslen(lpRebootMessage
) + 1;
4990 dwError
= STATUS_SUCCESS
;
4995 /* Unlock the service database */
4996 ScmUnlockDatabase();
4998 if (lpDescription
!= NULL
)
4999 HeapFree(GetProcessHeap(), 0, lpDescription
);
5001 if (lpRebootMessage
!= NULL
)
5002 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
5004 if (lpFailureCommand
!= NULL
)
5005 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
5007 if (hServiceKey
!= NULL
)
5008 RegCloseKey(hServiceKey
);
5010 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
5017 DWORD
RQueryServiceStatusEx(
5018 SC_RPC_HANDLE hService
,
5019 SC_STATUS_TYPE InfoLevel
,
5022 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
5024 LPSERVICE_STATUS_PROCESS lpStatus
;
5025 PSERVICE_HANDLE hSvc
;
5028 DPRINT("RQueryServiceStatusEx() called\n");
5031 return ERROR_SHUTDOWN_IN_PROGRESS
;
5033 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
5034 return ERROR_INVALID_LEVEL
;
5036 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
5038 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
5039 return ERROR_INSUFFICIENT_BUFFER
;
5041 hSvc
= ScmGetServiceFromHandle(hService
);
5044 DPRINT1("Invalid service handle!\n");
5045 return ERROR_INVALID_HANDLE
;
5048 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
5049 SERVICE_QUERY_STATUS
))
5051 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
5052 return ERROR_ACCESS_DENIED
;
5055 lpService
= hSvc
->ServiceEntry
;
5056 if (lpService
== NULL
)
5058 DPRINT("lpService == NULL!\n");
5059 return ERROR_INVALID_HANDLE
;
5062 /* Lock the service database shared */
5063 ScmLockDatabaseShared();
5065 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
5067 /* Return service status information */
5068 RtlCopyMemory(lpStatus
,
5070 sizeof(SERVICE_STATUS
));
5072 lpStatus
->dwProcessId
= (lpService
->lpImage
!= NULL
) ? lpService
->lpImage
->dwProcessId
: 0; /* FIXME */
5073 lpStatus
->dwServiceFlags
= 0; /* FIXME */
5075 /* Unlock the service database */
5076 ScmUnlockDatabase();
5078 return ERROR_SUCCESS
;
5083 DWORD
REnumServicesStatusExA(
5084 SC_RPC_HANDLE hSCManager
,
5085 SC_ENUM_TYPE InfoLevel
,
5086 DWORD dwServiceType
,
5087 DWORD dwServiceState
,
5090 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5091 LPBOUNDED_DWORD_256K lpServicesReturned
,
5092 LPBOUNDED_DWORD_256K lpResumeIndex
,
5093 LPCSTR pszGroupName
)
5095 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
5096 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
5097 LPWSTR lpStringPtrW
;
5099 LPWSTR pszGroupNameW
= NULL
;
5101 DWORD dwServiceCount
;
5103 DPRINT("REnumServicesStatusExA() called\n");
5107 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
5110 DPRINT("Failed to allocate buffer!\n");
5111 return ERROR_NOT_ENOUGH_MEMORY
;
5114 MultiByteToWideChar(CP_ACP
,
5119 strlen(pszGroupName
) + 1);
5122 if ((cbBufSize
> 0) && (lpBuffer
))
5124 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
5127 DPRINT("Failed to allocate buffer!\n");
5128 return ERROR_NOT_ENOUGH_MEMORY
;
5132 dwError
= REnumServicesStatusExW(hSCManager
,
5136 (LPBYTE
)lpStatusPtrW
,
5143 /* if no services were returned then we are Done */
5144 if (*lpServicesReturned
== 0)
5147 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
5148 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
5149 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
5150 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
5151 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5153 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
5155 /* Copy the service name */
5156 WideCharToMultiByte(CP_ACP
,
5161 wcslen(lpStringPtrW
),
5165 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5166 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5167 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5169 /* Copy the display name */
5170 WideCharToMultiByte(CP_ACP
,
5175 wcslen(lpStringPtrW
),
5179 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5180 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5181 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5183 /* Copy the status information */
5184 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
5185 &lpStatusPtrW
->ServiceStatusProcess
,
5186 sizeof(SERVICE_STATUS
));
5188 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
5189 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5195 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
5198 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
5200 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
5207 DWORD
REnumServicesStatusExW(
5208 SC_RPC_HANDLE hSCManager
,
5209 SC_ENUM_TYPE InfoLevel
,
5210 DWORD dwServiceType
,
5211 DWORD dwServiceState
,
5214 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5215 LPBOUNDED_DWORD_256K lpServicesReturned
,
5216 LPBOUNDED_DWORD_256K lpResumeIndex
,
5217 LPCWSTR pszGroupName
)
5219 PMANAGER_HANDLE hManager
;
5221 DWORD dwError
= ERROR_SUCCESS
;
5222 PLIST_ENTRY ServiceEntry
;
5223 PSERVICE CurrentService
;
5225 DWORD dwRequiredSize
;
5226 DWORD dwServiceCount
;
5228 DWORD dwLastResumeCount
= 0;
5229 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
5232 DPRINT("REnumServicesStatusExW() called\n");
5235 return ERROR_SHUTDOWN_IN_PROGRESS
;
5237 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
5238 return ERROR_INVALID_LEVEL
;
5240 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
5241 if (hManager
== NULL
)
5243 DPRINT1("Invalid service manager handle!\n");
5244 return ERROR_INVALID_HANDLE
;
5247 *pcbBytesNeeded
= 0;
5248 *lpServicesReturned
= 0;
5250 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
5252 DPRINT("Not a valid Service Type!\n");
5253 return ERROR_INVALID_PARAMETER
;
5256 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
5258 DPRINT("Not a valid Service State!\n");
5259 return ERROR_INVALID_PARAMETER
;
5262 /* Check access rights */
5263 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
5264 SC_MANAGER_ENUMERATE_SERVICE
))
5266 DPRINT("Insufficient access rights! 0x%lx\n",
5267 hManager
->Handle
.DesiredAccess
);
5268 return ERROR_ACCESS_DENIED
;
5272 dwLastResumeCount
= *lpResumeIndex
;
5274 /* Lock the service database shared */
5275 ScmLockDatabaseShared();
5277 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
5278 if (lpService
== NULL
)
5280 dwError
= ERROR_SUCCESS
;
5287 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5288 ServiceEntry
!= &ServiceListHead
;
5289 ServiceEntry
= ServiceEntry
->Flink
)
5291 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5295 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5298 dwState
= SERVICE_ACTIVE
;
5299 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5300 dwState
= SERVICE_INACTIVE
;
5302 if ((dwState
& dwServiceState
) == 0)
5307 if (*pszGroupName
== 0)
5309 if (CurrentService
->lpGroup
!= NULL
)
5314 if ((CurrentService
->lpGroup
== NULL
) ||
5315 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5320 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5321 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5322 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5324 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5326 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5327 dwRequiredSize
+= dwSize
;
5329 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5333 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5339 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5340 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5343 ServiceEntry
!= &ServiceListHead
;
5344 ServiceEntry
= ServiceEntry
->Flink
)
5346 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5350 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5353 dwState
= SERVICE_ACTIVE
;
5354 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5355 dwState
= SERVICE_INACTIVE
;
5357 if ((dwState
& dwServiceState
) == 0)
5362 if (*pszGroupName
== 0)
5364 if (CurrentService
->lpGroup
!= NULL
)
5369 if ((CurrentService
->lpGroup
== NULL
) ||
5370 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5375 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5376 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5377 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5379 dwError
= ERROR_MORE_DATA
;
5382 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5385 *lpResumeIndex
= dwLastResumeCount
;
5387 *lpServicesReturned
= dwServiceCount
;
5388 *pcbBytesNeeded
= dwRequiredSize
;
5390 /* If there was no services that matched */
5391 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5393 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5397 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5398 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5399 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5402 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5403 ServiceEntry
!= &ServiceListHead
;
5404 ServiceEntry
= ServiceEntry
->Flink
)
5406 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5410 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5413 dwState
= SERVICE_ACTIVE
;
5414 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5415 dwState
= SERVICE_INACTIVE
;
5417 if ((dwState
& dwServiceState
) == 0)
5422 if (*pszGroupName
== 0)
5424 if (CurrentService
->lpGroup
!= NULL
)
5429 if ((CurrentService
->lpGroup
== NULL
) ||
5430 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5435 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5436 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5437 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5439 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5441 /* Copy the service name */
5443 CurrentService
->lpServiceName
);
5444 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5445 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5447 /* Copy the display name */
5449 CurrentService
->lpDisplayName
);
5450 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5451 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5453 /* Copy the status information */
5454 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5455 &CurrentService
->Status
,
5456 sizeof(SERVICE_STATUS
));
5457 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
=
5458 (CurrentService
->lpImage
!= NULL
) ? CurrentService
->lpImage
->dwProcessId
: 0; /* FIXME */
5459 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5462 dwRequiredSize
+= dwSize
;
5472 *pcbBytesNeeded
= 0;
5478 /* Unlock the service database */
5479 ScmUnlockDatabase();
5481 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5488 DWORD
RSendTSMessage(
5489 handle_t BindingHandle
) /* FIXME */
5492 return ERROR_CALL_NOT_IMPLEMENTED
;
5497 DWORD
RCreateServiceWOW64A(
5498 handle_t BindingHandle
,
5499 LPSTR lpServiceName
,
5500 LPSTR lpDisplayName
,
5501 DWORD dwDesiredAccess
,
5502 DWORD dwServiceType
,
5504 DWORD dwErrorControl
,
5505 LPSTR lpBinaryPathName
,
5506 LPSTR lpLoadOrderGroup
,
5508 LPBYTE lpDependencies
,
5510 LPSTR lpServiceStartName
,
5513 LPSC_RPC_HANDLE lpServiceHandle
)
5516 return ERROR_CALL_NOT_IMPLEMENTED
;
5521 DWORD
RCreateServiceWOW64W(
5522 handle_t BindingHandle
,
5523 LPWSTR lpServiceName
,
5524 LPWSTR lpDisplayName
,
5525 DWORD dwDesiredAccess
,
5526 DWORD dwServiceType
,
5528 DWORD dwErrorControl
,
5529 LPWSTR lpBinaryPathName
,
5530 LPWSTR lpLoadOrderGroup
,
5532 LPBYTE lpDependencies
,
5534 LPWSTR lpServiceStartName
,
5537 LPSC_RPC_HANDLE lpServiceHandle
)
5540 return ERROR_CALL_NOT_IMPLEMENTED
;
5545 DWORD
RQueryServiceTagInfo(
5546 handle_t BindingHandle
) /* FIXME */
5549 return ERROR_CALL_NOT_IMPLEMENTED
;
5554 DWORD
RNotifyServiceStatusChange(
5555 SC_RPC_HANDLE hService
,
5556 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5557 GUID
*pClientProcessGuid
,
5558 GUID
*pSCMProcessGuid
,
5559 PBOOL pfCreateRemoteQueue
,
5560 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5563 return ERROR_CALL_NOT_IMPLEMENTED
;
5568 DWORD
RGetNotifyResults(
5569 SC_NOTIFY_RPC_HANDLE hNotify
,
5570 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5573 return ERROR_CALL_NOT_IMPLEMENTED
;
5578 DWORD
RCloseNotifyHandle(
5579 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5583 return ERROR_CALL_NOT_IMPLEMENTED
;
5588 DWORD
RControlServiceExA(
5589 SC_RPC_HANDLE hService
,
5594 return ERROR_CALL_NOT_IMPLEMENTED
;
5599 DWORD
RControlServiceExW(
5600 SC_RPC_HANDLE hService
,
5605 return ERROR_CALL_NOT_IMPLEMENTED
;
5610 DWORD
RSendPnPMessage(
5611 handle_t BindingHandle
) /* FIXME */
5614 return ERROR_CALL_NOT_IMPLEMENTED
;
5619 DWORD
RValidatePnPService(
5620 handle_t BindingHandle
) /* FIXME */
5623 return ERROR_CALL_NOT_IMPLEMENTED
;
5628 DWORD
ROpenServiceStatusHandle(
5629 handle_t BindingHandle
) /* FIXME */
5632 return ERROR_CALL_NOT_IMPLEMENTED
;
5638 handle_t BindingHandle
) /* FIXME */
5641 return ERROR_CALL_NOT_IMPLEMENTED
;
5645 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5647 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5651 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5653 HeapFree(GetProcessHeap(), 0, ptr
);
5657 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5662 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5667 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)