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 | \
81 /* VARIABLES ***************************************************************/
83 static GENERIC_MAPPING
84 ScmManagerMapping
= {SC_MANAGER_READ
,
87 SC_MANAGER_ALL_ACCESS
};
89 static GENERIC_MAPPING
90 ScmServiceMapping
= {SERVICE_READ
,
96 /* FUNCTIONS ***************************************************************/
99 ScmStartRpcServer(VOID
)
103 DPRINT("ScmStartRpcServer() called\n");
105 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
109 if (Status
!= RPC_S_OK
)
111 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
115 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
118 if (Status
!= RPC_S_OK
)
120 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
124 Status
= RpcServerListen(1, 20, TRUE
);
125 if (Status
!= RPC_S_OK
)
127 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
131 DPRINT("ScmStartRpcServer() done\n");
136 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
141 if (lpDatabaseName
== NULL
)
142 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
144 if (_wcsicmp(lpDatabaseName
, SERVICES_FAILED_DATABASEW
) == 0)
146 DPRINT("Database %S, does not exist\n",lpDatabaseName
);
147 return ERROR_DATABASE_DOES_NOT_EXIST
;
149 else if (_wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
151 DPRINT("Invalid Database name %S.\n",lpDatabaseName
);
152 return ERROR_INVALID_NAME
;
155 Ptr
= (MANAGER_HANDLE
*) HeapAlloc(GetProcessHeap(),
157 sizeof(MANAGER_HANDLE
) + (wcslen(lpDatabaseName
) + 1) * sizeof(WCHAR
));
159 return ERROR_NOT_ENOUGH_MEMORY
;
161 Ptr
->Handle
.Tag
= MANAGER_TAG
;
163 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
165 *Handle
= (SC_HANDLE
)Ptr
;
167 return ERROR_SUCCESS
;
172 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
177 Ptr
= (SERVICE_HANDLE
*) HeapAlloc(GetProcessHeap(),
179 sizeof(SERVICE_HANDLE
));
181 return ERROR_NOT_ENOUGH_MEMORY
;
183 Ptr
->Handle
.Tag
= SERVICE_TAG
;
185 Ptr
->ServiceEntry
= lpServiceEntry
;
187 *Handle
= (SC_HANDLE
)Ptr
;
189 return ERROR_SUCCESS
;
193 static PMANAGER_HANDLE
194 ScmGetServiceManagerFromHandle(SC_RPC_HANDLE Handle
)
196 PMANAGER_HANDLE pManager
= NULL
;
200 if (((PMANAGER_HANDLE
)Handle
)->Handle
.Tag
== MANAGER_TAG
)
201 pManager
= (PMANAGER_HANDLE
)Handle
;
203 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
205 DPRINT1("Exception: Invalid Service Manager handle!\n");
213 static PSERVICE_HANDLE
214 ScmGetServiceFromHandle(SC_RPC_HANDLE Handle
)
216 PSERVICE_HANDLE pService
= NULL
;
220 if (((PSERVICE_HANDLE
)Handle
)->Handle
.Tag
== SERVICE_TAG
)
221 pService
= (PSERVICE_HANDLE
)Handle
;
223 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
225 DPRINT1("Exception: Invalid Service handle!\n");
234 ScmCheckAccess(SC_HANDLE Handle
,
235 DWORD dwDesiredAccess
)
237 PMANAGER_HANDLE hMgr
;
239 hMgr
= (PMANAGER_HANDLE
)Handle
;
240 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
242 RtlMapGenericMask(&dwDesiredAccess
,
245 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
247 return ERROR_SUCCESS
;
249 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
251 RtlMapGenericMask(&dwDesiredAccess
,
254 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
256 return ERROR_SUCCESS
;
259 return ERROR_INVALID_HANDLE
;
264 ScmAssignNewTag(PSERVICE lpService
)
267 DPRINT("Assigning new tag to service %S\n", lpService
->lpServiceName
);
268 lpService
->dwTag
= 0;
269 return ERROR_SUCCESS
;
273 /* Internal recursive function */
274 /* Need to search for every dependency on every service */
276 Int_EnumDependentServicesW(HKEY hServicesKey
,
278 DWORD dwServiceState
,
279 PSERVICE
*lpServices
,
280 LPDWORD pcbBytesNeeded
,
281 LPDWORD lpServicesReturned
)
283 DWORD dwError
= ERROR_SUCCESS
;
284 WCHAR szNameBuf
[MAX_PATH
];
285 WCHAR szValueBuf
[MAX_PATH
];
286 WCHAR
*lpszNameBuf
= szNameBuf
;
287 WCHAR
*lpszValueBuf
= szValueBuf
;
291 PSERVICE lpCurrentService
;
292 HKEY hServiceEnumKey
;
293 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
294 DWORD dwDependServiceStrPtr
= 0;
295 DWORD dwRequiredSize
= 0;
297 /* Get the number of service keys */
298 dwError
= RegQueryInfoKeyW(hServicesKey
,
310 if (dwError
!= ERROR_SUCCESS
)
312 DPRINT("ERROR! Unable to get number of services keys.\n");
316 /* Iterate the service keys to see if another service depends on the this service */
317 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
320 dwError
= RegEnumKeyExW(hServicesKey
,
328 if (dwError
!= ERROR_SUCCESS
)
331 /* Open the Service key */
332 dwError
= RegOpenKeyExW(hServicesKey
,
337 if (dwError
!= ERROR_SUCCESS
)
342 /* Check for the DependOnService Value */
343 dwError
= RegQueryValueExW(hServiceEnumKey
,
347 (LPBYTE
)lpszValueBuf
,
350 /* FIXME: Handle load order. */
352 /* If the service found has a DependOnService value */
353 if (dwError
== ERROR_SUCCESS
)
355 dwDependServiceStrPtr
= 0;
357 /* Can be more than one Dependencies in the DependOnService string */
358 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
360 if (_wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
362 /* Get the current enumed service pointer */
363 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
365 /* Check for valid Service */
366 if (!lpCurrentService
)
368 /* This should never happen! */
369 DPRINT("This should not happen at this point, report to Developer\n");
370 return ERROR_NOT_FOUND
;
373 /* Determine state the service is in */
374 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
375 dwCurrentServiceState
= SERVICE_INACTIVE
;
377 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
378 if ((dwCurrentServiceState
== dwServiceState
) ||
379 (dwServiceState
== SERVICE_STATE_ALL
))
381 /* Calculate the required size */
382 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
383 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
384 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
386 /* Add the size for service name and display name pointers */
387 dwRequiredSize
+= (2 * sizeof(PVOID
));
389 /* increase the BytesNeeded size */
390 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
392 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
395 /* Recursive call to check for its dependencies */
396 Int_EnumDependentServicesW(hServicesKey
,
403 /* If the lpServices is valid set the service pointer */
405 lpServices
[*lpServicesReturned
] = lpCurrentService
;
407 *lpServicesReturned
= *lpServicesReturned
+ 1;
411 dwDependServiceStrPtr
+= (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
414 else if (*pcbBytesNeeded
)
416 dwError
= ERROR_SUCCESS
;
419 RegCloseKey(hServiceEnumKey
);
427 DWORD
RCloseServiceHandle(
428 LPSC_RPC_HANDLE hSCObject
)
430 PMANAGER_HANDLE hManager
;
431 PSERVICE_HANDLE hService
;
435 DWORD pcbBytesNeeded
= 0;
436 DWORD dwServicesReturned
= 0;
438 DPRINT("RCloseServiceHandle() called\n");
440 DPRINT("hSCObject = %p\n", *hSCObject
);
443 return ERROR_INVALID_HANDLE
;
445 hManager
= ScmGetServiceManagerFromHandle(*hSCObject
);
446 hService
= ScmGetServiceFromHandle(*hSCObject
);
448 if (hManager
!= NULL
)
450 DPRINT("Found manager handle\n");
452 /* FIXME: add handle cleanup code */
454 HeapFree(GetProcessHeap(), 0, hManager
);
459 DPRINT("RCloseServiceHandle() done\n");
460 return ERROR_SUCCESS
;
462 else if (hService
!= NULL
)
464 DPRINT("Found service handle\n");
466 /* Lock the service database exlusively */
467 ScmLockDatabaseExclusive();
469 /* Get the pointer to the service record */
470 lpService
= hService
->ServiceEntry
;
472 /* FIXME: add handle cleanup code */
474 /* Free the handle */
475 HeapFree(GetProcessHeap(), 0, hService
);
478 ASSERT(lpService
->dwRefCount
> 0);
480 lpService
->dwRefCount
--;
481 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
482 lpService
->dwRefCount
);
484 if (lpService
->dwRefCount
== 0)
486 /* If this service has been marked for deletion */
487 if (lpService
->bDeleted
)
489 /* Open the Services Reg key */
490 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
491 L
"System\\CurrentControlSet\\Services",
493 KEY_SET_VALUE
| KEY_READ
,
495 if (dwError
!= ERROR_SUCCESS
)
497 DPRINT("Failed to open services key\n");
502 /* Call the internal function with NULL, just to get bytes we need */
503 Int_EnumDependentServicesW(hServicesKey
,
508 &dwServicesReturned
);
510 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
513 DPRINT("Deletion failed due to running dependencies.\n");
514 RegCloseKey(hServicesKey
);
516 return ERROR_SUCCESS
;
519 /* There are no references and no runnning dependencies,
520 it is now safe to delete the service */
522 /* Delete the Service Key */
523 dwError
= RegDeleteKeyW(hServicesKey
,
524 lpService
->lpServiceName
);
526 RegCloseKey(hServicesKey
);
528 if (dwError
!= ERROR_SUCCESS
)
530 DPRINT("Failed to Delete the Service Registry key\n");
535 /* Delete the Service */
536 ScmDeleteServiceRecord(lpService
);
544 DPRINT("RCloseServiceHandle() done\n");
545 return ERROR_SUCCESS
;
548 DPRINT("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
550 return ERROR_INVALID_HANDLE
;
555 DWORD
RControlService(
556 SC_RPC_HANDLE hService
,
558 LPSERVICE_STATUS lpServiceStatus
)
560 PSERVICE_HANDLE hSvc
;
562 ACCESS_MASK DesiredAccess
;
563 DWORD dwError
= ERROR_SUCCESS
;
564 DWORD pcbBytesNeeded
= 0;
565 DWORD dwServicesReturned
= 0;
566 DWORD dwControlsAccepted
;
567 DWORD dwCurrentState
;
568 HKEY hServicesKey
= NULL
;
570 DPRINT("RControlService() called\n");
573 return ERROR_SHUTDOWN_IN_PROGRESS
;
575 /* Check the service handle */
576 hSvc
= ScmGetServiceFromHandle(hService
);
579 DPRINT1("Invalid service handle!\n");
580 return ERROR_INVALID_HANDLE
;
584 /* Check the service entry point */
585 lpService
= hSvc
->ServiceEntry
;
586 if (lpService
== NULL
)
588 DPRINT1("lpService == NULL!\n");
589 return ERROR_INVALID_HANDLE
;
592 /* Check access rights */
595 case SERVICE_CONTROL_STOP
:
596 DesiredAccess
= SERVICE_STOP
;
599 case SERVICE_CONTROL_PAUSE
:
600 case SERVICE_CONTROL_CONTINUE
:
601 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
604 case SERVICE_INTERROGATE
:
605 DesiredAccess
= SERVICE_INTERROGATE
;
609 if (dwControl
>= 128 && dwControl
<= 255)
610 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
612 return ERROR_INVALID_PARAMETER
;
616 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
618 return ERROR_ACCESS_DENIED
;
620 if (dwControl
== SERVICE_CONTROL_STOP
)
622 /* Check if the service has dependencies running as windows
623 doesn't stop a service that does */
625 /* Open the Services Reg key */
626 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
627 L
"System\\CurrentControlSet\\Services",
631 if (dwError
!= ERROR_SUCCESS
)
633 DPRINT("Failed to open services key\n");
637 /* Call the internal function with NULL, just to get bytes we need */
638 Int_EnumDependentServicesW(hServicesKey
,
643 &dwServicesReturned
);
645 RegCloseKey(hServicesKey
);
647 /* If pcbBytesNeeded is not zero then there are services running that
648 are dependent on this service */
649 if (pcbBytesNeeded
!= 0)
651 DPRINT("Service has running dependencies. Failed to stop service.\n");
652 return ERROR_DEPENDENT_SERVICES_RUNNING
;
656 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
658 /* Send control code to the driver */
659 dwError
= ScmControlDriver(lpService
,
665 dwControlsAccepted
= lpService
->Status
.dwControlsAccepted
;
666 dwCurrentState
= lpService
->Status
.dwCurrentState
;
668 /* Check the current state before sending a control request */
669 switch (dwCurrentState
)
671 case SERVICE_STOP_PENDING
:
672 case SERVICE_STOPPED
:
673 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
675 case SERVICE_START_PENDING
:
678 case SERVICE_CONTROL_STOP
:
681 case SERVICE_CONTROL_INTERROGATE
:
682 RtlCopyMemory(lpServiceStatus
,
684 sizeof(SERVICE_STATUS
));
685 return ERROR_SUCCESS
;
688 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
693 /* Check if the control code is acceptable to the service */
696 case SERVICE_CONTROL_STOP
:
697 if ((dwControlsAccepted
& SERVICE_ACCEPT_STOP
) == 0)
698 return ERROR_INVALID_SERVICE_CONTROL
;
701 case SERVICE_CONTROL_PAUSE
:
702 case SERVICE_CONTROL_CONTINUE
:
703 if ((dwControlsAccepted
& SERVICE_ACCEPT_PAUSE_CONTINUE
) == 0)
704 return ERROR_INVALID_SERVICE_CONTROL
;
708 /* Send control code to the service */
709 dwError
= ScmControlService(lpService
,
712 /* Return service status information */
713 RtlCopyMemory(lpServiceStatus
,
715 sizeof(SERVICE_STATUS
));
718 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
719 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
726 DWORD
RDeleteService(
727 SC_RPC_HANDLE hService
)
729 PSERVICE_HANDLE hSvc
;
733 DPRINT("RDeleteService() called\n");
736 return ERROR_SHUTDOWN_IN_PROGRESS
;
738 hSvc
= ScmGetServiceFromHandle(hService
);
741 DPRINT1("Invalid service handle!\n");
742 return ERROR_INVALID_HANDLE
;
745 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
747 return ERROR_ACCESS_DENIED
;
749 lpService
= hSvc
->ServiceEntry
;
750 if (lpService
== NULL
)
752 DPRINT("lpService == NULL!\n");
753 return ERROR_INVALID_HANDLE
;
756 /* Lock the service database exclusively */
757 ScmLockDatabaseExclusive();
759 if (lpService
->bDeleted
)
761 DPRINT("The service has already been marked for delete!\n");
762 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
766 /* Mark service for delete */
767 lpService
->bDeleted
= TRUE
;
769 dwError
= ScmMarkServiceForDelete(lpService
);
772 /* Unlock the service database */
775 DPRINT("RDeleteService() done\n");
782 DWORD
RLockServiceDatabase(
783 SC_RPC_HANDLE hSCManager
,
784 LPSC_RPC_LOCK lpLock
)
786 PMANAGER_HANDLE hMgr
;
788 DPRINT("RLockServiceDatabase() called\n");
792 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
795 DPRINT1("Invalid service manager handle!\n");
796 return ERROR_INVALID_HANDLE
;
799 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
801 return ERROR_ACCESS_DENIED
;
803 // return ScmLockDatabase(0, hMgr->0xC, hLock);
805 /* FIXME: Lock the database */
806 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
808 return ERROR_SUCCESS
;
813 DWORD
RQueryServiceObjectSecurity(
814 SC_RPC_HANDLE hService
,
815 SECURITY_INFORMATION dwSecurityInformation
,
816 LPBYTE lpSecurityDescriptor
,
818 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
820 PSERVICE_HANDLE hSvc
;
822 ULONG DesiredAccess
= 0;
828 SECURITY_DESCRIPTOR ObjectDescriptor
;
830 DPRINT("RQueryServiceObjectSecurity() called\n");
832 hSvc
= ScmGetServiceFromHandle(hService
);
835 DPRINT1("Invalid service handle!\n");
836 return ERROR_INVALID_HANDLE
;
839 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
|
840 GROUP_SECURITY_INFORMATION
|
841 OWNER_SECURITY_INFORMATION
))
842 DesiredAccess
|= READ_CONTROL
;
844 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
845 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
847 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
850 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
851 return ERROR_ACCESS_DENIED
;
854 lpService
= hSvc
->ServiceEntry
;
855 if (lpService
== NULL
)
857 DPRINT("lpService == NULL!\n");
858 return ERROR_INVALID_HANDLE
;
861 /* Lock the service database */
862 ScmLockDatabaseShared();
866 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
868 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
869 dwSecurityInformation
,
870 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
874 /* Unlock the service database */
877 if (NT_SUCCESS(Status
))
879 *pcbBytesNeeded
= dwBytesNeeded
;
880 dwError
= STATUS_SUCCESS
;
882 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
884 *pcbBytesNeeded
= dwBytesNeeded
;
885 dwError
= ERROR_INSUFFICIENT_BUFFER
;
887 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
889 dwError
= ERROR_GEN_FAILURE
;
893 dwError
= RtlNtStatusToDosError(Status
);
901 DWORD
RSetServiceObjectSecurity(
902 SC_RPC_HANDLE hService
,
903 DWORD dwSecurityInformation
,
904 LPBYTE lpSecurityDescriptor
,
905 DWORD dwSecuityDescriptorSize
)
907 PSERVICE_HANDLE hSvc
;
909 ULONG DesiredAccess
= 0;
910 /* HANDLE hToken = NULL; */
912 /* NTSTATUS Status; */
915 DPRINT("RSetServiceObjectSecurity() called\n");
917 hSvc
= ScmGetServiceFromHandle(hService
);
920 DPRINT1("Invalid service handle!\n");
921 return ERROR_INVALID_HANDLE
;
924 if (dwSecurityInformation
== 0 ||
925 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
926 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
927 return ERROR_INVALID_PARAMETER
;
929 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
930 return ERROR_INVALID_PARAMETER
;
932 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
933 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
935 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
936 DesiredAccess
|= WRITE_DAC
;
938 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
939 DesiredAccess
|= WRITE_OWNER
;
941 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
942 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
943 return ERROR_INVALID_PARAMETER
;
945 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
946 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
947 return ERROR_INVALID_PARAMETER
;
949 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
952 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
953 return ERROR_ACCESS_DENIED
;
956 lpService
= hSvc
->ServiceEntry
;
957 if (lpService
== NULL
)
959 DPRINT("lpService == NULL!\n");
960 return ERROR_INVALID_HANDLE
;
963 if (lpService
->bDeleted
)
964 return ERROR_SERVICE_MARKED_FOR_DELETE
;
967 RpcImpersonateClient(NULL
);
969 Status
= NtOpenThreadToken(NtCurrentThread(),
973 if (!NT_SUCCESS(Status
))
974 return RtlNtStatusToDosError(Status
);
979 /* Lock the service database exclusive */
980 ScmLockDatabaseExclusive();
983 Status
= RtlSetSecurityObject(dwSecurityInformation
,
984 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
985 &lpService
->lpSecurityDescriptor
,
988 if (!NT_SUCCESS(Status
))
990 dwError
= RtlNtStatusToDosError(Status
);
995 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
996 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
998 if (dwError
!= ERROR_SUCCESS
)
1002 dwError
= ERROR_SUCCESS
;
1003 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
1004 // lpService->lpSecurityDescriptor);
1006 RegFlushKey(hServiceKey
);
1007 RegCloseKey(hServiceKey
);
1016 /* Unlock service database */
1017 ScmUnlockDatabase();
1019 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1026 DWORD
RQueryServiceStatus(
1027 SC_RPC_HANDLE hService
,
1028 LPSERVICE_STATUS lpServiceStatus
)
1030 PSERVICE_HANDLE hSvc
;
1033 DPRINT("RQueryServiceStatus() called\n");
1036 return ERROR_SHUTDOWN_IN_PROGRESS
;
1038 hSvc
= ScmGetServiceFromHandle(hService
);
1041 DPRINT1("Invalid service handle!\n");
1042 return ERROR_INVALID_HANDLE
;
1045 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1046 SERVICE_QUERY_STATUS
))
1048 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1049 return ERROR_ACCESS_DENIED
;
1052 lpService
= hSvc
->ServiceEntry
;
1053 if (lpService
== NULL
)
1055 DPRINT("lpService == NULL!\n");
1056 return ERROR_INVALID_HANDLE
;
1059 /* Lock the service database shared */
1060 ScmLockDatabaseShared();
1062 /* Return service status information */
1063 RtlCopyMemory(lpServiceStatus
,
1065 sizeof(SERVICE_STATUS
));
1067 /* Unlock the service database */
1068 ScmUnlockDatabase();
1070 return ERROR_SUCCESS
;
1075 ScmIsValidServiceState(DWORD dwCurrentState
)
1077 switch (dwCurrentState
)
1079 case SERVICE_STOPPED
:
1080 case SERVICE_START_PENDING
:
1081 case SERVICE_STOP_PENDING
:
1082 case SERVICE_RUNNING
:
1083 case SERVICE_CONTINUE_PENDING
:
1084 case SERVICE_PAUSE_PENDING
:
1085 case SERVICE_PAUSED
:
1095 DWORD
RSetServiceStatus(
1096 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1097 LPSERVICE_STATUS lpServiceStatus
)
1101 DPRINT("RSetServiceStatus() called\n");
1102 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1103 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1104 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1105 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1106 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1107 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1108 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1109 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1111 if (hServiceStatus
== 0)
1113 DPRINT("hServiceStatus == NULL!\n");
1114 return ERROR_INVALID_HANDLE
;
1117 lpService
= (PSERVICE
)hServiceStatus
;
1118 if (lpService
== NULL
)
1120 DPRINT("lpService == NULL!\n");
1121 return ERROR_INVALID_HANDLE
;
1124 /* Check current state */
1125 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1127 DPRINT("Invalid service state!\n");
1128 return ERROR_INVALID_DATA
;
1131 /* Check service type */
1132 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1133 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1135 DPRINT("Invalid service type!\n");
1136 return ERROR_INVALID_DATA
;
1139 /* Check accepted controls */
1140 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1142 DPRINT("Invalid controls accepted!\n");
1143 return ERROR_INVALID_DATA
;
1146 /* Lock the service database exclusively */
1147 ScmLockDatabaseExclusive();
1149 RtlCopyMemory(&lpService
->Status
,
1151 sizeof(SERVICE_STATUS
));
1153 /* Unlock the service database */
1154 ScmUnlockDatabase();
1156 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1157 DPRINT("RSetServiceStatus() done\n");
1159 return ERROR_SUCCESS
;
1164 DWORD
RUnlockServiceDatabase(
1168 return ERROR_SUCCESS
;
1173 DWORD
RNotifyBootConfigStatus(
1174 SVCCTL_HANDLEW lpMachineName
,
1175 DWORD BootAcceptable
)
1177 DPRINT1("RNotifyBootConfigStatus(%p %lu) called\n", lpMachineName
, BootAcceptable
);
1178 return ERROR_SUCCESS
;
1181 // return ERROR_CALL_NOT_IMPLEMENTED;
1186 DWORD
RI_ScSetServiceBitsW(
1187 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1188 DWORD dwServiceBits
,
1190 int bUpdateImmediately
,
1194 return ERROR_CALL_NOT_IMPLEMENTED
;
1199 DWORD
RChangeServiceConfigW(
1200 SC_RPC_HANDLE hService
,
1201 DWORD dwServiceType
,
1203 DWORD dwErrorControl
,
1204 LPWSTR lpBinaryPathName
,
1205 LPWSTR lpLoadOrderGroup
,
1207 LPBYTE lpDependencies
,
1209 LPWSTR lpServiceStartName
,
1212 LPWSTR lpDisplayName
)
1214 DWORD dwError
= ERROR_SUCCESS
;
1215 PSERVICE_HANDLE hSvc
;
1216 PSERVICE lpService
= NULL
;
1217 HKEY hServiceKey
= NULL
;
1218 LPWSTR lpDisplayNameW
= NULL
;
1220 DPRINT("RChangeServiceConfigW() called\n");
1221 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1222 DPRINT("dwStartType = %lu\n", dwStartType
);
1223 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1224 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1225 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1226 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1229 return ERROR_SHUTDOWN_IN_PROGRESS
;
1231 hSvc
= ScmGetServiceFromHandle(hService
);
1234 DPRINT1("Invalid service handle!\n");
1235 return ERROR_INVALID_HANDLE
;
1238 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1239 SERVICE_CHANGE_CONFIG
))
1241 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1242 return ERROR_ACCESS_DENIED
;
1245 lpService
= hSvc
->ServiceEntry
;
1246 if (lpService
== NULL
)
1248 DPRINT("lpService == NULL!\n");
1249 return ERROR_INVALID_HANDLE
;
1252 /* Lock the service database exclusively */
1253 ScmLockDatabaseExclusive();
1255 if (lpService
->bDeleted
)
1257 DPRINT("The service has already been marked for delete!\n");
1258 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1262 /* Open the service key */
1263 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1266 if (dwError
!= ERROR_SUCCESS
)
1269 /* Write service data to the registry */
1270 /* Set the display name */
1271 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1273 RegSetValueExW(hServiceKey
,
1277 (LPBYTE
)lpDisplayName
,
1278 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1280 /* Update the display name */
1281 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1283 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1284 if (lpDisplayNameW
== NULL
)
1286 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1290 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1291 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1293 lpService
->lpDisplayName
= lpDisplayNameW
;
1296 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1298 /* Set the service type */
1299 dwError
= RegSetValueExW(hServiceKey
,
1303 (LPBYTE
)&dwServiceType
,
1305 if (dwError
!= ERROR_SUCCESS
)
1308 lpService
->Status
.dwServiceType
= dwServiceType
;
1311 if (dwStartType
!= SERVICE_NO_CHANGE
)
1313 /* Set the start value */
1314 dwError
= RegSetValueExW(hServiceKey
,
1318 (LPBYTE
)&dwStartType
,
1320 if (dwError
!= ERROR_SUCCESS
)
1323 lpService
->dwStartType
= dwStartType
;
1326 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1328 /* Set the error control value */
1329 dwError
= RegSetValueExW(hServiceKey
,
1333 (LPBYTE
)&dwErrorControl
,
1335 if (dwError
!= ERROR_SUCCESS
)
1338 lpService
->dwErrorControl
= dwErrorControl
;
1342 /* FIXME: set the new ImagePath value */
1344 /* Set the image path */
1345 if (dwServiceType
& SERVICE_WIN32
)
1347 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1349 dwError
= RegSetValueExW(hServiceKey
,
1353 (LPBYTE
)lpBinaryPathName
,
1354 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1355 if (dwError
!= ERROR_SUCCESS
)
1359 else if (dwServiceType
& SERVICE_DRIVER
)
1361 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1363 dwError
= RegSetValueExW(hServiceKey
,
1367 (LPBYTE
)lpImagePath
,
1368 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1369 if (dwError
!= ERROR_SUCCESS
)
1375 /* Set the group name */
1376 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1378 dwError
= RegSetValueExW(hServiceKey
,
1382 (LPBYTE
)lpLoadOrderGroup
,
1383 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1384 if (dwError
!= ERROR_SUCCESS
)
1387 dwError
= ScmSetServiceGroup(lpService
,
1389 if (dwError
!= ERROR_SUCCESS
)
1393 if (lpdwTagId
!= NULL
)
1395 dwError
= ScmAssignNewTag(lpService
);
1396 if (dwError
!= ERROR_SUCCESS
)
1399 dwError
= RegSetValueExW(hServiceKey
,
1403 (LPBYTE
)&lpService
->dwTag
,
1405 if (dwError
!= ERROR_SUCCESS
)
1408 *lpdwTagId
= lpService
->dwTag
;
1411 /* Write dependencies */
1412 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1414 dwError
= ScmWriteDependencies(hServiceKey
,
1415 (LPWSTR
)lpDependencies
,
1417 if (dwError
!= ERROR_SUCCESS
)
1421 if (lpPassword
!= NULL
)
1423 /* FIXME: Write password */
1427 if (hServiceKey
!= NULL
)
1428 RegCloseKey(hServiceKey
);
1430 /* Unlock the service database */
1431 ScmUnlockDatabase();
1433 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1439 /* Create a path suitable for the bootloader out of the full path */
1441 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1443 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1446 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1447 OBJECT_ATTRIBUTES ObjectAttributes
;
1449 HANDLE SymbolicLinkHandle
;
1451 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1453 ServiceNameLen
= wcslen(CanonName
);
1455 /* First check, if it's already good */
1456 if (ServiceNameLen
> 12 &&
1457 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1459 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1460 if (*RelativeName
== NULL
)
1462 DPRINT("Error allocating memory for boot driver name!\n");
1463 return ERROR_NOT_ENOUGH_MEMORY
;
1467 wcscpy(*RelativeName
, CanonName
);
1469 DPRINT("Bootdriver name %S\n", *RelativeName
);
1470 return ERROR_SUCCESS
;
1473 /* If it has %SystemRoot% prefix, substitute it to \System*/
1474 if (ServiceNameLen
> 13 &&
1475 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1477 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1478 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1480 if (*RelativeName
== NULL
)
1482 DPRINT("Error allocating memory for boot driver name!\n");
1483 return ERROR_NOT_ENOUGH_MEMORY
;
1487 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1488 wcscat(*RelativeName
, CanonName
+ 13);
1490 DPRINT("Bootdriver name %S\n", *RelativeName
);
1491 return ERROR_SUCCESS
;
1494 /* Get buffer size needed for expanding env strings */
1495 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1497 if (BufferSize
<= 1)
1499 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1500 return ERROR_INVALID_ENVIRONMENT
;
1503 /* Allocate memory, since the size is known now */
1504 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1507 DPRINT("Error allocating memory for boot driver name!\n");
1508 return ERROR_NOT_ENOUGH_MEMORY
;
1512 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1515 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1516 LocalFree(Expanded
);
1517 return ERROR_NOT_ENOUGH_MEMORY
;
1520 /* Convert to NY-style path */
1521 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1523 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1524 return ERROR_INVALID_ENVIRONMENT
;
1527 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1529 /* No need to keep the dos-path anymore */
1530 LocalFree(Expanded
);
1532 /* Copy it to the allocated place */
1533 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1536 DPRINT("Error allocating memory for boot driver name!\n");
1537 return ERROR_NOT_ENOUGH_MEMORY
;
1540 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1541 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1542 Expanded
[ExpandedLen
] = 0;
1544 if (ServiceNameLen
> ExpandedLen
&&
1545 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1547 /* Only \SystemRoot\ is missing */
1548 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1549 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1550 if (*RelativeName
== NULL
)
1552 DPRINT("Error allocating memory for boot driver name!\n");
1553 LocalFree(Expanded
);
1554 return ERROR_NOT_ENOUGH_MEMORY
;
1557 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1558 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1560 RtlFreeUnicodeString(&NtPathName
);
1561 return ERROR_SUCCESS
;
1564 /* The most complex case starts here */
1565 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1566 InitializeObjectAttributes(&ObjectAttributes
,
1568 OBJ_CASE_INSENSITIVE
,
1572 /* Open this symlink */
1573 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1575 if (NT_SUCCESS(Status
))
1577 LinkTarget
.Length
= 0;
1578 LinkTarget
.MaximumLength
= 0;
1580 DPRINT("Opened symbolic link object\n");
1582 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1583 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1585 /* Check if required buffer size is sane */
1586 if (BufferSize
> 0xFFFD)
1588 DPRINT("Too large buffer required\n");
1591 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1592 LocalFree(Expanded
);
1593 return ERROR_NOT_ENOUGH_MEMORY
;
1596 /* Alloc the string */
1597 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1598 if (!LinkTarget
.Buffer
)
1600 DPRINT("Unable to alloc buffer\n");
1601 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1602 LocalFree(Expanded
);
1603 return ERROR_NOT_ENOUGH_MEMORY
;
1606 /* Do a real query now */
1607 LinkTarget
.Length
= (USHORT
)BufferSize
;
1608 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1610 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1611 if (NT_SUCCESS(Status
))
1613 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1615 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1616 if ((ServiceNameLen
> ExpandedLen
) &&
1617 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1619 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1620 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1622 if (*RelativeName
== NULL
)
1624 DPRINT("Unable to alloc buffer\n");
1625 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1626 LocalFree(Expanded
);
1627 RtlFreeUnicodeString(&NtPathName
);
1628 return ERROR_NOT_ENOUGH_MEMORY
;
1631 /* Copy it over, substituting the first part
1633 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1634 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1637 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1638 LocalFree(Expanded
);
1639 RtlFreeUnicodeString(&NtPathName
);
1641 /* Return success */
1642 return ERROR_SUCCESS
;
1646 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1647 LocalFree(Expanded
);
1648 RtlFreeUnicodeString(&NtPathName
);
1649 return ERROR_INVALID_PARAMETER
;
1654 DPRINT("Error, Status = %08X\n", Status
);
1655 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1656 LocalFree(Expanded
);
1657 RtlFreeUnicodeString(&NtPathName
);
1658 return ERROR_INVALID_PARAMETER
;
1663 DPRINT("Error, Status = %08X\n", Status
);
1664 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1665 LocalFree(Expanded
);
1666 RtlFreeUnicodeString(&NtPathName
);
1667 return ERROR_INVALID_PARAMETER
;
1672 DPRINT("Error, Status = %08X\n", Status
);
1673 LocalFree(Expanded
);
1674 return ERROR_INVALID_PARAMETER
;
1678 *RelativeName
= NULL
;
1679 return ERROR_INVALID_PARAMETER
;
1683 ScmCanonDriverImagePath(DWORD dwStartType
,
1684 const wchar_t *lpServiceName
,
1685 wchar_t **lpCanonName
)
1687 DWORD ServiceNameLen
, Result
;
1688 UNICODE_STRING NtServiceName
;
1689 WCHAR
*RelativeName
;
1690 const WCHAR
*SourceName
= lpServiceName
;
1692 /* Calculate the length of the service's name */
1693 ServiceNameLen
= wcslen(lpServiceName
);
1695 /* 12 is wcslen(L"\\SystemRoot\\") */
1696 if (ServiceNameLen
> 12 &&
1697 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1699 /* SystemRoot prefix is already included */
1701 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1703 if (*lpCanonName
== NULL
)
1705 DPRINT("Error allocating memory for canonized service name!\n");
1706 return ERROR_NOT_ENOUGH_MEMORY
;
1709 /* If it's a boot-time driver, it must be systemroot relative */
1710 if (dwStartType
== SERVICE_BOOT_START
)
1714 wcscpy(*lpCanonName
, SourceName
);
1716 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1720 /* Check if it has %SystemRoot% (len=13) */
1721 if (ServiceNameLen
> 13 &&
1722 !_wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1724 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1725 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1727 if (*lpCanonName
== NULL
)
1729 DPRINT("Error allocating memory for canonized service name!\n");
1730 return ERROR_NOT_ENOUGH_MEMORY
;
1733 /* If it's a boot-time driver, it must be systemroot relative */
1734 if (dwStartType
== SERVICE_BOOT_START
)
1735 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1737 wcscat(*lpCanonName
, lpServiceName
+ 13);
1739 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1743 /* Check if it's a relative path name */
1744 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1746 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1748 if (*lpCanonName
== NULL
)
1750 DPRINT("Error allocating memory for canonized service name!\n");
1751 return ERROR_NOT_ENOUGH_MEMORY
;
1754 /* Just copy it over without changing */
1755 wcscpy(*lpCanonName
, lpServiceName
);
1760 /* It seems to be a DOS path, convert it */
1761 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1763 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
1764 return ERROR_INVALID_PARAMETER
;
1767 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1769 if (*lpCanonName
== NULL
)
1771 DPRINT("Error allocating memory for canonized service name!\n");
1772 RtlFreeUnicodeString(&NtServiceName
);
1773 return ERROR_NOT_ENOUGH_MEMORY
;
1776 /* Copy the string */
1777 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1779 /* The unicode string is not needed anymore */
1780 RtlFreeUnicodeString(&NtServiceName
);
1782 if (dwStartType
!= SERVICE_BOOT_START
)
1784 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1788 /* The service is boot-started, so must be relative */
1789 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1792 /* There is a problem, free name and return */
1793 LocalFree(*lpCanonName
);
1794 DPRINT("Error converting named!\n");
1798 ASSERT(RelativeName
);
1800 /* Copy that string */
1801 wcscpy(*lpCanonName
, RelativeName
+ 12);
1803 /* Free the allocated buffer */
1804 LocalFree(RelativeName
);
1806 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1814 DWORD
RCreateServiceW(
1815 SC_RPC_HANDLE hSCManager
,
1816 LPCWSTR lpServiceName
,
1817 LPCWSTR lpDisplayName
,
1818 DWORD dwDesiredAccess
,
1819 DWORD dwServiceType
,
1821 DWORD dwErrorControl
,
1822 LPCWSTR lpBinaryPathName
,
1823 LPCWSTR lpLoadOrderGroup
,
1825 LPBYTE lpDependencies
,
1827 LPCWSTR lpServiceStartName
,
1830 LPSC_RPC_HANDLE lpServiceHandle
)
1832 PMANAGER_HANDLE hManager
;
1833 DWORD dwError
= ERROR_SUCCESS
;
1834 PSERVICE lpService
= NULL
;
1835 SC_HANDLE hServiceHandle
= NULL
;
1836 LPWSTR lpImagePath
= NULL
;
1837 HKEY hServiceKey
= NULL
;
1838 LPWSTR lpObjectName
;
1840 DPRINT("RCreateServiceW() called\n");
1841 DPRINT("lpServiceName = %S\n", lpServiceName
);
1842 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1843 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1844 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1845 DPRINT("dwStartType = %lu\n", dwStartType
);
1846 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1847 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1848 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1851 return ERROR_SHUTDOWN_IN_PROGRESS
;
1853 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
1854 if (hManager
== NULL
)
1856 DPRINT1("Invalid service manager handle!\n");
1857 return ERROR_INVALID_HANDLE
;
1860 /* Check access rights */
1861 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1862 SC_MANAGER_CREATE_SERVICE
))
1864 DPRINT("Insufficient access rights! 0x%lx\n",
1865 hManager
->Handle
.DesiredAccess
);
1866 return ERROR_ACCESS_DENIED
;
1869 if (wcslen(lpServiceName
) == 0)
1871 return ERROR_INVALID_NAME
;
1874 if (wcslen(lpBinaryPathName
) == 0)
1876 return ERROR_INVALID_PARAMETER
;
1879 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1880 (lpServiceStartName
))
1882 return ERROR_INVALID_PARAMETER
;
1885 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1886 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1887 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1889 return ERROR_INVALID_PARAMETER
;
1892 if (dwStartType
> SERVICE_DISABLED
)
1894 return ERROR_INVALID_PARAMETER
;
1897 /* Lock the service database exclusively */
1898 ScmLockDatabaseExclusive();
1900 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1903 /* Unlock the service database */
1904 ScmUnlockDatabase();
1906 /* check if it is marked for deletion */
1907 if (lpService
->bDeleted
)
1908 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1909 /* Return Error exist */
1910 return ERROR_SERVICE_EXISTS
;
1913 if (lpDisplayName
!= NULL
&&
1914 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1916 /* Unlock the service database */
1917 ScmUnlockDatabase();
1919 return ERROR_DUPLICATE_SERVICE_NAME
;
1922 if (dwServiceType
& SERVICE_DRIVER
)
1924 dwError
= ScmCanonDriverImagePath(dwStartType
,
1927 if (dwError
!= ERROR_SUCCESS
)
1932 if (dwStartType
== SERVICE_BOOT_START
||
1933 dwStartType
== SERVICE_SYSTEM_START
)
1935 /* Unlock the service database */
1936 ScmUnlockDatabase();
1938 return ERROR_INVALID_PARAMETER
;
1942 /* Allocate a new service entry */
1943 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1945 if (dwError
!= ERROR_SUCCESS
)
1948 /* Fill the new service entry */
1949 lpService
->Status
.dwServiceType
= dwServiceType
;
1950 lpService
->dwStartType
= dwStartType
;
1951 lpService
->dwErrorControl
= dwErrorControl
;
1953 /* Fill the display name */
1954 if (lpDisplayName
!= NULL
&&
1955 *lpDisplayName
!= 0 &&
1956 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1958 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1959 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1960 if (lpService
->lpDisplayName
== NULL
)
1962 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1965 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1968 /* Assign the service to a group */
1969 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1971 dwError
= ScmSetServiceGroup(lpService
,
1973 if (dwError
!= ERROR_SUCCESS
)
1977 /* Assign a new tag */
1978 if (lpdwTagId
!= NULL
)
1980 dwError
= ScmAssignNewTag(lpService
);
1981 if (dwError
!= ERROR_SUCCESS
)
1985 /* Write service data to the registry */
1986 /* Create the service key */
1987 dwError
= ScmCreateServiceKey(lpServiceName
,
1990 if (dwError
!= ERROR_SUCCESS
)
1993 /* Set the display name */
1994 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1996 RegSetValueExW(hServiceKey
,
2000 (LPBYTE
)lpDisplayName
,
2001 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2004 /* Set the service type */
2005 dwError
= RegSetValueExW(hServiceKey
,
2009 (LPBYTE
)&dwServiceType
,
2011 if (dwError
!= ERROR_SUCCESS
)
2014 /* Set the start value */
2015 dwError
= RegSetValueExW(hServiceKey
,
2019 (LPBYTE
)&dwStartType
,
2021 if (dwError
!= ERROR_SUCCESS
)
2024 /* Set the error control value */
2025 dwError
= RegSetValueExW(hServiceKey
,
2029 (LPBYTE
)&dwErrorControl
,
2031 if (dwError
!= ERROR_SUCCESS
)
2034 /* Set the image path */
2035 if (dwServiceType
& SERVICE_WIN32
)
2037 dwError
= RegSetValueExW(hServiceKey
,
2041 (LPBYTE
)lpBinaryPathName
,
2042 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
2043 if (dwError
!= ERROR_SUCCESS
)
2046 else if (dwServiceType
& SERVICE_DRIVER
)
2048 dwError
= RegSetValueExW(hServiceKey
,
2052 (LPBYTE
)lpImagePath
,
2053 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2054 if (dwError
!= ERROR_SUCCESS
)
2058 /* Set the group name */
2059 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2061 dwError
= RegSetValueExW(hServiceKey
,
2065 (LPBYTE
)lpLoadOrderGroup
,
2066 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
2067 if (dwError
!= ERROR_SUCCESS
)
2071 if (lpdwTagId
!= NULL
)
2073 dwError
= RegSetValueExW(hServiceKey
,
2077 (LPBYTE
)&lpService
->dwTag
,
2079 if (dwError
!= ERROR_SUCCESS
)
2083 /* Write dependencies */
2084 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2086 dwError
= ScmWriteDependencies(hServiceKey
,
2087 (LPWSTR
)lpDependencies
,
2089 if (dwError
!= ERROR_SUCCESS
)
2093 /* Write service start name */
2094 if (dwServiceType
& SERVICE_WIN32
)
2096 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2097 dwError
= RegSetValueExW(hServiceKey
,
2101 (LPBYTE
)lpObjectName
,
2102 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
2103 if (dwError
!= ERROR_SUCCESS
)
2107 if (lpPassword
!= NULL
)
2109 /* FIXME: Write password */
2112 dwError
= ScmCreateServiceHandle(lpService
,
2114 if (dwError
!= ERROR_SUCCESS
)
2117 dwError
= ScmCheckAccess(hServiceHandle
,
2119 if (dwError
!= ERROR_SUCCESS
)
2122 lpService
->dwRefCount
= 1;
2123 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2126 /* Unlock the service database */
2127 ScmUnlockDatabase();
2129 if (hServiceKey
!= NULL
)
2130 RegCloseKey(hServiceKey
);
2132 if (dwError
== ERROR_SUCCESS
)
2134 DPRINT("hService %p\n", hServiceHandle
);
2135 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2137 if (lpdwTagId
!= NULL
)
2138 *lpdwTagId
= lpService
->dwTag
;
2142 /* Release the display name buffer */
2143 if (lpService
->lpServiceName
!= NULL
)
2144 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2148 /* Remove the service handle */
2149 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2152 if (lpService
!= NULL
)
2154 /* FIXME: remove the service entry */
2158 if (lpImagePath
!= NULL
)
2159 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2161 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2168 DWORD
REnumDependentServicesW(
2169 SC_RPC_HANDLE hService
,
2170 DWORD dwServiceState
,
2173 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2174 LPBOUNDED_DWORD_256K lpServicesReturned
)
2176 DWORD dwError
= ERROR_SUCCESS
;
2177 DWORD dwServicesReturned
= 0;
2178 DWORD dwServiceCount
;
2179 HKEY hServicesKey
= NULL
;
2180 PSERVICE_HANDLE hSvc
;
2181 PSERVICE lpService
= NULL
;
2182 PSERVICE
*lpServicesArray
= NULL
;
2183 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2186 *pcbBytesNeeded
= 0;
2187 *lpServicesReturned
= 0;
2189 DPRINT("REnumDependentServicesW() called\n");
2191 hSvc
= ScmGetServiceFromHandle(hService
);
2194 DPRINT1("Invalid service handle!\n");
2195 return ERROR_INVALID_HANDLE
;
2198 lpService
= hSvc
->ServiceEntry
;
2200 /* Check access rights */
2201 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2202 SC_MANAGER_ENUMERATE_SERVICE
))
2204 DPRINT("Insufficient access rights! 0x%lx\n",
2205 hSvc
->Handle
.DesiredAccess
);
2206 return ERROR_ACCESS_DENIED
;
2209 /* Open the Services Reg key */
2210 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2211 L
"System\\CurrentControlSet\\Services",
2215 if (dwError
!= ERROR_SUCCESS
)
2218 /* First determine the bytes needed and get the number of dependent services */
2219 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2224 &dwServicesReturned
);
2225 if (dwError
!= ERROR_SUCCESS
)
2228 /* If buffer size is less than the bytes needed or pointer is null */
2229 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2231 dwError
= ERROR_MORE_DATA
;
2235 /* Allocate memory for array of service pointers */
2236 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2238 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2239 if (!lpServicesArray
)
2241 DPRINT("Could not allocate a buffer!!\n");
2242 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2246 dwServicesReturned
= 0;
2247 *pcbBytesNeeded
= 0;
2249 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2254 &dwServicesReturned
);
2255 if (dwError
!= ERROR_SUCCESS
)
2260 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2261 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2263 /* Copy EnumDepenedentService to Buffer */
2264 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2266 lpService
= lpServicesArray
[dwServiceCount
];
2268 /* Copy status info */
2269 memcpy(&lpServicesPtr
->ServiceStatus
,
2271 sizeof(SERVICE_STATUS
));
2273 /* Copy display name */
2274 wcscpy(lpStr
, lpService
->lpDisplayName
);
2275 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2276 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2278 /* Copy service name */
2279 wcscpy(lpStr
, lpService
->lpServiceName
);
2280 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2281 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2286 *lpServicesReturned
= dwServicesReturned
;
2289 if (lpServicesArray
!= NULL
)
2290 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2292 RegCloseKey(hServicesKey
);
2294 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2301 DWORD
REnumServicesStatusW(
2302 SC_RPC_HANDLE hSCManager
,
2303 DWORD dwServiceType
,
2304 DWORD dwServiceState
,
2307 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2308 LPBOUNDED_DWORD_256K lpServicesReturned
,
2309 LPBOUNDED_DWORD_256K lpResumeHandle
)
2311 PMANAGER_HANDLE hManager
;
2313 DWORD dwError
= ERROR_SUCCESS
;
2314 PLIST_ENTRY ServiceEntry
;
2315 PSERVICE CurrentService
;
2317 DWORD dwRequiredSize
;
2318 DWORD dwServiceCount
;
2320 DWORD dwLastResumeCount
= 0;
2321 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2324 DPRINT("REnumServicesStatusW() called\n");
2327 return ERROR_SHUTDOWN_IN_PROGRESS
;
2329 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2330 if (hManager
== NULL
)
2332 DPRINT1("Invalid service manager handle!\n");
2333 return ERROR_INVALID_HANDLE
;
2337 *pcbBytesNeeded
= 0;
2338 *lpServicesReturned
= 0;
2340 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2342 DPRINT("Not a valid Service Type!\n");
2343 return ERROR_INVALID_PARAMETER
;
2346 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2348 DPRINT("Not a valid Service State!\n");
2349 return ERROR_INVALID_PARAMETER
;
2352 /* Check access rights */
2353 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2354 SC_MANAGER_ENUMERATE_SERVICE
))
2356 DPRINT("Insufficient access rights! 0x%lx\n",
2357 hManager
->Handle
.DesiredAccess
);
2358 return ERROR_ACCESS_DENIED
;
2362 dwLastResumeCount
= *lpResumeHandle
;
2364 /* Lock the service database shared */
2365 ScmLockDatabaseShared();
2367 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2368 if (lpService
== NULL
)
2370 dwError
= ERROR_SUCCESS
;
2377 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2378 ServiceEntry
!= &ServiceListHead
;
2379 ServiceEntry
= ServiceEntry
->Flink
)
2381 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2385 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2388 dwState
= SERVICE_ACTIVE
;
2389 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2390 dwState
= SERVICE_INACTIVE
;
2392 if ((dwState
& dwServiceState
) == 0)
2395 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2396 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2397 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2399 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2401 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2405 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2406 dwRequiredSize
+= dwSize
;
2408 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2411 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2412 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2415 ServiceEntry
!= &ServiceListHead
;
2416 ServiceEntry
= ServiceEntry
->Flink
)
2418 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2422 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2425 dwState
= SERVICE_ACTIVE
;
2426 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2427 dwState
= SERVICE_INACTIVE
;
2429 if ((dwState
& dwServiceState
) == 0)
2432 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2433 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2434 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2436 dwError
= ERROR_MORE_DATA
;
2439 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2442 *lpResumeHandle
= dwLastResumeCount
;
2444 *lpServicesReturned
= dwServiceCount
;
2445 *pcbBytesNeeded
= dwRequiredSize
;
2447 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2448 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2449 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2452 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2453 ServiceEntry
!= &ServiceListHead
;
2454 ServiceEntry
= ServiceEntry
->Flink
)
2456 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2460 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2463 dwState
= SERVICE_ACTIVE
;
2464 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2465 dwState
= SERVICE_INACTIVE
;
2467 if ((dwState
& dwServiceState
) == 0)
2470 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2471 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2472 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2474 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2477 /* Copy the service name */
2478 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2479 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2480 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2482 /* Copy the display name */
2483 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2484 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2485 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2487 /* Copy the status information */
2488 memcpy(&lpStatusPtr
->ServiceStatus
,
2489 &CurrentService
->Status
,
2490 sizeof(SERVICE_STATUS
));
2493 dwRequiredSize
+= dwSize
;
2498 *pcbBytesNeeded
= 0;
2499 if (lpResumeHandle
) *lpResumeHandle
= 0;
2503 /* Unlock the service database */
2504 ScmUnlockDatabase();
2506 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2513 DWORD
ROpenSCManagerW(
2514 LPWSTR lpMachineName
,
2515 LPWSTR lpDatabaseName
,
2516 DWORD dwDesiredAccess
,
2517 LPSC_RPC_HANDLE lpScHandle
)
2522 DPRINT("ROpenSCManagerW() called\n");
2523 DPRINT("lpMachineName = %p\n", lpMachineName
);
2524 DPRINT("lpMachineName: %S\n", lpMachineName
);
2525 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2526 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2527 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2530 return ERROR_SHUTDOWN_IN_PROGRESS
;
2533 return ERROR_INVALID_PARAMETER
;
2535 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2537 if (dwError
!= ERROR_SUCCESS
)
2539 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2543 /* Check the desired access */
2544 dwError
= ScmCheckAccess(hHandle
,
2545 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2546 if (dwError
!= ERROR_SUCCESS
)
2548 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2549 HeapFree(GetProcessHeap(), 0, hHandle
);
2553 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2554 DPRINT("*hScm = %p\n", *lpScHandle
);
2556 DPRINT("ROpenSCManagerW() done\n");
2558 return ERROR_SUCCESS
;
2563 DWORD
ROpenServiceW(
2564 SC_RPC_HANDLE hSCManager
,
2565 LPWSTR lpServiceName
,
2566 DWORD dwDesiredAccess
,
2567 LPSC_RPC_HANDLE lpServiceHandle
)
2570 PMANAGER_HANDLE hManager
;
2572 DWORD dwError
= ERROR_SUCCESS
;
2574 DPRINT("ROpenServiceW() called\n");
2575 DPRINT("hSCManager = %p\n", hSCManager
);
2576 DPRINT("lpServiceName = %p\n", lpServiceName
);
2577 DPRINT("lpServiceName: %S\n", lpServiceName
);
2578 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2581 return ERROR_SHUTDOWN_IN_PROGRESS
;
2583 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2584 if (hManager
== NULL
)
2586 DPRINT1("Invalid service manager handle!\n");
2587 return ERROR_INVALID_HANDLE
;
2590 if (!lpServiceHandle
)
2591 return ERROR_INVALID_PARAMETER
;
2594 return ERROR_INVALID_ADDRESS
;
2596 /* Lock the service database exclusive */
2597 ScmLockDatabaseExclusive();
2599 /* Get service database entry */
2600 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2601 if (lpService
== NULL
)
2603 DPRINT("Could not find a service!\n");
2604 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
2608 /* Create a service handle */
2609 dwError
= ScmCreateServiceHandle(lpService
,
2611 if (dwError
!= ERROR_SUCCESS
)
2613 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2617 /* Check the desired access */
2618 dwError
= ScmCheckAccess(hHandle
,
2620 if (dwError
!= ERROR_SUCCESS
)
2622 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2623 HeapFree(GetProcessHeap(), 0, hHandle
);
2627 lpService
->dwRefCount
++;
2628 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2630 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2631 DPRINT("*hService = %p\n", *lpServiceHandle
);
2634 /* Unlock the service database */
2635 ScmUnlockDatabase();
2637 DPRINT("ROpenServiceW() done\n");
2644 DWORD
RQueryServiceConfigW(
2645 SC_RPC_HANDLE hService
,
2646 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2648 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2650 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2651 DWORD dwError
= ERROR_SUCCESS
;
2652 PSERVICE_HANDLE hSvc
;
2653 PSERVICE lpService
= NULL
;
2654 HKEY hServiceKey
= NULL
;
2655 LPWSTR lpImagePath
= NULL
;
2656 LPWSTR lpServiceStartName
= NULL
;
2657 LPWSTR lpDependencies
= NULL
;
2658 DWORD dwDependenciesLength
= 0;
2659 DWORD dwRequiredSize
;
2660 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2661 WCHAR lpEmptyString
[] = {0,0};
2664 DPRINT("RQueryServiceConfigW() called\n");
2667 return ERROR_SHUTDOWN_IN_PROGRESS
;
2669 hSvc
= ScmGetServiceFromHandle(hService
);
2672 DPRINT1("Invalid service handle!\n");
2673 return ERROR_INVALID_HANDLE
;
2676 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2677 SERVICE_QUERY_CONFIG
))
2679 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2680 return ERROR_ACCESS_DENIED
;
2683 lpService
= hSvc
->ServiceEntry
;
2684 if (lpService
== NULL
)
2686 DPRINT("lpService == NULL!\n");
2687 return ERROR_INVALID_HANDLE
;
2690 /* Lock the service database shared */
2691 ScmLockDatabaseShared();
2693 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2696 if (dwError
!= ERROR_SUCCESS
)
2699 /* Read the image path */
2700 dwError
= ScmReadString(hServiceKey
,
2703 if (dwError
!= ERROR_SUCCESS
)
2706 /* Read the service start name */
2707 ScmReadString(hServiceKey
,
2709 &lpServiceStartName
);
2711 /* Read the dependencies */
2712 ScmReadDependencies(hServiceKey
,
2714 &dwDependenciesLength
);
2716 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2718 if (lpImagePath
!= NULL
)
2719 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2721 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2723 if (lpService
->lpGroup
!= NULL
)
2724 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2726 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2728 if (lpDependencies
!= NULL
)
2729 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2731 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2733 if (lpServiceStartName
!= NULL
)
2734 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2736 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2738 if (lpService
->lpDisplayName
!= NULL
)
2739 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2741 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2743 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2745 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2749 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2750 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2751 lpConfig
->dwStartType
= lpService
->dwStartType
;
2752 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2753 lpConfig
->dwTagId
= lpService
->dwTag
;
2755 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2757 /* Append the image path */
2758 if (lpImagePath
!= NULL
)
2760 wcscpy(lpStr
, lpImagePath
);
2764 wcscpy(lpStr
, lpEmptyString
);
2767 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2768 lpStr
+= (wcslen(lpStr
) + 1);
2770 /* Append the group name */
2771 if (lpService
->lpGroup
!= NULL
)
2773 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2777 wcscpy(lpStr
, lpEmptyString
);
2780 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2781 lpStr
+= (wcslen(lpStr
) + 1);
2783 /* Append Dependencies */
2784 if (lpDependencies
!= NULL
)
2788 dwDependenciesLength
* sizeof(WCHAR
));
2792 wcscpy(lpStr
, lpEmptyString
);
2795 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2796 if (lpDependencies
!= NULL
)
2797 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2799 lpStr
+= (wcslen(lpStr
) + 1);
2801 /* Append the service start name */
2802 if (lpServiceStartName
!= NULL
)
2804 wcscpy(lpStr
, lpServiceStartName
);
2808 wcscpy(lpStr
, lpEmptyString
);
2811 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2812 lpStr
+= (wcslen(lpStr
) + 1);
2814 /* Append the display name */
2815 if (lpService
->lpDisplayName
!= NULL
)
2817 wcscpy(lpStr
, lpService
->lpDisplayName
);
2821 wcscpy(lpStr
, lpEmptyString
);
2824 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2827 if (pcbBytesNeeded
!= NULL
)
2828 *pcbBytesNeeded
= dwRequiredSize
;
2831 /* Unlock the service database */
2832 ScmUnlockDatabase();
2834 if (lpImagePath
!= NULL
)
2835 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2837 if (lpServiceStartName
!= NULL
)
2838 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2840 if (lpDependencies
!= NULL
)
2841 HeapFree(GetProcessHeap(), 0, lpDependencies
);
2843 if (hServiceKey
!= NULL
)
2844 RegCloseKey(hServiceKey
);
2846 DPRINT("RQueryServiceConfigW() done\n");
2853 DWORD
RQueryServiceLockStatusW(
2854 SC_RPC_HANDLE hSCManager
,
2855 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2857 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2860 return ERROR_CALL_NOT_IMPLEMENTED
;
2865 DWORD
RStartServiceW(
2866 SC_RPC_HANDLE hService
,
2868 LPSTRING_PTRSW argv
)
2870 DWORD dwError
= ERROR_SUCCESS
;
2871 PSERVICE_HANDLE hSvc
;
2872 PSERVICE lpService
= NULL
;
2875 DPRINT("RStartServiceW(%p %lu %p) called\n", hService
, argc
, argv
);
2876 DPRINT(" argc: %lu\n", argc
);
2879 for (i
= 0; i
< argc
; i
++)
2881 DPRINT(" argv[%lu]: %S\n", i
, argv
[i
]);
2886 return ERROR_SHUTDOWN_IN_PROGRESS
;
2888 hSvc
= ScmGetServiceFromHandle(hService
);
2891 DPRINT1("Invalid service handle!\n");
2892 return ERROR_INVALID_HANDLE
;
2895 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2898 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2899 return ERROR_ACCESS_DENIED
;
2902 lpService
= hSvc
->ServiceEntry
;
2903 if (lpService
== NULL
)
2905 DPRINT("lpService == NULL!\n");
2906 return ERROR_INVALID_HANDLE
;
2909 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2910 return ERROR_SERVICE_DISABLED
;
2912 if (lpService
->bDeleted
)
2913 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2915 /* Start the service */
2916 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2923 DWORD
RGetServiceDisplayNameW(
2924 SC_RPC_HANDLE hSCManager
,
2925 LPCWSTR lpServiceName
,
2926 LPWSTR lpDisplayName
,
2929 // PMANAGER_HANDLE hManager;
2934 DPRINT("RGetServiceDisplayNameW() called\n");
2935 DPRINT("hSCManager = %p\n", hSCManager
);
2936 DPRINT("lpServiceName: %S\n", lpServiceName
);
2937 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2938 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2940 // hManager = (PMANAGER_HANDLE)hSCManager;
2941 // if (hManager->Handle.Tag != MANAGER_TAG)
2943 // DPRINT("Invalid manager handle!\n");
2944 // return ERROR_INVALID_HANDLE;
2947 /* Get service database entry */
2948 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2949 if (lpService
== NULL
)
2951 DPRINT("Could not find a service!\n");
2953 /* If the service could not be found and lpcchBuffer is less than 2, windows
2954 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2955 if (*lpcchBuffer
< 2)
2958 if (lpDisplayName
!= NULL
)
2960 *lpDisplayName
= '\0';
2964 return ERROR_SERVICE_DOES_NOT_EXIST
;
2967 if (!lpService
->lpDisplayName
)
2969 dwLength
= wcslen(lpService
->lpServiceName
);
2971 if (lpDisplayName
!= NULL
&&
2972 *lpcchBuffer
> dwLength
)
2974 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2979 dwLength
= wcslen(lpService
->lpDisplayName
);
2981 if (lpDisplayName
!= NULL
&&
2982 *lpcchBuffer
> dwLength
)
2984 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2988 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2990 *lpcchBuffer
= dwLength
;
2997 DWORD
RGetServiceKeyNameW(
2998 SC_RPC_HANDLE hSCManager
,
2999 LPCWSTR lpDisplayName
,
3000 LPWSTR lpServiceName
,
3003 // PMANAGER_HANDLE hManager;
3008 DPRINT("RGetServiceKeyNameW() called\n");
3009 DPRINT("hSCManager = %p\n", hSCManager
);
3010 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
3011 DPRINT("lpServiceName: %p\n", lpServiceName
);
3012 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3014 // hManager = (PMANAGER_HANDLE)hSCManager;
3015 // if (hManager->Handle.Tag != MANAGER_TAG)
3017 // DPRINT("Invalid manager handle!\n");
3018 // return ERROR_INVALID_HANDLE;
3021 /* Get service database entry */
3022 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
3023 if (lpService
== NULL
)
3025 DPRINT("Could not find a service!\n");
3027 /* If the service could not be found and lpcchBuffer is less than 2, windows
3028 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3029 if (*lpcchBuffer
< 2)
3032 if (lpServiceName
!= NULL
)
3034 *lpServiceName
= '\0';
3038 return ERROR_SERVICE_DOES_NOT_EXIST
;
3041 dwLength
= wcslen(lpService
->lpServiceName
);
3043 if (lpServiceName
!= NULL
&&
3044 *lpcchBuffer
> dwLength
)
3046 wcscpy(lpServiceName
, lpService
->lpServiceName
);
3047 *lpcchBuffer
= dwLength
;
3048 return ERROR_SUCCESS
;
3051 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3053 *lpcchBuffer
= dwLength
;
3060 DWORD
RI_ScSetServiceBitsA(
3061 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3062 DWORD dwServiceBits
,
3064 int bUpdateImmediately
,
3068 return ERROR_CALL_NOT_IMPLEMENTED
;
3073 DWORD
RChangeServiceConfigA(
3074 SC_RPC_HANDLE hService
,
3075 DWORD dwServiceType
,
3077 DWORD dwErrorControl
,
3078 LPSTR lpBinaryPathName
,
3079 LPSTR lpLoadOrderGroup
,
3081 LPSTR lpDependencies
,
3083 LPSTR lpServiceStartName
,
3086 LPSTR lpDisplayName
)
3088 DWORD dwError
= ERROR_SUCCESS
;
3089 PSERVICE_HANDLE hSvc
;
3090 PSERVICE lpService
= NULL
;
3091 HKEY hServiceKey
= NULL
;
3092 LPWSTR lpDisplayNameW
= NULL
;
3093 // LPWSTR lpBinaryPathNameW = NULL;
3094 LPWSTR lpLoadOrderGroupW
= NULL
;
3095 LPWSTR lpDependenciesW
= NULL
;
3096 // LPWSTR lpPasswordW = NULL;
3098 DPRINT("RChangeServiceConfigA() called\n");
3099 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3100 DPRINT("dwStartType = %lu\n", dwStartType
);
3101 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3102 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3103 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3104 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3107 return ERROR_SHUTDOWN_IN_PROGRESS
;
3109 hSvc
= ScmGetServiceFromHandle(hService
);
3112 DPRINT1("Invalid service handle!\n");
3113 return ERROR_INVALID_HANDLE
;
3116 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3117 SERVICE_CHANGE_CONFIG
))
3119 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3120 return ERROR_ACCESS_DENIED
;
3123 lpService
= hSvc
->ServiceEntry
;
3124 if (lpService
== NULL
)
3126 DPRINT("lpService == NULL!\n");
3127 return ERROR_INVALID_HANDLE
;
3130 /* Lock the service database exclusively */
3131 ScmLockDatabaseExclusive();
3133 if (lpService
->bDeleted
)
3135 DPRINT("The service has already been marked for delete!\n");
3136 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
3140 /* Open the service key */
3141 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3144 if (dwError
!= ERROR_SUCCESS
)
3147 /* Write service data to the registry */
3149 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3151 /* Set the display name */
3152 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3154 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3155 if (lpDisplayNameW
== NULL
)
3157 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3161 MultiByteToWideChar(CP_ACP
,
3166 strlen(lpDisplayName
) + 1);
3168 RegSetValueExW(hServiceKey
,
3172 (LPBYTE
)lpDisplayNameW
,
3173 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3175 /* Update lpService->lpDisplayName */
3176 if (lpService
->lpDisplayName
)
3177 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3179 lpService
->lpDisplayName
= lpDisplayNameW
;
3182 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3184 /* Set the service type */
3185 dwError
= RegSetValueExW(hServiceKey
,
3189 (LPBYTE
)&dwServiceType
,
3191 if (dwError
!= ERROR_SUCCESS
)
3194 lpService
->Status
.dwServiceType
= dwServiceType
;
3197 if (dwStartType
!= SERVICE_NO_CHANGE
)
3199 /* Set the start value */
3200 dwError
= RegSetValueExW(hServiceKey
,
3204 (LPBYTE
)&dwStartType
,
3206 if (dwError
!= ERROR_SUCCESS
)
3209 lpService
->dwStartType
= dwStartType
;
3212 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3214 /* Set the error control value */
3215 dwError
= RegSetValueExW(hServiceKey
,
3219 (LPBYTE
)&dwErrorControl
,
3221 if (dwError
!= ERROR_SUCCESS
)
3224 lpService
->dwErrorControl
= dwErrorControl
;
3228 /* FIXME: set the new ImagePath value */
3230 /* Set the image path */
3231 if (dwServiceType
& SERVICE_WIN32
)
3233 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3235 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3236 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, strlen(lpBinaryPathName
)+1);
3237 dwError
= RegSetValueExW(hServiceKey
,
3241 (LPBYTE
)lpBinaryPathNameW
,
3242 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3243 if (dwError
!= ERROR_SUCCESS
)
3247 else if (dwServiceType
& SERVICE_DRIVER
)
3249 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3251 dwError
= RegSetValueExW(hServiceKey
,
3255 (LPBYTE
)lpImagePath
,
3256 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3257 if (dwError
!= ERROR_SUCCESS
)
3263 /* Set the group name */
3264 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3266 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3268 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3269 if (lpLoadOrderGroupW
== NULL
)
3271 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3275 MultiByteToWideChar(CP_ACP
,
3280 strlen(lpLoadOrderGroup
) + 1);
3282 dwError
= RegSetValueExW(hServiceKey
,
3286 (LPBYTE
)lpLoadOrderGroupW
,
3287 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3288 if (dwError
!= ERROR_SUCCESS
)
3290 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3294 dwError
= ScmSetServiceGroup(lpService
,
3297 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3299 if (dwError
!= ERROR_SUCCESS
)
3303 if (lpdwTagId
!= NULL
)
3305 dwError
= ScmAssignNewTag(lpService
);
3306 if (dwError
!= ERROR_SUCCESS
)
3309 dwError
= RegSetValueExW(hServiceKey
,
3313 (LPBYTE
)&lpService
->dwTag
,
3315 if (dwError
!= ERROR_SUCCESS
)
3318 *lpdwTagId
= lpService
->dwTag
;
3321 /* Write dependencies */
3322 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3324 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3326 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3327 if (lpDependenciesW
== NULL
)
3329 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3333 MultiByteToWideChar(CP_ACP
,
3338 strlen(lpDependencies
) + 1);
3340 dwError
= ScmWriteDependencies(hServiceKey
,
3341 (LPWSTR
)lpDependenciesW
,
3344 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3347 if (lpPassword
!= NULL
)
3349 /* FIXME: Write password */
3353 /* Unlock the service database */
3354 ScmUnlockDatabase();
3356 if (hServiceKey
!= NULL
)
3357 RegCloseKey(hServiceKey
);
3359 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3366 DWORD
RCreateServiceA(
3367 SC_RPC_HANDLE hSCManager
,
3368 LPSTR lpServiceName
,
3369 LPSTR lpDisplayName
,
3370 DWORD dwDesiredAccess
,
3371 DWORD dwServiceType
,
3373 DWORD dwErrorControl
,
3374 LPSTR lpBinaryPathName
,
3375 LPSTR lpLoadOrderGroup
,
3377 LPBYTE lpDependencies
,
3379 LPSTR lpServiceStartName
,
3382 LPSC_RPC_HANDLE lpServiceHandle
)
3384 DWORD dwError
= ERROR_SUCCESS
;
3385 LPWSTR lpServiceNameW
= NULL
;
3386 LPWSTR lpDisplayNameW
= NULL
;
3387 LPWSTR lpBinaryPathNameW
= NULL
;
3388 LPWSTR lpLoadOrderGroupW
= NULL
;
3389 LPWSTR lpDependenciesW
= NULL
;
3390 LPWSTR lpServiceStartNameW
= NULL
;
3391 DWORD dwDependenciesLength
= 0;
3398 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3399 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3400 if (!lpServiceNameW
)
3402 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3405 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3410 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3411 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3412 if (!lpDisplayNameW
)
3414 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3417 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3420 if (lpBinaryPathName
)
3422 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3423 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3424 if (!lpBinaryPathNameW
)
3426 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3429 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3432 if (lpLoadOrderGroup
)
3434 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3435 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3436 if (!lpLoadOrderGroupW
)
3438 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3441 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3446 lpStr
= (LPSTR
)lpDependencies
;
3449 dwLength
= strlen(lpStr
) + 1;
3450 dwDependenciesLength
+= dwLength
;
3451 lpStr
= lpStr
+ dwLength
;
3453 dwDependenciesLength
++;
3455 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3456 if (!lpDependenciesW
)
3458 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3461 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3464 if (lpServiceStartName
)
3466 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3467 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3468 if (!lpServiceStartNameW
)
3470 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3473 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3476 dwError
= RCreateServiceW(hSCManager
,
3486 (LPBYTE
)lpDependenciesW
,
3487 dwDependenciesLength
,
3488 lpServiceStartNameW
,
3494 if (lpServiceNameW
!=NULL
)
3495 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3497 if (lpDisplayNameW
!= NULL
)
3498 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3500 if (lpBinaryPathNameW
!= NULL
)
3501 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3503 if (lpLoadOrderGroupW
!= NULL
)
3504 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3506 if (lpDependenciesW
!= NULL
)
3507 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3509 if (lpServiceStartNameW
!= NULL
)
3510 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3517 DWORD
REnumDependentServicesA(
3518 SC_RPC_HANDLE hService
,
3519 DWORD dwServiceState
,
3522 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3523 LPBOUNDED_DWORD_256K lpServicesReturned
)
3525 DWORD dwError
= ERROR_SUCCESS
;
3526 DWORD dwServicesReturned
= 0;
3527 DWORD dwServiceCount
;
3528 HKEY hServicesKey
= NULL
;
3529 PSERVICE_HANDLE hSvc
;
3530 PSERVICE lpService
= NULL
;
3531 PSERVICE
*lpServicesArray
= NULL
;
3532 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3535 *pcbBytesNeeded
= 0;
3536 *lpServicesReturned
= 0;
3538 DPRINT("REnumDependentServicesA() called\n");
3540 hSvc
= ScmGetServiceFromHandle(hService
);
3543 DPRINT1("Invalid service handle!\n");
3544 return ERROR_INVALID_HANDLE
;
3547 lpService
= hSvc
->ServiceEntry
;
3549 /* Check access rights */
3550 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3551 SC_MANAGER_ENUMERATE_SERVICE
))
3553 DPRINT("Insufficient access rights! 0x%lx\n",
3554 hSvc
->Handle
.DesiredAccess
);
3555 return ERROR_ACCESS_DENIED
;
3558 /* Open the Services Reg key */
3559 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3560 L
"System\\CurrentControlSet\\Services",
3565 if (dwError
!= ERROR_SUCCESS
)
3568 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3569 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3570 are the same for both. Verified in WINXP. */
3572 /* First determine the bytes needed and get the number of dependent services*/
3573 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3578 &dwServicesReturned
);
3579 if (dwError
!= ERROR_SUCCESS
)
3582 /* If buffer size is less than the bytes needed or pointer is null*/
3583 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3585 dwError
= ERROR_MORE_DATA
;
3589 /* Allocate memory for array of service pointers */
3590 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3592 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3593 if (!lpServicesArray
)
3595 DPRINT("Could not allocate a buffer!!\n");
3596 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3600 dwServicesReturned
= 0;
3601 *pcbBytesNeeded
= 0;
3603 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3608 &dwServicesReturned
);
3609 if (dwError
!= ERROR_SUCCESS
)
3614 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3615 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3617 /* Copy EnumDepenedentService to Buffer */
3618 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3620 lpService
= lpServicesArray
[dwServiceCount
];
3622 /* Copy the status info */
3623 memcpy(&lpServicesPtr
->ServiceStatus
,
3625 sizeof(SERVICE_STATUS
));
3627 /* Copy display name */
3628 WideCharToMultiByte(CP_ACP
,
3630 lpService
->lpDisplayName
,
3633 wcslen(lpService
->lpDisplayName
),
3636 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3637 lpStr
+= strlen(lpStr
) + 1;
3639 /* Copy service name */
3640 WideCharToMultiByte(CP_ACP
,
3642 lpService
->lpServiceName
,
3645 wcslen(lpService
->lpServiceName
),
3648 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3649 lpStr
+= strlen(lpStr
) + 1;
3654 *lpServicesReturned
= dwServicesReturned
;
3657 if (lpServicesArray
)
3658 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3660 RegCloseKey(hServicesKey
);
3662 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3669 DWORD
REnumServicesStatusA(
3670 SC_RPC_HANDLE hSCManager
,
3671 DWORD dwServiceType
,
3672 DWORD dwServiceState
,
3675 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3676 LPBOUNDED_DWORD_256K lpServicesReturned
,
3677 LPBOUNDED_DWORD_256K lpResumeHandle
)
3679 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3680 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3681 LPWSTR lpStringPtrW
;
3684 DWORD dwServiceCount
;
3686 DPRINT("REnumServicesStatusA() called\n");
3688 if ((dwBufSize
> 0) && (lpBuffer
))
3690 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3693 DPRINT("Failed to allocate buffer!\n");
3694 return ERROR_NOT_ENOUGH_MEMORY
;
3698 dwError
= REnumServicesStatusW(hSCManager
,
3701 (LPBYTE
)lpStatusPtrW
,
3707 /* if no services were returned then we are Done */
3708 if (*lpServicesReturned
== 0)
3711 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3712 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3713 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3714 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3715 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3717 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3719 /* Copy the service name */
3720 WideCharToMultiByte(CP_ACP
,
3725 wcslen(lpStringPtrW
),
3729 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3730 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3731 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3733 /* Copy the display name */
3734 WideCharToMultiByte(CP_ACP
,
3739 wcslen(lpStringPtrW
),
3743 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3744 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3745 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3747 /* Copy the status information */
3748 memcpy(&lpStatusPtrA
->ServiceStatus
,
3749 &lpStatusPtrW
->ServiceStatus
,
3750 sizeof(SERVICE_STATUS
));
3757 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3759 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3766 DWORD
ROpenSCManagerA(
3767 LPSTR lpMachineName
,
3768 LPSTR lpDatabaseName
,
3769 DWORD dwDesiredAccess
,
3770 LPSC_RPC_HANDLE lpScHandle
)
3772 UNICODE_STRING MachineName
;
3773 UNICODE_STRING DatabaseName
;
3776 DPRINT("ROpenSCManagerA() called\n");
3779 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3783 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3786 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3787 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3792 RtlFreeUnicodeString(&MachineName
);
3795 RtlFreeUnicodeString(&DatabaseName
);
3802 DWORD
ROpenServiceA(
3803 SC_RPC_HANDLE hSCManager
,
3804 LPSTR lpServiceName
,
3805 DWORD dwDesiredAccess
,
3806 LPSC_RPC_HANDLE lpServiceHandle
)
3808 UNICODE_STRING ServiceName
;
3811 DPRINT("ROpenServiceA() called\n");
3814 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3817 dwError
= ROpenServiceW(hSCManager
,
3818 lpServiceName
? ServiceName
.Buffer
: NULL
,
3823 RtlFreeUnicodeString(&ServiceName
);
3830 DWORD
RQueryServiceConfigA(
3831 SC_RPC_HANDLE hService
,
3832 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3834 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3836 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3837 DWORD dwError
= ERROR_SUCCESS
;
3838 PSERVICE_HANDLE hSvc
;
3839 PSERVICE lpService
= NULL
;
3840 HKEY hServiceKey
= NULL
;
3841 LPWSTR lpImagePath
= NULL
;
3842 LPWSTR lpServiceStartName
= NULL
;
3843 LPWSTR lpDependencies
= NULL
;
3844 DWORD dwDependenciesLength
= 0;
3845 DWORD dwRequiredSize
;
3846 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3847 CHAR lpEmptyString
[]={0,0};
3850 DPRINT("RQueryServiceConfigA() called\n");
3853 return ERROR_SHUTDOWN_IN_PROGRESS
;
3855 hSvc
= ScmGetServiceFromHandle(hService
);
3858 DPRINT1("Invalid service handle!\n");
3859 return ERROR_INVALID_HANDLE
;
3862 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3863 SERVICE_QUERY_CONFIG
))
3865 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3866 return ERROR_ACCESS_DENIED
;
3869 lpService
= hSvc
->ServiceEntry
;
3870 if (lpService
== NULL
)
3872 DPRINT("lpService == NULL!\n");
3873 return ERROR_INVALID_HANDLE
;
3876 /* Lock the service database shared */
3877 ScmLockDatabaseShared();
3879 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3882 if (dwError
!= ERROR_SUCCESS
)
3885 /* Read the image path */
3886 dwError
= ScmReadString(hServiceKey
,
3889 if (dwError
!= ERROR_SUCCESS
)
3892 /* Read the service start name */
3893 ScmReadString(hServiceKey
,
3895 &lpServiceStartName
);
3897 /* Read the dependencies */
3898 ScmReadDependencies(hServiceKey
,
3900 &dwDependenciesLength
);
3902 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3904 if (lpImagePath
!= NULL
)
3905 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3907 dwRequiredSize
+= 2;
3909 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3910 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3912 dwRequiredSize
+= 2;
3914 /* Add Dependencies length */
3915 if (lpDependencies
!= NULL
)
3916 dwRequiredSize
+= dwDependenciesLength
;
3918 dwRequiredSize
+= 2;
3920 if (lpServiceStartName
!= NULL
)
3921 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3923 dwRequiredSize
+= 2;
3925 if (lpService
->lpDisplayName
!= NULL
)
3926 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3928 dwRequiredSize
+= 2;
3930 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3932 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3936 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3937 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3938 lpConfig
->dwStartType
= lpService
->dwStartType
;
3939 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3940 lpConfig
->dwTagId
= lpService
->dwTag
;
3942 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3944 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3949 WideCharToMultiByte(CP_ACP
,
3954 wcslen(lpImagePath
) + 1,
3960 strcpy(lpStr
, lpEmptyString
);
3963 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3964 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3966 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
3968 WideCharToMultiByte(CP_ACP
,
3970 lpService
->lpGroup
->lpGroupName
,
3973 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
3979 strcpy(lpStr
, lpEmptyString
);
3982 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3983 lpStr
+= (strlen(lpStr
) + 1);
3985 /* Append Dependencies */
3988 WideCharToMultiByte(CP_ACP
,
3991 dwDependenciesLength
,
3993 dwDependenciesLength
,
3999 strcpy(lpStr
, lpEmptyString
);
4002 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4004 lpStr
+= dwDependenciesLength
;
4006 lpStr
+= (strlen(lpStr
) + 1);
4008 if (lpServiceStartName
)
4010 WideCharToMultiByte(CP_ACP
,
4015 wcslen(lpServiceStartName
) + 1,
4021 strcpy(lpStr
, lpEmptyString
);
4024 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4025 lpStr
+= (strlen(lpStr
) + 1);
4027 if (lpService
->lpDisplayName
)
4029 WideCharToMultiByte(CP_ACP
,
4031 lpService
->lpDisplayName
,
4034 wcslen(lpService
->lpDisplayName
) + 1,
4040 strcpy(lpStr
, lpEmptyString
);
4043 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4046 if (pcbBytesNeeded
!= NULL
)
4047 *pcbBytesNeeded
= dwRequiredSize
;
4050 /* Unlock the service database */
4051 ScmUnlockDatabase();
4053 if (lpImagePath
!= NULL
)
4054 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4056 if (lpServiceStartName
!= NULL
)
4057 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4059 if (lpDependencies
!= NULL
)
4060 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4062 if (hServiceKey
!= NULL
)
4063 RegCloseKey(hServiceKey
);
4065 DPRINT("RQueryServiceConfigA() done\n");
4072 DWORD
RQueryServiceLockStatusA(
4073 SC_RPC_HANDLE hSCManager
,
4074 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
4076 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4079 return ERROR_CALL_NOT_IMPLEMENTED
;
4084 DWORD
RStartServiceA(
4085 SC_RPC_HANDLE hService
,
4087 LPSTRING_PTRSA argv
)
4089 DWORD dwError
= ERROR_SUCCESS
;
4090 PSERVICE_HANDLE hSvc
;
4091 PSERVICE lpService
= NULL
;
4092 LPWSTR
*lpVector
= NULL
;
4096 DPRINT("RStartServiceA() called\n");
4099 return ERROR_SHUTDOWN_IN_PROGRESS
;
4101 hSvc
= ScmGetServiceFromHandle(hService
);
4104 DPRINT1("Invalid service handle!\n");
4105 return ERROR_INVALID_HANDLE
;
4108 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4111 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4112 return ERROR_ACCESS_DENIED
;
4115 lpService
= hSvc
->ServiceEntry
;
4116 if (lpService
== NULL
)
4118 DPRINT("lpService == NULL!\n");
4119 return ERROR_INVALID_HANDLE
;
4122 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4123 return ERROR_SERVICE_DISABLED
;
4125 if (lpService
->bDeleted
)
4126 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4128 /* Build a Unicode argument vector */
4131 lpVector
= HeapAlloc(GetProcessHeap(),
4133 argc
* sizeof(LPWSTR
));
4134 if (lpVector
== NULL
)
4135 return ERROR_NOT_ENOUGH_MEMORY
;
4137 for (i
= 0; i
< argc
; i
++)
4139 dwLength
= MultiByteToWideChar(CP_ACP
,
4146 lpVector
[i
] = HeapAlloc(GetProcessHeap(),
4148 dwLength
* sizeof(WCHAR
));
4149 if (lpVector
[i
] == NULL
)
4151 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
4155 MultiByteToWideChar(CP_ACP
,
4164 /* Start the service */
4165 dwError
= ScmStartService(lpService
, argc
, lpVector
);
4168 /* Free the Unicode argument vector */
4169 if (lpVector
!= NULL
)
4171 for (i
= 0; i
< argc
; i
++)
4173 if (lpVector
[i
] != NULL
)
4174 HeapFree(GetProcessHeap(), 0, lpVector
[i
]);
4176 HeapFree(GetProcessHeap(), 0, lpVector
);
4184 DWORD
RGetServiceDisplayNameA(
4185 SC_RPC_HANDLE hSCManager
,
4186 LPCSTR lpServiceName
,
4187 LPSTR lpDisplayName
,
4188 LPBOUNDED_DWORD_4K lpcchBuffer
)
4190 // PMANAGER_HANDLE hManager;
4191 PSERVICE lpService
= NULL
;
4194 LPWSTR lpServiceNameW
;
4196 DPRINT("RGetServiceDisplayNameA() called\n");
4197 DPRINT("hSCManager = %p\n", hSCManager
);
4198 DPRINT("lpServiceName: %s\n", lpServiceName
);
4199 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4200 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4202 // hManager = (PMANAGER_HANDLE)hSCManager;
4203 // if (hManager->Handle.Tag != MANAGER_TAG)
4205 // DPRINT("Invalid manager handle!\n");
4206 // return ERROR_INVALID_HANDLE;
4209 if (lpServiceName
!= NULL
)
4211 dwLength
= strlen(lpServiceName
) + 1;
4212 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4214 dwLength
* sizeof(WCHAR
));
4215 if (!lpServiceNameW
)
4216 return ERROR_NOT_ENOUGH_MEMORY
;
4218 MultiByteToWideChar(CP_ACP
,
4225 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4227 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4230 if (lpService
== NULL
)
4232 DPRINT("Could not find a service!\n");
4234 /* If the service could not be found and lpcchBuffer is 0, windows
4235 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4236 if (*lpcchBuffer
== 0)
4239 if (lpDisplayName
!= NULL
)
4241 *lpDisplayName
= '\0';
4244 return ERROR_SERVICE_DOES_NOT_EXIST
;
4247 if (!lpService
->lpDisplayName
)
4249 dwLength
= wcslen(lpService
->lpServiceName
);
4250 if (lpDisplayName
!= NULL
&&
4251 *lpcchBuffer
> dwLength
)
4253 WideCharToMultiByte(CP_ACP
,
4255 lpService
->lpServiceName
,
4256 wcslen(lpService
->lpServiceName
),
4261 return ERROR_SUCCESS
;
4266 dwLength
= wcslen(lpService
->lpDisplayName
);
4267 if (lpDisplayName
!= NULL
&&
4268 *lpcchBuffer
> dwLength
)
4270 WideCharToMultiByte(CP_ACP
,
4272 lpService
->lpDisplayName
,
4273 wcslen(lpService
->lpDisplayName
),
4278 return ERROR_SUCCESS
;
4282 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4284 *lpcchBuffer
= dwLength
* 2;
4291 DWORD
RGetServiceKeyNameA(
4292 SC_RPC_HANDLE hSCManager
,
4293 LPCSTR lpDisplayName
,
4294 LPSTR lpServiceName
,
4295 LPBOUNDED_DWORD_4K lpcchBuffer
)
4300 LPWSTR lpDisplayNameW
;
4302 DPRINT("RGetServiceKeyNameA() called\n");
4303 DPRINT("hSCManager = %p\n", hSCManager
);
4304 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4305 DPRINT("lpServiceName: %p\n", lpServiceName
);
4306 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4308 dwLength
= strlen(lpDisplayName
) + 1;
4309 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4311 dwLength
* sizeof(WCHAR
));
4312 if (!lpDisplayNameW
)
4313 return ERROR_NOT_ENOUGH_MEMORY
;
4315 MultiByteToWideChar(CP_ACP
,
4322 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4324 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4326 if (lpService
== NULL
)
4328 DPRINT("Could not find the service!\n");
4330 /* If the service could not be found and lpcchBuffer is 0,
4331 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4332 if (*lpcchBuffer
== 0)
4335 if (lpServiceName
!= NULL
)
4337 *lpServiceName
= '\0';
4341 return ERROR_SERVICE_DOES_NOT_EXIST
;
4344 dwLength
= wcslen(lpService
->lpServiceName
);
4345 if (lpServiceName
!= NULL
&&
4346 *lpcchBuffer
> dwLength
)
4348 WideCharToMultiByte(CP_ACP
,
4350 lpService
->lpServiceName
,
4351 wcslen(lpService
->lpServiceName
),
4356 return ERROR_SUCCESS
;
4359 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4361 *lpcchBuffer
= dwLength
* 2;
4368 DWORD
RI_ScGetCurrentGroupStateW(
4369 SC_RPC_HANDLE hSCManager
,
4370 LPWSTR lpLoadOrderGroup
,
4374 return ERROR_CALL_NOT_IMPLEMENTED
;
4379 DWORD
REnumServiceGroupW(
4380 SC_RPC_HANDLE hSCManager
,
4381 DWORD dwServiceType
,
4382 DWORD dwServiceState
,
4385 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4386 LPBOUNDED_DWORD_256K lpServicesReturned
,
4387 LPBOUNDED_DWORD_256K lpResumeIndex
,
4388 LPCWSTR pszGroupName
)
4391 return ERROR_CALL_NOT_IMPLEMENTED
;
4396 // WARNING: This function is untested
4399 DWORD
RChangeServiceConfig2A(
4400 SC_RPC_HANDLE hService
,
4401 SC_RPC_CONFIG_INFOA Info
)
4403 SC_RPC_CONFIG_INFOW InfoW
;
4404 DWORD dwRet
, dwLength
;
4407 DPRINT("RChangeServiceConfig2A() called\n");
4408 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4410 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4412 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4414 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4415 //LPSERVICE_DESCRIPTIONA lpServiceDescriptonA;
4417 //lpServiceDescriptonA = Info.psd;
4419 ///if (lpServiceDescriptonA &&
4420 ///lpServiceDescriptonA->lpDescription)
4422 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4424 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4426 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4427 if (!lpServiceDescriptonW
)
4429 return ERROR_NOT_ENOUGH_MEMORY
;
4432 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4434 MultiByteToWideChar(CP_ACP
,
4438 lpServiceDescriptonW
->lpDescription
,
4441 ptr
= lpServiceDescriptonW
;
4442 InfoW
.psd
= lpServiceDescriptonW
;
4445 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4447 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4448 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4449 DWORD dwRebootLen
= 0;
4450 DWORD dwCommandLen
= 0;
4452 lpServiceFailureActionsA
= Info
.psfa
;
4454 if (lpServiceFailureActionsA
)
4456 if (lpServiceFailureActionsA
->lpRebootMsg
)
4458 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4460 if (lpServiceFailureActionsA
->lpCommand
)
4462 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4464 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4466 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4469 if (!lpServiceFailureActionsW
)
4471 return ERROR_NOT_ENOUGH_MEMORY
;
4474 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4475 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4476 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4478 if (lpServiceFailureActionsA
->lpRebootMsg
)
4480 MultiByteToWideChar(CP_ACP
,
4482 lpServiceFailureActionsA
->lpRebootMsg
,
4484 lpServiceFailureActionsW
->lpRebootMsg
,
4488 if (lpServiceFailureActionsA
->lpCommand
)
4490 MultiByteToWideChar(CP_ACP
,
4492 lpServiceFailureActionsA
->lpCommand
,
4494 lpServiceFailureActionsW
->lpCommand
,
4498 ptr
= lpServiceFailureActionsW
;
4502 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4504 HeapFree(GetProcessHeap(), 0, ptr
);
4511 DWORD
RChangeServiceConfig2W(
4512 SC_RPC_HANDLE hService
,
4513 SC_RPC_CONFIG_INFOW Info
)
4515 DWORD dwError
= ERROR_SUCCESS
;
4516 PSERVICE_HANDLE hSvc
;
4517 PSERVICE lpService
= NULL
;
4518 HKEY hServiceKey
= NULL
;
4520 DPRINT("RChangeServiceConfig2W() called\n");
4521 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4524 return ERROR_SHUTDOWN_IN_PROGRESS
;
4526 hSvc
= ScmGetServiceFromHandle(hService
);
4529 DPRINT1("Invalid service handle!\n");
4530 return ERROR_INVALID_HANDLE
;
4533 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4534 SERVICE_CHANGE_CONFIG
))
4536 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4537 return ERROR_ACCESS_DENIED
;
4540 lpService
= hSvc
->ServiceEntry
;
4541 if (lpService
== NULL
)
4543 DPRINT("lpService == NULL!\n");
4544 return ERROR_INVALID_HANDLE
;
4547 /* Lock the service database exclusively */
4548 ScmLockDatabaseExclusive();
4550 if (lpService
->bDeleted
)
4552 DPRINT("The service has already been marked for delete!\n");
4553 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
4557 /* Open the service key */
4558 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4561 if (dwError
!= ERROR_SUCCESS
)
4564 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4566 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4568 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4569 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4571 if (lpServiceDescription
!= NULL
&&
4572 lpServiceDescription
->lpDescription
!= NULL
)
4574 DPRINT("Setting value %S\n", lpServiceDescription
->lpDescription
);
4575 dwError
= RegSetValueExW(hServiceKey
,
4579 (LPBYTE
)lpServiceDescription
->lpDescription
,
4580 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4581 if (dwError
!= ERROR_SUCCESS
)
4585 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4588 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4593 /* Unlock the service database */
4594 ScmUnlockDatabase();
4596 if (hServiceKey
!= NULL
)
4597 RegCloseKey(hServiceKey
);
4599 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4606 DWORD
RQueryServiceConfig2A(
4607 SC_RPC_HANDLE hService
,
4611 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4613 DWORD dwError
= ERROR_SUCCESS
;
4614 PSERVICE_HANDLE hSvc
;
4615 PSERVICE lpService
= NULL
;
4616 HKEY hServiceKey
= NULL
;
4617 LPWSTR lpDescriptionW
= NULL
;
4618 LPSTR lpDescription
= NULL
;
4620 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4621 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4624 return ERROR_INVALID_ADDRESS
;
4627 return ERROR_SHUTDOWN_IN_PROGRESS
;
4629 hSvc
= ScmGetServiceFromHandle(hService
);
4632 DPRINT1("Invalid service handle!\n");
4633 return ERROR_INVALID_HANDLE
;
4636 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4637 SERVICE_QUERY_CONFIG
))
4639 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4640 return ERROR_ACCESS_DENIED
;
4643 lpService
= hSvc
->ServiceEntry
;
4644 if (lpService
== NULL
)
4646 DPRINT("lpService == NULL!\n");
4647 return ERROR_INVALID_HANDLE
;
4650 /* Lock the service database shared */
4651 ScmLockDatabaseShared();
4653 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4656 if (dwError
!= ERROR_SUCCESS
)
4659 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4661 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4664 dwError
= ScmReadString(hServiceKey
,
4667 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4670 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4671 if (dwError
== ERROR_SUCCESS
)
4672 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4674 if (cbBufSize
< *pcbBytesNeeded
)
4676 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4680 if (dwError
== ERROR_SUCCESS
)
4682 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4684 WideCharToMultiByte(CP_ACP
,
4689 wcslen(lpDescriptionW
),
4692 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4696 lpServiceDescription
->lpDescription
= NULL
;
4697 dwError
= ERROR_SUCCESS
;
4701 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4704 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4709 /* Unlock the service database */
4710 ScmUnlockDatabase();
4712 if (lpDescription
!= NULL
)
4713 HeapFree(GetProcessHeap(), 0, lpDescription
);
4715 if (hServiceKey
!= NULL
)
4716 RegCloseKey(hServiceKey
);
4718 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4725 DWORD
RQueryServiceConfig2W(
4726 SC_RPC_HANDLE hService
,
4730 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4732 DWORD dwError
= ERROR_SUCCESS
;
4733 PSERVICE_HANDLE hSvc
;
4734 PSERVICE lpService
= NULL
;
4735 HKEY hServiceKey
= NULL
;
4736 DWORD dwRequiredSize
;
4737 LPWSTR lpDescription
= NULL
;
4738 LPWSTR lpFailureCommand
= NULL
;
4739 LPWSTR lpRebootMessage
= NULL
;
4741 DPRINT("RQueryServiceConfig2W() called\n");
4744 return ERROR_INVALID_ADDRESS
;
4747 return ERROR_SHUTDOWN_IN_PROGRESS
;
4749 hSvc
= ScmGetServiceFromHandle(hService
);
4752 DPRINT1("Invalid service handle!\n");
4753 return ERROR_INVALID_HANDLE
;
4756 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4757 SERVICE_QUERY_CONFIG
))
4759 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4760 return ERROR_ACCESS_DENIED
;
4763 lpService
= hSvc
->ServiceEntry
;
4764 if (lpService
== NULL
)
4766 DPRINT("lpService == NULL!\n");
4767 return ERROR_INVALID_HANDLE
;
4770 /* Lock the service database shared */
4771 ScmLockDatabaseShared();
4773 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4776 if (dwError
!= ERROR_SUCCESS
)
4779 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4781 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4784 dwError
= ScmReadString(hServiceKey
,
4787 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4790 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONW
);
4791 if (dwError
== ERROR_SUCCESS
)
4792 *pcbBytesNeeded
+= ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4794 if (cbBufSize
< *pcbBytesNeeded
)
4796 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4800 if (dwError
== ERROR_SUCCESS
)
4802 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4803 wcscpy(lpStr
, lpDescription
);
4804 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4808 lpServiceDescription
->lpDescription
= NULL
;
4809 dwError
= ERROR_SUCCESS
;
4812 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4815 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
4819 dwError
= ScmReadString(hServiceKey
,
4823 dwError
= ScmReadString(hServiceKey
,
4827 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
4829 if (lpFailureCommand
)
4830 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
4832 if (lpRebootMessage
)
4833 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
4835 if (cbBufSize
< dwRequiredSize
)
4837 *pcbBytesNeeded
= dwRequiredSize
;
4838 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4842 lpFailureActions
->cActions
= 0;
4843 lpFailureActions
->dwResetPeriod
= 0;
4844 lpFailureActions
->lpCommand
= NULL
;
4845 lpFailureActions
->lpRebootMsg
= NULL
;
4846 lpFailureActions
->lpsaActions
= NULL
;
4848 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
4849 if (lpRebootMessage
)
4851 wcscpy(lpStr
, lpRebootMessage
);
4852 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
4853 lpStr
+= wcslen(lpRebootMessage
) + 1;
4856 if (lpFailureCommand
)
4858 wcscpy(lpStr
, lpFailureCommand
);
4859 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
4860 lpStr
+= wcslen(lpRebootMessage
) + 1;
4862 dwError
= STATUS_SUCCESS
;
4867 /* Unlock the service database */
4868 ScmUnlockDatabase();
4870 if (lpDescription
!= NULL
)
4871 HeapFree(GetProcessHeap(), 0, lpDescription
);
4873 if (lpRebootMessage
!= NULL
)
4874 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
4876 if (lpFailureCommand
!= NULL
)
4877 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
4879 if (hServiceKey
!= NULL
)
4880 RegCloseKey(hServiceKey
);
4882 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4889 DWORD
RQueryServiceStatusEx(
4890 SC_RPC_HANDLE hService
,
4891 SC_STATUS_TYPE InfoLevel
,
4894 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4896 LPSERVICE_STATUS_PROCESS lpStatus
;
4897 PSERVICE_HANDLE hSvc
;
4900 DPRINT("RQueryServiceStatusEx() called\n");
4903 return ERROR_SHUTDOWN_IN_PROGRESS
;
4905 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4906 return ERROR_INVALID_LEVEL
;
4908 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4910 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4911 return ERROR_INSUFFICIENT_BUFFER
;
4913 hSvc
= ScmGetServiceFromHandle(hService
);
4916 DPRINT1("Invalid service handle!\n");
4917 return ERROR_INVALID_HANDLE
;
4920 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4921 SERVICE_QUERY_STATUS
))
4923 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4924 return ERROR_ACCESS_DENIED
;
4927 lpService
= hSvc
->ServiceEntry
;
4928 if (lpService
== NULL
)
4930 DPRINT("lpService == NULL!\n");
4931 return ERROR_INVALID_HANDLE
;
4934 /* Lock the service database shared */
4935 ScmLockDatabaseShared();
4937 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4939 /* Return service status information */
4940 RtlCopyMemory(lpStatus
,
4942 sizeof(SERVICE_STATUS
));
4944 lpStatus
->dwProcessId
= (lpService
->lpImage
!= NULL
) ? lpService
->lpImage
->dwProcessId
: 0; /* FIXME */
4945 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4947 /* Unlock the service database */
4948 ScmUnlockDatabase();
4950 return ERROR_SUCCESS
;
4955 DWORD
REnumServicesStatusExA(
4956 SC_RPC_HANDLE hSCManager
,
4957 SC_ENUM_TYPE InfoLevel
,
4958 DWORD dwServiceType
,
4959 DWORD dwServiceState
,
4962 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4963 LPBOUNDED_DWORD_256K lpServicesReturned
,
4964 LPBOUNDED_DWORD_256K lpResumeIndex
,
4965 LPCSTR pszGroupName
)
4967 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
4968 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
4969 LPWSTR lpStringPtrW
;
4971 LPWSTR pszGroupNameW
= NULL
;
4973 DWORD dwServiceCount
;
4975 DPRINT("REnumServicesStatusExA() called\n");
4979 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
4982 DPRINT("Failed to allocate buffer!\n");
4983 return ERROR_NOT_ENOUGH_MEMORY
;
4986 MultiByteToWideChar(CP_ACP
,
4991 strlen(pszGroupName
) + 1);
4994 if ((cbBufSize
> 0) && (lpBuffer
))
4996 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
4999 DPRINT("Failed to allocate buffer!\n");
5000 return ERROR_NOT_ENOUGH_MEMORY
;
5004 dwError
= REnumServicesStatusExW(hSCManager
,
5008 (LPBYTE
)lpStatusPtrW
,
5015 /* if no services were returned then we are Done */
5016 if (*lpServicesReturned
== 0)
5019 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
5020 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
5021 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
5022 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
5023 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5025 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
5027 /* Copy the service name */
5028 WideCharToMultiByte(CP_ACP
,
5033 wcslen(lpStringPtrW
),
5037 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5038 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5039 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5041 /* Copy the display name */
5042 WideCharToMultiByte(CP_ACP
,
5047 wcslen(lpStringPtrW
),
5051 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
5052 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5053 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5055 /* Copy the status information */
5056 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
5057 &lpStatusPtrW
->ServiceStatusProcess
,
5058 sizeof(SERVICE_STATUS
));
5060 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
5061 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5067 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
5070 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
5072 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
5079 DWORD
REnumServicesStatusExW(
5080 SC_RPC_HANDLE hSCManager
,
5081 SC_ENUM_TYPE InfoLevel
,
5082 DWORD dwServiceType
,
5083 DWORD dwServiceState
,
5086 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5087 LPBOUNDED_DWORD_256K lpServicesReturned
,
5088 LPBOUNDED_DWORD_256K lpResumeIndex
,
5089 LPCWSTR pszGroupName
)
5091 PMANAGER_HANDLE hManager
;
5093 DWORD dwError
= ERROR_SUCCESS
;
5094 PLIST_ENTRY ServiceEntry
;
5095 PSERVICE CurrentService
;
5097 DWORD dwRequiredSize
;
5098 DWORD dwServiceCount
;
5100 DWORD dwLastResumeCount
= 0;
5101 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
5104 DPRINT("REnumServicesStatusExW() called\n");
5107 return ERROR_SHUTDOWN_IN_PROGRESS
;
5109 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
5110 return ERROR_INVALID_LEVEL
;
5112 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
5113 if (hManager
== NULL
)
5115 DPRINT1("Invalid service manager handle!\n");
5116 return ERROR_INVALID_HANDLE
;
5119 *pcbBytesNeeded
= 0;
5120 *lpServicesReturned
= 0;
5122 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
5124 DPRINT("Not a valid Service Type!\n");
5125 return ERROR_INVALID_PARAMETER
;
5128 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
5130 DPRINT("Not a valid Service State!\n");
5131 return ERROR_INVALID_PARAMETER
;
5134 /* Check access rights */
5135 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
5136 SC_MANAGER_ENUMERATE_SERVICE
))
5138 DPRINT("Insufficient access rights! 0x%lx\n",
5139 hManager
->Handle
.DesiredAccess
);
5140 return ERROR_ACCESS_DENIED
;
5144 dwLastResumeCount
= *lpResumeIndex
;
5146 /* Lock the service database shared */
5147 ScmLockDatabaseShared();
5149 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
5150 if (lpService
== NULL
)
5152 dwError
= ERROR_SUCCESS
;
5159 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5160 ServiceEntry
!= &ServiceListHead
;
5161 ServiceEntry
= ServiceEntry
->Flink
)
5163 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5167 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5170 dwState
= SERVICE_ACTIVE
;
5171 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5172 dwState
= SERVICE_INACTIVE
;
5174 if ((dwState
& dwServiceState
) == 0)
5179 if (*pszGroupName
== 0)
5181 if (CurrentService
->lpGroup
!= NULL
)
5186 if ((CurrentService
->lpGroup
== NULL
) ||
5187 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5192 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5193 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5194 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5196 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5198 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5199 dwRequiredSize
+= dwSize
;
5201 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5205 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5211 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5212 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5215 ServiceEntry
!= &ServiceListHead
;
5216 ServiceEntry
= ServiceEntry
->Flink
)
5218 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5222 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5225 dwState
= SERVICE_ACTIVE
;
5226 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5227 dwState
= SERVICE_INACTIVE
;
5229 if ((dwState
& dwServiceState
) == 0)
5234 if (*pszGroupName
== 0)
5236 if (CurrentService
->lpGroup
!= NULL
)
5241 if ((CurrentService
->lpGroup
== NULL
) ||
5242 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5247 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5248 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5249 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5251 dwError
= ERROR_MORE_DATA
;
5254 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5257 *lpResumeIndex
= dwLastResumeCount
;
5259 *lpServicesReturned
= dwServiceCount
;
5260 *pcbBytesNeeded
= dwRequiredSize
;
5262 /* If there was no services that matched */
5263 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5265 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5269 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5270 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5271 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5274 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5275 ServiceEntry
!= &ServiceListHead
;
5276 ServiceEntry
= ServiceEntry
->Flink
)
5278 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5282 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5285 dwState
= SERVICE_ACTIVE
;
5286 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5287 dwState
= SERVICE_INACTIVE
;
5289 if ((dwState
& dwServiceState
) == 0)
5294 if (*pszGroupName
== 0)
5296 if (CurrentService
->lpGroup
!= NULL
)
5301 if ((CurrentService
->lpGroup
== NULL
) ||
5302 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5307 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5308 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5309 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5311 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5313 /* Copy the service name */
5315 CurrentService
->lpServiceName
);
5316 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5317 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5319 /* Copy the display name */
5321 CurrentService
->lpDisplayName
);
5322 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5323 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5325 /* Copy the status information */
5326 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5327 &CurrentService
->Status
,
5328 sizeof(SERVICE_STATUS
));
5329 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
=
5330 (CurrentService
->lpImage
!= NULL
) ? CurrentService
->lpImage
->dwProcessId
: 0; /* FIXME */
5331 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5334 dwRequiredSize
+= dwSize
;
5344 *pcbBytesNeeded
= 0;
5350 /* Unlock the service database */
5351 ScmUnlockDatabase();
5353 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5360 DWORD
RSendTSMessage(
5361 handle_t BindingHandle
) /* FIXME */
5364 return ERROR_CALL_NOT_IMPLEMENTED
;
5369 DWORD
RCreateServiceWOW64A(
5370 handle_t BindingHandle
,
5371 LPSTR lpServiceName
,
5372 LPSTR lpDisplayName
,
5373 DWORD dwDesiredAccess
,
5374 DWORD dwServiceType
,
5376 DWORD dwErrorControl
,
5377 LPSTR lpBinaryPathName
,
5378 LPSTR lpLoadOrderGroup
,
5380 LPBYTE lpDependencies
,
5382 LPSTR lpServiceStartName
,
5385 LPSC_RPC_HANDLE lpServiceHandle
)
5388 return ERROR_CALL_NOT_IMPLEMENTED
;
5393 DWORD
RCreateServiceWOW64W(
5394 handle_t BindingHandle
,
5395 LPWSTR lpServiceName
,
5396 LPWSTR lpDisplayName
,
5397 DWORD dwDesiredAccess
,
5398 DWORD dwServiceType
,
5400 DWORD dwErrorControl
,
5401 LPWSTR lpBinaryPathName
,
5402 LPWSTR lpLoadOrderGroup
,
5404 LPBYTE lpDependencies
,
5406 LPWSTR lpServiceStartName
,
5409 LPSC_RPC_HANDLE lpServiceHandle
)
5412 return ERROR_CALL_NOT_IMPLEMENTED
;
5417 DWORD
RQueryServiceTagInfo(
5418 handle_t BindingHandle
) /* FIXME */
5421 return ERROR_CALL_NOT_IMPLEMENTED
;
5426 DWORD
RNotifyServiceStatusChange(
5427 SC_RPC_HANDLE hService
,
5428 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5429 GUID
*pClientProcessGuid
,
5430 GUID
*pSCMProcessGuid
,
5431 PBOOL pfCreateRemoteQueue
,
5432 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5435 return ERROR_CALL_NOT_IMPLEMENTED
;
5440 DWORD
RGetNotifyResults(
5441 SC_NOTIFY_RPC_HANDLE hNotify
,
5442 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5445 return ERROR_CALL_NOT_IMPLEMENTED
;
5450 DWORD
RCloseNotifyHandle(
5451 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5455 return ERROR_CALL_NOT_IMPLEMENTED
;
5460 DWORD
RControlServiceExA(
5461 SC_RPC_HANDLE hService
,
5466 return ERROR_CALL_NOT_IMPLEMENTED
;
5471 DWORD
RControlServiceExW(
5472 SC_RPC_HANDLE hService
,
5477 return ERROR_CALL_NOT_IMPLEMENTED
;
5482 DWORD
RSendPnPMessage(
5483 handle_t BindingHandle
) /* FIXME */
5486 return ERROR_CALL_NOT_IMPLEMENTED
;
5491 DWORD
RValidatePnPService(
5492 handle_t BindingHandle
) /* FIXME */
5495 return ERROR_CALL_NOT_IMPLEMENTED
;
5500 DWORD
ROpenServiceStatusHandle(
5501 handle_t BindingHandle
) /* FIXME */
5504 return ERROR_CALL_NOT_IMPLEMENTED
;
5510 handle_t BindingHandle
) /* FIXME */
5513 return ERROR_CALL_NOT_IMPLEMENTED
;
5517 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5519 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5523 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5525 HeapFree(GetProcessHeap(), 0, ptr
);
5529 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5534 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5539 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)