2 * PROJECT: ReactOS Service Control Manager
3 * LICENSE: GPL - See COPYING in the top level directory
4 * FILE: base/system/services/rpcserver.c
5 * PURPOSE: RPC server interface for the advapi32 calls
6 * COPYRIGHT: Copyright 2005-2006 Eric Kohl
7 * Copyright 2006-2007 Hervé Poussineau <hpoussin@reactos.org>
8 * Copyright 2007 Ged Murphy <gedmurphy@reactos.org>
11 /* INCLUDES ****************************************************************/
19 /* GLOBALS *****************************************************************/
21 #define MANAGER_TAG 0x72674D68 /* 'hMgr' */
22 #define SERVICE_TAG 0x63765368 /* 'hSvc' */
24 typedef struct _SCMGR_HANDLE
31 typedef struct _MANAGER_HANDLE
34 WCHAR DatabaseName
[1];
35 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
38 typedef struct _SERVICE_HANDLE
41 PSERVICE ServiceEntry
;
42 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
45 #define SC_MANAGER_READ \
46 (STANDARD_RIGHTS_READ | \
47 SC_MANAGER_QUERY_LOCK_STATUS | \
48 SC_MANAGER_ENUMERATE_SERVICE)
50 #define SC_MANAGER_WRITE \
51 (STANDARD_RIGHTS_WRITE | \
52 SC_MANAGER_MODIFY_BOOT_CONFIG | \
53 SC_MANAGER_CREATE_SERVICE)
55 #define SC_MANAGER_EXECUTE \
56 (STANDARD_RIGHTS_EXECUTE | \
58 SC_MANAGER_ENUMERATE_SERVICE | \
59 SC_MANAGER_CONNECT | \
60 SC_MANAGER_CREATE_SERVICE)
63 #define SERVICE_READ \
64 (STANDARD_RIGHTS_READ | \
65 SERVICE_INTERROGATE | \
66 SERVICE_ENUMERATE_DEPENDENTS | \
67 SERVICE_QUERY_STATUS | \
70 #define SERVICE_WRITE \
71 (STANDARD_RIGHTS_WRITE | \
72 SERVICE_CHANGE_CONFIG)
74 #define SERVICE_EXECUTE \
75 (STANDARD_RIGHTS_EXECUTE | \
76 SERVICE_USER_DEFINED_CONTROL | \
77 SERVICE_PAUSE_CONTINUE | \
82 /* VARIABLES ***************************************************************/
84 static GENERIC_MAPPING
85 ScmManagerMapping
= {SC_MANAGER_READ
,
88 SC_MANAGER_ALL_ACCESS
};
90 static GENERIC_MAPPING
91 ScmServiceMapping
= {SERVICE_READ
,
94 SC_MANAGER_ALL_ACCESS
};
97 /* FUNCTIONS ***************************************************************/
100 ScmStartRpcServer(VOID
)
104 DPRINT("ScmStartRpcServer() called\n");
106 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
110 if (Status
!= RPC_S_OK
)
112 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
116 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
119 if (Status
!= RPC_S_OK
)
121 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
125 Status
= RpcServerListen(1, 20, TRUE
);
126 if (Status
!= RPC_S_OK
)
128 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
132 DPRINT("ScmStartRpcServer() done\n");
137 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
142 if (lpDatabaseName
== NULL
)
143 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
145 if (_wcsicmp(lpDatabaseName
, SERVICES_FAILED_DATABASEW
) == 0)
147 DPRINT("Database %S, does not exist\n",lpDatabaseName
);
148 return ERROR_DATABASE_DOES_NOT_EXIST
;
150 else if (_wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
152 DPRINT("Invalid Database name %S.\n",lpDatabaseName
);
153 return ERROR_INVALID_NAME
;
156 Ptr
= (MANAGER_HANDLE
*) HeapAlloc(GetProcessHeap(),
158 sizeof(MANAGER_HANDLE
) + (wcslen(lpDatabaseName
) + 1) * sizeof(WCHAR
));
160 return ERROR_NOT_ENOUGH_MEMORY
;
162 Ptr
->Handle
.Tag
= MANAGER_TAG
;
164 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
166 *Handle
= (SC_HANDLE
)Ptr
;
168 return ERROR_SUCCESS
;
173 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
178 Ptr
= (SERVICE_HANDLE
*) HeapAlloc(GetProcessHeap(),
180 sizeof(SERVICE_HANDLE
));
182 return ERROR_NOT_ENOUGH_MEMORY
;
184 Ptr
->Handle
.Tag
= SERVICE_TAG
;
186 Ptr
->ServiceEntry
= lpServiceEntry
;
188 *Handle
= (SC_HANDLE
)Ptr
;
190 return ERROR_SUCCESS
;
194 static PMANAGER_HANDLE
195 ScmGetServiceManagerFromHandle(SC_RPC_HANDLE Handle
)
197 PMANAGER_HANDLE pManager
= NULL
;
201 if (((PMANAGER_HANDLE
)Handle
)->Handle
.Tag
== MANAGER_TAG
)
202 pManager
= (PMANAGER_HANDLE
)Handle
;
204 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
206 DPRINT1("Exception: Invalid Service Manager handle!\n");
214 static PSERVICE_HANDLE
215 ScmGetServiceFromHandle(SC_RPC_HANDLE Handle
)
217 PSERVICE_HANDLE pService
= NULL
;
221 if (((PSERVICE_HANDLE
)Handle
)->Handle
.Tag
== SERVICE_TAG
)
222 pService
= (PSERVICE_HANDLE
)Handle
;
224 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
226 DPRINT1("Exception: Invalid Service handle!\n");
235 ScmCheckAccess(SC_HANDLE Handle
,
236 DWORD dwDesiredAccess
)
238 PMANAGER_HANDLE hMgr
;
240 hMgr
= (PMANAGER_HANDLE
)Handle
;
241 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
243 RtlMapGenericMask(&dwDesiredAccess
,
246 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
248 return ERROR_SUCCESS
;
250 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
252 RtlMapGenericMask(&dwDesiredAccess
,
255 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
257 return ERROR_SUCCESS
;
260 return ERROR_INVALID_HANDLE
;
265 ScmAssignNewTag(PSERVICE lpService
)
268 DPRINT("Assigning new tag to service %S\n", lpService
->lpServiceName
);
269 lpService
->dwTag
= 0;
270 return ERROR_SUCCESS
;
274 /* Internal recursive function */
275 /* Need to search for every dependency on every service */
277 Int_EnumDependentServicesW(HKEY hServicesKey
,
279 DWORD dwServiceState
,
280 PSERVICE
*lpServices
,
281 LPDWORD pcbBytesNeeded
,
282 LPDWORD lpServicesReturned
)
284 DWORD dwError
= ERROR_SUCCESS
;
285 WCHAR szNameBuf
[MAX_PATH
];
286 WCHAR szValueBuf
[MAX_PATH
];
287 WCHAR
*lpszNameBuf
= szNameBuf
;
288 WCHAR
*lpszValueBuf
= szValueBuf
;
292 PSERVICE lpCurrentService
;
293 HKEY hServiceEnumKey
;
294 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
295 DWORD dwDependServiceStrPtr
= 0;
296 DWORD dwRequiredSize
= 0;
298 /* Get the number of service keys */
299 dwError
= RegQueryInfoKeyW(hServicesKey
,
311 if (dwError
!= ERROR_SUCCESS
)
313 DPRINT("ERROR! Unable to get number of services keys.\n");
317 /* Iterate the service keys to see if another service depends on the this service */
318 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
321 dwError
= RegEnumKeyExW(hServicesKey
,
329 if (dwError
!= ERROR_SUCCESS
)
332 /* Open the Service key */
333 dwError
= RegOpenKeyExW(hServicesKey
,
338 if (dwError
!= ERROR_SUCCESS
)
343 /* Check for the DependOnService Value */
344 dwError
= RegQueryValueExW(hServiceEnumKey
,
348 (LPBYTE
)lpszValueBuf
,
351 /* FIXME: Handle load order. */
353 /* If the service found has a DependOnService value */
354 if (dwError
== ERROR_SUCCESS
)
356 dwDependServiceStrPtr
= 0;
358 /* Can be more than one Dependencies in the DependOnService string */
359 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
361 if (_wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
363 /* Get the current enumed service pointer */
364 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
366 /* Check for valid Service */
367 if (!lpCurrentService
)
369 /* This should never happen! */
370 DPRINT("This should not happen at this point, report to Developer\n");
371 return ERROR_NOT_FOUND
;
374 /* Determine state the service is in */
375 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
376 dwCurrentServiceState
= SERVICE_INACTIVE
;
378 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
379 if ((dwCurrentServiceState
== dwServiceState
) ||
380 (dwServiceState
== SERVICE_STATE_ALL
))
382 /* Calculate the required size */
383 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
384 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
385 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
387 /* Add the size for service name and display name pointers */
388 dwRequiredSize
+= (2 * sizeof(PVOID
));
390 /* increase the BytesNeeded size */
391 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
393 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
396 /* Recursive call to check for its dependencies */
397 Int_EnumDependentServicesW(hServicesKey
,
404 /* If the lpServices is valid set the service pointer */
406 lpServices
[*lpServicesReturned
] = lpCurrentService
;
408 *lpServicesReturned
= *lpServicesReturned
+ 1;
412 dwDependServiceStrPtr
+= (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
415 else if (*pcbBytesNeeded
)
417 dwError
= ERROR_SUCCESS
;
420 RegCloseKey(hServiceEnumKey
);
428 DWORD
RCloseServiceHandle(
429 LPSC_RPC_HANDLE hSCObject
)
431 PMANAGER_HANDLE hManager
;
432 PSERVICE_HANDLE hService
;
436 DWORD pcbBytesNeeded
= 0;
437 DWORD dwServicesReturned
= 0;
439 DPRINT("RCloseServiceHandle() called\n");
441 DPRINT("hSCObject = %p\n", *hSCObject
);
444 return ERROR_INVALID_HANDLE
;
446 hManager
= ScmGetServiceManagerFromHandle(*hSCObject
);
447 hService
= ScmGetServiceFromHandle(*hSCObject
);
449 if (hManager
!= NULL
)
451 DPRINT("Found manager handle\n");
453 /* FIXME: add handle cleanup code */
455 HeapFree(GetProcessHeap(), 0, hManager
);
460 DPRINT("RCloseServiceHandle() done\n");
461 return ERROR_SUCCESS
;
463 else if (hService
!= NULL
)
465 DPRINT("Found service handle\n");
467 /* Lock the service database exlusively */
468 ScmLockDatabaseExclusive();
470 /* Get the pointer to the service record */
471 lpService
= hService
->ServiceEntry
;
473 /* FIXME: add handle cleanup code */
475 /* Free the handle */
476 HeapFree(GetProcessHeap(), 0, hService
);
479 ASSERT(lpService
->dwRefCount
> 0);
481 lpService
->dwRefCount
--;
482 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
483 lpService
->dwRefCount
);
485 if (lpService
->dwRefCount
== 0)
487 /* If this service has been marked for deletion */
488 if (lpService
->bDeleted
)
490 /* Open the Services Reg key */
491 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
492 L
"System\\CurrentControlSet\\Services",
494 KEY_SET_VALUE
| KEY_READ
,
496 if (dwError
!= ERROR_SUCCESS
)
498 DPRINT("Failed to open services key\n");
503 /* Call the internal function with NULL, just to get bytes we need */
504 Int_EnumDependentServicesW(hServicesKey
,
509 &dwServicesReturned
);
511 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
514 DPRINT("Deletion failed due to running dependencies.\n");
515 RegCloseKey(hServicesKey
);
517 return ERROR_SUCCESS
;
520 /* There are no references and no runnning dependencies,
521 it is now safe to delete the service */
523 /* Delete the Service Key */
524 dwError
= RegDeleteKeyW(hServicesKey
,
525 lpService
->lpServiceName
);
527 RegCloseKey(hServicesKey
);
529 if (dwError
!= ERROR_SUCCESS
)
531 DPRINT("Failed to Delete the Service Registry key\n");
536 /* Delete the Service */
537 ScmDeleteServiceRecord(lpService
);
545 DPRINT("RCloseServiceHandle() done\n");
546 return ERROR_SUCCESS
;
549 DPRINT("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
551 return ERROR_INVALID_HANDLE
;
556 DWORD
RControlService(
557 SC_RPC_HANDLE hService
,
559 LPSERVICE_STATUS lpServiceStatus
)
561 PSERVICE_HANDLE hSvc
;
563 ACCESS_MASK DesiredAccess
;
564 DWORD dwError
= ERROR_SUCCESS
;
565 DWORD pcbBytesNeeded
= 0;
566 DWORD dwServicesReturned
= 0;
567 DWORD dwControlsAccepted
;
568 DWORD dwCurrentState
;
569 HKEY hServicesKey
= NULL
;
571 DPRINT("RControlService() called\n");
574 return ERROR_SHUTDOWN_IN_PROGRESS
;
576 /* Check the service handle */
577 hSvc
= ScmGetServiceFromHandle(hService
);
580 DPRINT1("Invalid service handle!\n");
581 return ERROR_INVALID_HANDLE
;
585 /* Check the service entry point */
586 lpService
= hSvc
->ServiceEntry
;
587 if (lpService
== NULL
)
589 DPRINT1("lpService == NULL!\n");
590 return ERROR_INVALID_HANDLE
;
593 /* Check access rights */
596 case SERVICE_CONTROL_STOP
:
597 DesiredAccess
= SERVICE_STOP
;
600 case SERVICE_CONTROL_PAUSE
:
601 case SERVICE_CONTROL_CONTINUE
:
602 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
605 case SERVICE_INTERROGATE
:
606 DesiredAccess
= SERVICE_INTERROGATE
;
610 if (dwControl
>= 128 && dwControl
<= 255)
611 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
613 DesiredAccess
= SERVICE_QUERY_CONFIG
|
614 SERVICE_CHANGE_CONFIG
|
615 SERVICE_QUERY_STATUS
|
617 SERVICE_PAUSE_CONTINUE
;
621 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
623 return ERROR_ACCESS_DENIED
;
625 if (dwControl
== SERVICE_CONTROL_STOP
)
627 /* Check if the service has dependencies running as windows
628 doesn't stop a service that does */
630 /* Open the Services Reg key */
631 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
632 L
"System\\CurrentControlSet\\Services",
636 if (dwError
!= ERROR_SUCCESS
)
638 DPRINT("Failed to open services key\n");
642 /* Call the internal function with NULL, just to get bytes we need */
643 Int_EnumDependentServicesW(hServicesKey
,
648 &dwServicesReturned
);
650 RegCloseKey(hServicesKey
);
652 /* If pcbBytesNeeded is not zero then there are services running that
653 are dependent on this service */
654 if (pcbBytesNeeded
!= 0)
656 DPRINT("Service has running dependencies. Failed to stop service.\n");
657 return ERROR_DEPENDENT_SERVICES_RUNNING
;
661 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
663 /* Send control code to the driver */
664 dwError
= ScmControlDriver(lpService
,
670 dwControlsAccepted
= lpService
->Status
.dwControlsAccepted
;
671 dwCurrentState
= lpService
->Status
.dwCurrentState
;
673 /* Check the current state before sending a control request */
674 switch (dwCurrentState
)
676 case SERVICE_STOP_PENDING
:
677 case SERVICE_STOPPED
:
678 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
680 case SERVICE_START_PENDING
:
683 case SERVICE_CONTROL_STOP
:
686 case SERVICE_CONTROL_INTERROGATE
:
687 RtlCopyMemory(lpServiceStatus
,
689 sizeof(SERVICE_STATUS
));
690 return ERROR_SUCCESS
;
693 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
698 /* Check if the control code is acceptable to the service */
701 case SERVICE_CONTROL_STOP
:
702 if ((dwControlsAccepted
& SERVICE_ACCEPT_STOP
) == 0)
703 return ERROR_INVALID_SERVICE_CONTROL
;
706 case SERVICE_CONTROL_PAUSE
:
707 case SERVICE_CONTROL_CONTINUE
:
708 if ((dwControlsAccepted
& SERVICE_ACCEPT_PAUSE_CONTINUE
) == 0)
709 return ERROR_INVALID_SERVICE_CONTROL
;
713 /* Send control code to the service */
714 dwError
= ScmControlService(lpService
,
717 /* Return service status information */
718 RtlCopyMemory(lpServiceStatus
,
720 sizeof(SERVICE_STATUS
));
723 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
724 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
726 if (dwError
== ERROR_SUCCESS
&&
727 dwControl
== SERVICE_CONTROL_STOP
&&
728 lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
)
730 lpService
->ProcessId
= 0; /* FIXME */
731 lpService
->ThreadId
= 0;
740 DWORD
RDeleteService(
741 SC_RPC_HANDLE hService
)
743 PSERVICE_HANDLE hSvc
;
747 DPRINT("RDeleteService() called\n");
750 return ERROR_SHUTDOWN_IN_PROGRESS
;
752 hSvc
= ScmGetServiceFromHandle(hService
);
755 DPRINT1("Invalid service handle!\n");
756 return ERROR_INVALID_HANDLE
;
759 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
761 return ERROR_ACCESS_DENIED
;
763 lpService
= hSvc
->ServiceEntry
;
764 if (lpService
== NULL
)
766 DPRINT("lpService == NULL!\n");
767 return ERROR_INVALID_HANDLE
;
770 /* Lock the service database exclusively */
771 ScmLockDatabaseExclusive();
773 if (lpService
->bDeleted
)
775 DPRINT("The service has already been marked for delete!\n");
776 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
780 /* Mark service for delete */
781 lpService
->bDeleted
= TRUE
;
783 dwError
= ScmMarkServiceForDelete(lpService
);
786 /* Unlock the service database */
789 DPRINT("RDeleteService() done\n");
796 DWORD
RLockServiceDatabase(
797 SC_RPC_HANDLE hSCManager
,
798 LPSC_RPC_LOCK lpLock
)
800 PMANAGER_HANDLE hMgr
;
802 DPRINT("RLockServiceDatabase() called\n");
806 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
809 DPRINT1("Invalid service manager handle!\n");
810 return ERROR_INVALID_HANDLE
;
813 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
815 return ERROR_ACCESS_DENIED
;
817 // return ScmLockDatabase(0, hMgr->0xC, hLock);
819 /* FIXME: Lock the database */
820 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
822 return ERROR_SUCCESS
;
827 DWORD
RQueryServiceObjectSecurity(
828 SC_RPC_HANDLE hService
,
829 SECURITY_INFORMATION dwSecurityInformation
,
830 LPBYTE lpSecurityDescriptor
,
832 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
834 PSERVICE_HANDLE hSvc
;
836 ULONG DesiredAccess
= 0;
842 SECURITY_DESCRIPTOR ObjectDescriptor
;
844 DPRINT("RQueryServiceObjectSecurity() called\n");
846 hSvc
= ScmGetServiceFromHandle(hService
);
849 DPRINT1("Invalid service handle!\n");
850 return ERROR_INVALID_HANDLE
;
853 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
|
854 GROUP_SECURITY_INFORMATION
|
855 OWNER_SECURITY_INFORMATION
))
856 DesiredAccess
|= READ_CONTROL
;
858 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
859 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
861 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
864 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
865 return ERROR_ACCESS_DENIED
;
868 lpService
= hSvc
->ServiceEntry
;
869 if (lpService
== NULL
)
871 DPRINT("lpService == NULL!\n");
872 return ERROR_INVALID_HANDLE
;
875 /* FIXME: Lock the service list */
878 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
880 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
881 dwSecurityInformation
,
882 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
886 /* FIXME: Unlock the service list */
888 if (NT_SUCCESS(Status
))
890 *pcbBytesNeeded
= dwBytesNeeded
;
891 dwError
= STATUS_SUCCESS
;
893 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
895 *pcbBytesNeeded
= dwBytesNeeded
;
896 dwError
= ERROR_INSUFFICIENT_BUFFER
;
898 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
900 dwError
= ERROR_GEN_FAILURE
;
904 dwError
= RtlNtStatusToDosError(Status
);
912 DWORD
RSetServiceObjectSecurity(
913 SC_RPC_HANDLE hService
,
914 DWORD dwSecurityInformation
,
915 LPBYTE lpSecurityDescriptor
,
916 DWORD dwSecuityDescriptorSize
)
918 PSERVICE_HANDLE hSvc
;
920 ULONG DesiredAccess
= 0;
921 /* HANDLE hToken = NULL; */
923 /* NTSTATUS Status; */
926 DPRINT("RSetServiceObjectSecurity() called\n");
928 hSvc
= ScmGetServiceFromHandle(hService
);
931 DPRINT1("Invalid service handle!\n");
932 return ERROR_INVALID_HANDLE
;
935 if (dwSecurityInformation
== 0 ||
936 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
937 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
938 return ERROR_INVALID_PARAMETER
;
940 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
941 return ERROR_INVALID_PARAMETER
;
943 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
944 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
946 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
947 DesiredAccess
|= WRITE_DAC
;
949 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
950 DesiredAccess
|= WRITE_OWNER
;
952 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
953 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
954 return ERROR_INVALID_PARAMETER
;
956 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
957 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
958 return ERROR_INVALID_PARAMETER
;
960 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
963 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
964 return ERROR_ACCESS_DENIED
;
967 lpService
= hSvc
->ServiceEntry
;
968 if (lpService
== NULL
)
970 DPRINT("lpService == NULL!\n");
971 return ERROR_INVALID_HANDLE
;
974 if (lpService
->bDeleted
)
975 return ERROR_SERVICE_MARKED_FOR_DELETE
;
978 RpcImpersonateClient(NULL
);
980 Status
= NtOpenThreadToken(NtCurrentThread(),
984 if (!NT_SUCCESS(Status
))
985 return RtlNtStatusToDosError(Status
);
989 /* FIXME: Lock service database */
991 Status
= RtlSetSecurityObject(dwSecurityInformation
,
992 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
993 &lpService
->lpSecurityDescriptor
,
996 if (!NT_SUCCESS(Status
))
998 dwError
= RtlNtStatusToDosError(Status
);
1003 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
1004 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
1006 if (dwError
!= ERROR_SUCCESS
)
1010 dwError
= ERROR_SUCCESS
;
1011 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
1012 // lpService->lpSecurityDescriptor);
1014 RegFlushKey(hServiceKey
);
1015 RegCloseKey(hServiceKey
);
1024 /* FIXME: Unlock service database */
1026 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1033 DWORD
RQueryServiceStatus(
1034 SC_RPC_HANDLE hService
,
1035 LPSERVICE_STATUS lpServiceStatus
)
1037 PSERVICE_HANDLE hSvc
;
1040 DPRINT("RQueryServiceStatus() called\n");
1043 return ERROR_SHUTDOWN_IN_PROGRESS
;
1045 hSvc
= ScmGetServiceFromHandle(hService
);
1048 DPRINT1("Invalid service handle!\n");
1049 return ERROR_INVALID_HANDLE
;
1052 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1053 SERVICE_QUERY_STATUS
))
1055 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1056 return ERROR_ACCESS_DENIED
;
1059 lpService
= hSvc
->ServiceEntry
;
1060 if (lpService
== NULL
)
1062 DPRINT("lpService == NULL!\n");
1063 return ERROR_INVALID_HANDLE
;
1066 /* Lock the srevice database shared */
1067 ScmLockDatabaseShared();
1069 /* Return service status information */
1070 RtlCopyMemory(lpServiceStatus
,
1072 sizeof(SERVICE_STATUS
));
1074 /* Unlock the service database */
1075 ScmUnlockDatabase();
1077 return ERROR_SUCCESS
;
1082 ScmIsValidServiceState(DWORD dwCurrentState
)
1084 switch (dwCurrentState
)
1086 case SERVICE_STOPPED
:
1087 case SERVICE_START_PENDING
:
1088 case SERVICE_STOP_PENDING
:
1089 case SERVICE_RUNNING
:
1090 case SERVICE_CONTINUE_PENDING
:
1091 case SERVICE_PAUSE_PENDING
:
1092 case SERVICE_PAUSED
:
1102 DWORD
RSetServiceStatus(
1103 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1104 LPSERVICE_STATUS lpServiceStatus
)
1108 DPRINT("RSetServiceStatus() called\n");
1109 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1110 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1111 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1112 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1113 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1114 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1115 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1116 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1118 if (hServiceStatus
== 0)
1120 DPRINT("hServiceStatus == NULL!\n");
1121 return ERROR_INVALID_HANDLE
;
1124 lpService
= (PSERVICE
)hServiceStatus
;
1125 if (lpService
== NULL
)
1127 DPRINT("lpService == NULL!\n");
1128 return ERROR_INVALID_HANDLE
;
1131 /* Check current state */
1132 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1134 DPRINT("Invalid service state!\n");
1135 return ERROR_INVALID_DATA
;
1138 /* Check service type */
1139 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1140 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1142 DPRINT("Invalid service type!\n");
1143 return ERROR_INVALID_DATA
;
1146 /* Check accepted controls */
1147 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1149 DPRINT("Invalid controls accepted!\n");
1150 return ERROR_INVALID_DATA
;
1153 /* Lock the service database exclusively */
1154 ScmLockDatabaseExclusive();
1156 RtlCopyMemory(&lpService
->Status
,
1158 sizeof(SERVICE_STATUS
));
1160 /* Unlock the service database */
1161 ScmUnlockDatabase();
1163 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1164 DPRINT("RSetServiceStatus() done\n");
1166 return ERROR_SUCCESS
;
1171 DWORD
RUnlockServiceDatabase(
1175 return ERROR_SUCCESS
;
1180 DWORD
RNotifyBootConfigStatus(
1181 SVCCTL_HANDLEW lpMachineName
,
1182 DWORD BootAcceptable
)
1185 return ERROR_CALL_NOT_IMPLEMENTED
;
1190 DWORD
RI_ScSetServiceBitsW(
1191 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1192 DWORD dwServiceBits
,
1194 int bUpdateImmediately
,
1198 return ERROR_CALL_NOT_IMPLEMENTED
;
1203 DWORD
RChangeServiceConfigW(
1204 SC_RPC_HANDLE hService
,
1205 DWORD dwServiceType
,
1207 DWORD dwErrorControl
,
1208 LPWSTR lpBinaryPathName
,
1209 LPWSTR lpLoadOrderGroup
,
1211 LPBYTE lpDependencies
,
1213 LPWSTR lpServiceStartName
,
1216 LPWSTR lpDisplayName
)
1218 DWORD dwError
= ERROR_SUCCESS
;
1219 PSERVICE_HANDLE hSvc
;
1220 PSERVICE lpService
= NULL
;
1221 HKEY hServiceKey
= NULL
;
1222 LPWSTR lpDisplayNameW
= NULL
;
1224 DPRINT("RChangeServiceConfigW() called\n");
1225 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1226 DPRINT("dwStartType = %lu\n", dwStartType
);
1227 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1228 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1229 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1230 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1233 return ERROR_SHUTDOWN_IN_PROGRESS
;
1235 hSvc
= ScmGetServiceFromHandle(hService
);
1238 DPRINT1("Invalid service handle!\n");
1239 return ERROR_INVALID_HANDLE
;
1242 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1243 SERVICE_CHANGE_CONFIG
))
1245 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1246 return ERROR_ACCESS_DENIED
;
1249 lpService
= hSvc
->ServiceEntry
;
1250 if (lpService
== NULL
)
1252 DPRINT("lpService == NULL!\n");
1253 return ERROR_INVALID_HANDLE
;
1256 /* Lock the service database exclusively */
1257 ScmLockDatabaseExclusive();
1259 if (lpService
->bDeleted
)
1261 DPRINT("The service has already been marked for delete!\n");
1262 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1266 /* Open the service key */
1267 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1270 if (dwError
!= ERROR_SUCCESS
)
1273 /* Write service data to the registry */
1274 /* Set the display name */
1275 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1277 RegSetValueExW(hServiceKey
,
1281 (LPBYTE
)lpDisplayName
,
1282 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1284 /* Update the display name */
1285 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1287 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1288 if (lpDisplayNameW
== NULL
)
1290 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1294 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1295 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1297 lpService
->lpDisplayName
= lpDisplayNameW
;
1300 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1302 /* Set the service type */
1303 dwError
= RegSetValueExW(hServiceKey
,
1307 (LPBYTE
)&dwServiceType
,
1309 if (dwError
!= ERROR_SUCCESS
)
1312 lpService
->Status
.dwServiceType
= dwServiceType
;
1315 if (dwStartType
!= SERVICE_NO_CHANGE
)
1317 /* Set the start value */
1318 dwError
= RegSetValueExW(hServiceKey
,
1322 (LPBYTE
)&dwStartType
,
1324 if (dwError
!= ERROR_SUCCESS
)
1327 lpService
->dwStartType
= dwStartType
;
1330 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1332 /* Set the error control value */
1333 dwError
= RegSetValueExW(hServiceKey
,
1337 (LPBYTE
)&dwErrorControl
,
1339 if (dwError
!= ERROR_SUCCESS
)
1342 lpService
->dwErrorControl
= dwErrorControl
;
1346 /* FIXME: set the new ImagePath value */
1348 /* Set the image path */
1349 if (dwServiceType
& SERVICE_WIN32
)
1351 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1353 dwError
= RegSetValueExW(hServiceKey
,
1357 (LPBYTE
)lpBinaryPathName
,
1358 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1359 if (dwError
!= ERROR_SUCCESS
)
1363 else if (dwServiceType
& SERVICE_DRIVER
)
1365 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1367 dwError
= RegSetValueExW(hServiceKey
,
1371 (LPBYTE
)lpImagePath
,
1372 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1373 if (dwError
!= ERROR_SUCCESS
)
1379 /* Set the group name */
1380 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1382 dwError
= RegSetValueExW(hServiceKey
,
1386 (LPBYTE
)lpLoadOrderGroup
,
1387 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1388 if (dwError
!= ERROR_SUCCESS
)
1391 dwError
= ScmSetServiceGroup(lpService
,
1393 if (dwError
!= ERROR_SUCCESS
)
1397 if (lpdwTagId
!= NULL
)
1399 dwError
= ScmAssignNewTag(lpService
);
1400 if (dwError
!= ERROR_SUCCESS
)
1403 dwError
= RegSetValueExW(hServiceKey
,
1407 (LPBYTE
)&lpService
->dwTag
,
1409 if (dwError
!= ERROR_SUCCESS
)
1412 *lpdwTagId
= lpService
->dwTag
;
1415 /* Write dependencies */
1416 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1418 dwError
= ScmWriteDependencies(hServiceKey
,
1419 (LPWSTR
)lpDependencies
,
1421 if (dwError
!= ERROR_SUCCESS
)
1425 if (lpPassword
!= NULL
)
1427 /* FIXME: Write password */
1431 if (hServiceKey
!= NULL
)
1432 RegCloseKey(hServiceKey
);
1434 /* Unlock the service database */
1435 ScmUnlockDatabase();
1437 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1443 /* Create a path suitable for the bootloader out of the full path */
1445 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1447 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1450 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1451 OBJECT_ATTRIBUTES ObjectAttributes
;
1453 HANDLE SymbolicLinkHandle
;
1455 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1457 ServiceNameLen
= wcslen(CanonName
);
1459 /* First check, if it's already good */
1460 if (ServiceNameLen
> 12 &&
1461 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1463 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1464 if (*RelativeName
== NULL
)
1466 DPRINT("Error allocating memory for boot driver name!\n");
1467 return ERROR_NOT_ENOUGH_MEMORY
;
1471 wcscpy(*RelativeName
, CanonName
);
1473 DPRINT("Bootdriver name %S\n", *RelativeName
);
1474 return ERROR_SUCCESS
;
1477 /* If it has %SystemRoot% prefix, substitute it to \System*/
1478 if (ServiceNameLen
> 13 &&
1479 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1481 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1482 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1484 if (*RelativeName
== NULL
)
1486 DPRINT("Error allocating memory for boot driver name!\n");
1487 return ERROR_NOT_ENOUGH_MEMORY
;
1491 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1492 wcscat(*RelativeName
, CanonName
+ 13);
1494 DPRINT("Bootdriver name %S\n", *RelativeName
);
1495 return ERROR_SUCCESS
;
1498 /* Get buffer size needed for expanding env strings */
1499 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1501 if (BufferSize
<= 1)
1503 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1504 return ERROR_INVALID_ENVIRONMENT
;
1507 /* Allocate memory, since the size is known now */
1508 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1511 DPRINT("Error allocating memory for boot driver name!\n");
1512 return ERROR_NOT_ENOUGH_MEMORY
;
1516 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1519 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1520 LocalFree(Expanded
);
1521 return ERROR_NOT_ENOUGH_MEMORY
;
1524 /* Convert to NY-style path */
1525 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1527 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1528 return ERROR_INVALID_ENVIRONMENT
;
1531 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1533 /* No need to keep the dos-path anymore */
1534 LocalFree(Expanded
);
1536 /* Copy it to the allocated place */
1537 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1540 DPRINT("Error allocating memory for boot driver name!\n");
1541 return ERROR_NOT_ENOUGH_MEMORY
;
1544 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1545 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1546 Expanded
[ExpandedLen
] = 0;
1548 if (ServiceNameLen
> ExpandedLen
&&
1549 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1551 /* Only \SystemRoot\ is missing */
1552 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1553 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1554 if (*RelativeName
== NULL
)
1556 DPRINT("Error allocating memory for boot driver name!\n");
1557 LocalFree(Expanded
);
1558 return ERROR_NOT_ENOUGH_MEMORY
;
1561 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1562 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1564 RtlFreeUnicodeString(&NtPathName
);
1565 return ERROR_SUCCESS
;
1568 /* The most complex case starts here */
1569 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1570 InitializeObjectAttributes(&ObjectAttributes
,
1572 OBJ_CASE_INSENSITIVE
,
1576 /* Open this symlink */
1577 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1579 if (NT_SUCCESS(Status
))
1581 LinkTarget
.Length
= 0;
1582 LinkTarget
.MaximumLength
= 0;
1584 DPRINT("Opened symbolic link object\n");
1586 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1587 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1589 /* Check if required buffer size is sane */
1590 if (BufferSize
> 0xFFFD)
1592 DPRINT("Too large buffer required\n");
1595 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1596 LocalFree(Expanded
);
1597 return ERROR_NOT_ENOUGH_MEMORY
;
1600 /* Alloc the string */
1601 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1602 if (!LinkTarget
.Buffer
)
1604 DPRINT("Unable to alloc buffer\n");
1605 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1606 LocalFree(Expanded
);
1607 return ERROR_NOT_ENOUGH_MEMORY
;
1610 /* Do a real query now */
1611 LinkTarget
.Length
= BufferSize
;
1612 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1614 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1615 if (NT_SUCCESS(Status
))
1617 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1619 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1620 if ((ServiceNameLen
> ExpandedLen
) &&
1621 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1623 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1624 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1626 if (*RelativeName
== NULL
)
1628 DPRINT("Unable to alloc buffer\n");
1629 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1630 LocalFree(Expanded
);
1631 RtlFreeUnicodeString(&NtPathName
);
1632 return ERROR_NOT_ENOUGH_MEMORY
;
1635 /* Copy it over, substituting the first part
1637 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1638 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1641 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1642 LocalFree(Expanded
);
1643 RtlFreeUnicodeString(&NtPathName
);
1645 /* Return success */
1646 return ERROR_SUCCESS
;
1650 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1651 LocalFree(Expanded
);
1652 RtlFreeUnicodeString(&NtPathName
);
1653 return ERROR_INVALID_PARAMETER
;
1658 DPRINT("Error, Status = %08X\n", Status
);
1659 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1660 LocalFree(Expanded
);
1661 RtlFreeUnicodeString(&NtPathName
);
1662 return ERROR_INVALID_PARAMETER
;
1667 DPRINT("Error, Status = %08X\n", Status
);
1668 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1669 LocalFree(Expanded
);
1670 RtlFreeUnicodeString(&NtPathName
);
1671 return ERROR_INVALID_PARAMETER
;
1676 DPRINT("Error, Status = %08X\n", Status
);
1677 LocalFree(Expanded
);
1678 return ERROR_INVALID_PARAMETER
;
1682 *RelativeName
= NULL
;
1683 return ERROR_INVALID_PARAMETER
;
1687 ScmCanonDriverImagePath(DWORD dwStartType
,
1688 const wchar_t *lpServiceName
,
1689 wchar_t **lpCanonName
)
1691 DWORD ServiceNameLen
, Result
;
1692 UNICODE_STRING NtServiceName
;
1693 WCHAR
*RelativeName
;
1694 const WCHAR
*SourceName
= lpServiceName
;
1696 /* Calculate the length of the service's name */
1697 ServiceNameLen
= wcslen(lpServiceName
);
1699 /* 12 is wcslen(L"\\SystemRoot\\") */
1700 if (ServiceNameLen
> 12 &&
1701 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1703 /* SystemRoot prefix is already included */
1705 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1707 if (*lpCanonName
== NULL
)
1709 DPRINT("Error allocating memory for canonized service name!\n");
1710 return ERROR_NOT_ENOUGH_MEMORY
;
1713 /* If it's a boot-time driver, it must be systemroot relative */
1714 if (dwStartType
== SERVICE_BOOT_START
)
1718 wcscpy(*lpCanonName
, SourceName
);
1720 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1724 /* Check if it has %SystemRoot% (len=13) */
1725 if (ServiceNameLen
> 13 &&
1726 !_wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1728 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1729 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1731 if (*lpCanonName
== NULL
)
1733 DPRINT("Error allocating memory for canonized service name!\n");
1734 return ERROR_NOT_ENOUGH_MEMORY
;
1737 /* If it's a boot-time driver, it must be systemroot relative */
1738 if (dwStartType
== SERVICE_BOOT_START
)
1739 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1741 wcscat(*lpCanonName
, lpServiceName
+ 13);
1743 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1747 /* Check if it's a relative path name */
1748 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1750 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1752 if (*lpCanonName
== NULL
)
1754 DPRINT("Error allocating memory for canonized service name!\n");
1755 return ERROR_NOT_ENOUGH_MEMORY
;
1758 /* Just copy it over without changing */
1759 wcscpy(*lpCanonName
, lpServiceName
);
1764 /* It seems to be a DOS path, convert it */
1765 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1767 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
1768 return ERROR_INVALID_PARAMETER
;
1771 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1773 if (*lpCanonName
== NULL
)
1775 DPRINT("Error allocating memory for canonized service name!\n");
1776 RtlFreeUnicodeString(&NtServiceName
);
1777 return ERROR_NOT_ENOUGH_MEMORY
;
1780 /* Copy the string */
1781 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1783 /* The unicode string is not needed anymore */
1784 RtlFreeUnicodeString(&NtServiceName
);
1786 if (dwStartType
!= SERVICE_BOOT_START
)
1788 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1792 /* The service is boot-started, so must be relative */
1793 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1796 /* There is a problem, free name and return */
1797 LocalFree(*lpCanonName
);
1798 DPRINT("Error converting named!\n");
1802 ASSERT(RelativeName
);
1804 /* Copy that string */
1805 wcscpy(*lpCanonName
, RelativeName
+ 12);
1807 /* Free the allocated buffer */
1808 LocalFree(RelativeName
);
1810 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1818 DWORD
RCreateServiceW(
1819 SC_RPC_HANDLE hSCManager
,
1820 LPCWSTR lpServiceName
,
1821 LPCWSTR lpDisplayName
,
1822 DWORD dwDesiredAccess
,
1823 DWORD dwServiceType
,
1825 DWORD dwErrorControl
,
1826 LPCWSTR lpBinaryPathName
,
1827 LPCWSTR lpLoadOrderGroup
,
1829 LPBYTE lpDependencies
,
1831 LPCWSTR lpServiceStartName
,
1834 LPSC_RPC_HANDLE lpServiceHandle
)
1836 PMANAGER_HANDLE hManager
;
1837 DWORD dwError
= ERROR_SUCCESS
;
1838 PSERVICE lpService
= NULL
;
1839 SC_HANDLE hServiceHandle
= NULL
;
1840 LPWSTR lpImagePath
= NULL
;
1841 HKEY hServiceKey
= NULL
;
1842 LPWSTR lpObjectName
;
1844 DPRINT("RCreateServiceW() called\n");
1845 DPRINT("lpServiceName = %S\n", lpServiceName
);
1846 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1847 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1848 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1849 DPRINT("dwStartType = %lu\n", dwStartType
);
1850 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1851 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1852 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1855 return ERROR_SHUTDOWN_IN_PROGRESS
;
1857 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
1858 if (hManager
== NULL
)
1860 DPRINT1("Invalid service manager handle!\n");
1861 return ERROR_INVALID_HANDLE
;
1864 /* Check access rights */
1865 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1866 SC_MANAGER_CREATE_SERVICE
))
1868 DPRINT("Insufficient access rights! 0x%lx\n",
1869 hManager
->Handle
.DesiredAccess
);
1870 return ERROR_ACCESS_DENIED
;
1873 if (wcslen(lpServiceName
) == 0)
1875 return ERROR_INVALID_NAME
;
1878 if (wcslen(lpBinaryPathName
) == 0)
1880 return ERROR_INVALID_PARAMETER
;
1883 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1884 (lpServiceStartName
))
1886 return ERROR_INVALID_PARAMETER
;
1889 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1890 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1891 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1893 return ERROR_INVALID_PARAMETER
;
1896 if (dwStartType
> SERVICE_DISABLED
)
1898 return ERROR_INVALID_PARAMETER
;
1901 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1904 /* check if it is marked for deletion */
1905 if (lpService
->bDeleted
)
1906 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1907 /* Return Error exist */
1908 return ERROR_SERVICE_EXISTS
;
1911 if (lpDisplayName
!= NULL
&&
1912 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1913 return ERROR_DUPLICATE_SERVICE_NAME
;
1915 if (dwServiceType
& SERVICE_DRIVER
)
1917 dwError
= ScmCanonDriverImagePath(dwStartType
,
1920 if (dwError
!= ERROR_SUCCESS
)
1925 if (dwStartType
== SERVICE_BOOT_START
||
1926 dwStartType
== SERVICE_SYSTEM_START
)
1928 return ERROR_INVALID_PARAMETER
;
1932 /* Allocate a new service entry */
1933 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1935 if (dwError
!= ERROR_SUCCESS
)
1938 /* Fill the new service entry */
1939 lpService
->Status
.dwServiceType
= dwServiceType
;
1940 lpService
->dwStartType
= dwStartType
;
1941 lpService
->dwErrorControl
= dwErrorControl
;
1943 /* Fill the display name */
1944 if (lpDisplayName
!= NULL
&&
1945 *lpDisplayName
!= 0 &&
1946 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1948 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1949 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1950 if (lpService
->lpDisplayName
== NULL
)
1952 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1955 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1958 /* Assign the service to a group */
1959 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1961 dwError
= ScmSetServiceGroup(lpService
,
1963 if (dwError
!= ERROR_SUCCESS
)
1967 /* Assign a new tag */
1968 if (lpdwTagId
!= NULL
)
1970 dwError
= ScmAssignNewTag(lpService
);
1971 if (dwError
!= ERROR_SUCCESS
)
1975 /* Write service data to the registry */
1976 /* Create the service key */
1977 dwError
= ScmCreateServiceKey(lpServiceName
,
1980 if (dwError
!= ERROR_SUCCESS
)
1983 /* Set the display name */
1984 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1986 RegSetValueExW(hServiceKey
,
1990 (LPBYTE
)lpDisplayName
,
1991 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1994 /* Set the service type */
1995 dwError
= RegSetValueExW(hServiceKey
,
1999 (LPBYTE
)&dwServiceType
,
2001 if (dwError
!= ERROR_SUCCESS
)
2004 /* Set the start value */
2005 dwError
= RegSetValueExW(hServiceKey
,
2009 (LPBYTE
)&dwStartType
,
2011 if (dwError
!= ERROR_SUCCESS
)
2014 /* Set the error control value */
2015 dwError
= RegSetValueExW(hServiceKey
,
2019 (LPBYTE
)&dwErrorControl
,
2021 if (dwError
!= ERROR_SUCCESS
)
2024 /* Set the image path */
2025 if (dwServiceType
& SERVICE_WIN32
)
2027 dwError
= RegSetValueExW(hServiceKey
,
2031 (LPBYTE
)lpBinaryPathName
,
2032 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
2033 if (dwError
!= ERROR_SUCCESS
)
2036 else if (dwServiceType
& SERVICE_DRIVER
)
2038 dwError
= RegSetValueExW(hServiceKey
,
2042 (LPBYTE
)lpImagePath
,
2043 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2044 if (dwError
!= ERROR_SUCCESS
)
2048 /* Set the group name */
2049 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2051 dwError
= RegSetValueExW(hServiceKey
,
2055 (LPBYTE
)lpLoadOrderGroup
,
2056 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
2057 if (dwError
!= ERROR_SUCCESS
)
2061 if (lpdwTagId
!= NULL
)
2063 dwError
= RegSetValueExW(hServiceKey
,
2067 (LPBYTE
)&lpService
->dwTag
,
2069 if (dwError
!= ERROR_SUCCESS
)
2073 /* Write dependencies */
2074 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2076 dwError
= ScmWriteDependencies(hServiceKey
,
2077 (LPWSTR
)lpDependencies
,
2079 if (dwError
!= ERROR_SUCCESS
)
2083 /* Write service start name */
2084 if (dwServiceType
& SERVICE_WIN32
)
2086 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2087 dwError
= RegSetValueExW(hServiceKey
,
2091 (LPBYTE
)lpObjectName
,
2092 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
2093 if (dwError
!= ERROR_SUCCESS
)
2097 if (lpPassword
!= NULL
)
2099 /* FIXME: Write password */
2102 dwError
= ScmCreateServiceHandle(lpService
,
2104 if (dwError
!= ERROR_SUCCESS
)
2107 dwError
= ScmCheckAccess(hServiceHandle
,
2109 if (dwError
!= ERROR_SUCCESS
)
2112 lpService
->dwRefCount
= 1;
2113 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2116 if (hServiceKey
!= NULL
)
2117 RegCloseKey(hServiceKey
);
2119 if (dwError
== ERROR_SUCCESS
)
2121 DPRINT("hService %p\n", hServiceHandle
);
2122 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2124 if (lpdwTagId
!= NULL
)
2125 *lpdwTagId
= lpService
->dwTag
;
2129 /* Release the display name buffer */
2130 if (lpService
->lpServiceName
!= NULL
)
2131 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2135 /* Remove the service handle */
2136 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2139 if (lpService
!= NULL
)
2141 /* FIXME: remove the service entry */
2145 if (lpImagePath
!= NULL
)
2146 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2148 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2155 DWORD
REnumDependentServicesW(
2156 SC_RPC_HANDLE hService
,
2157 DWORD dwServiceState
,
2160 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2161 LPBOUNDED_DWORD_256K lpServicesReturned
)
2163 DWORD dwError
= ERROR_SUCCESS
;
2164 DWORD dwServicesReturned
= 0;
2165 DWORD dwServiceCount
;
2166 HKEY hServicesKey
= NULL
;
2167 PSERVICE_HANDLE hSvc
;
2168 PSERVICE lpService
= NULL
;
2169 PSERVICE
*lpServicesArray
= NULL
;
2170 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2173 *pcbBytesNeeded
= 0;
2174 *lpServicesReturned
= 0;
2176 DPRINT("REnumDependentServicesW() called\n");
2178 hSvc
= ScmGetServiceFromHandle(hService
);
2181 DPRINT1("Invalid service handle!\n");
2182 return ERROR_INVALID_HANDLE
;
2185 lpService
= hSvc
->ServiceEntry
;
2187 /* Check access rights */
2188 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2189 SC_MANAGER_ENUMERATE_SERVICE
))
2191 DPRINT("Insufficient access rights! 0x%lx\n",
2192 hSvc
->Handle
.DesiredAccess
);
2193 return ERROR_ACCESS_DENIED
;
2196 /* Open the Services Reg key */
2197 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2198 L
"System\\CurrentControlSet\\Services",
2202 if (dwError
!= ERROR_SUCCESS
)
2205 /* First determine the bytes needed and get the number of dependent services */
2206 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2211 &dwServicesReturned
);
2212 if (dwError
!= ERROR_SUCCESS
)
2215 /* If buffer size is less than the bytes needed or pointer is null */
2216 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2218 dwError
= ERROR_MORE_DATA
;
2222 /* Allocate memory for array of service pointers */
2223 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2225 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2226 if (!lpServicesArray
)
2228 DPRINT("Could not allocate a buffer!!\n");
2229 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2233 dwServicesReturned
= 0;
2234 *pcbBytesNeeded
= 0;
2236 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2241 &dwServicesReturned
);
2242 if (dwError
!= ERROR_SUCCESS
)
2247 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2248 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2250 /* Copy EnumDepenedentService to Buffer */
2251 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2253 lpService
= lpServicesArray
[dwServiceCount
];
2255 /* Copy status info */
2256 memcpy(&lpServicesPtr
->ServiceStatus
,
2258 sizeof(SERVICE_STATUS
));
2260 /* Copy display name */
2261 wcscpy(lpStr
, lpService
->lpDisplayName
);
2262 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2263 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2265 /* Copy service name */
2266 wcscpy(lpStr
, lpService
->lpServiceName
);
2267 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2268 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2273 *lpServicesReturned
= dwServicesReturned
;
2276 if (lpServicesArray
!= NULL
)
2277 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2279 RegCloseKey(hServicesKey
);
2281 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2288 DWORD
REnumServicesStatusW(
2289 SC_RPC_HANDLE hSCManager
,
2290 DWORD dwServiceType
,
2291 DWORD dwServiceState
,
2294 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2295 LPBOUNDED_DWORD_256K lpServicesReturned
,
2296 LPBOUNDED_DWORD_256K lpResumeHandle
)
2298 PMANAGER_HANDLE hManager
;
2300 DWORD dwError
= ERROR_SUCCESS
;
2301 PLIST_ENTRY ServiceEntry
;
2302 PSERVICE CurrentService
;
2304 DWORD dwRequiredSize
;
2305 DWORD dwServiceCount
;
2307 DWORD dwLastResumeCount
= 0;
2308 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2311 DPRINT("REnumServicesStatusW() called\n");
2314 return ERROR_SHUTDOWN_IN_PROGRESS
;
2316 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2317 if (hManager
== NULL
)
2319 DPRINT1("Invalid service manager handle!\n");
2320 return ERROR_INVALID_HANDLE
;
2324 *pcbBytesNeeded
= 0;
2325 *lpServicesReturned
= 0;
2327 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2329 DPRINT("Not a valid Service Type!\n");
2330 return ERROR_INVALID_PARAMETER
;
2333 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2335 DPRINT("Not a valid Service State!\n");
2336 return ERROR_INVALID_PARAMETER
;
2339 /* Check access rights */
2340 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2341 SC_MANAGER_ENUMERATE_SERVICE
))
2343 DPRINT("Insufficient access rights! 0x%lx\n",
2344 hManager
->Handle
.DesiredAccess
);
2345 return ERROR_ACCESS_DENIED
;
2349 dwLastResumeCount
= *lpResumeHandle
;
2351 /* Lock the service database shared */
2352 ScmLockDatabaseShared();
2354 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2355 if (lpService
== NULL
)
2357 dwError
= ERROR_SUCCESS
;
2364 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2365 ServiceEntry
!= &ServiceListHead
;
2366 ServiceEntry
= ServiceEntry
->Flink
)
2368 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2372 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2375 dwState
= SERVICE_ACTIVE
;
2376 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2377 dwState
= SERVICE_INACTIVE
;
2379 if ((dwState
& dwServiceState
) == 0)
2382 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2383 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2384 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2386 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2388 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2392 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2393 dwRequiredSize
+= dwSize
;
2395 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2398 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2399 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2402 ServiceEntry
!= &ServiceListHead
;
2403 ServiceEntry
= ServiceEntry
->Flink
)
2405 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2409 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2412 dwState
= SERVICE_ACTIVE
;
2413 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2414 dwState
= SERVICE_INACTIVE
;
2416 if ((dwState
& dwServiceState
) == 0)
2419 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2420 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2421 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2423 dwError
= ERROR_MORE_DATA
;
2426 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2429 *lpResumeHandle
= dwLastResumeCount
;
2431 *lpServicesReturned
= dwServiceCount
;
2432 *pcbBytesNeeded
= dwRequiredSize
;
2434 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2435 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2436 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2439 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2440 ServiceEntry
!= &ServiceListHead
;
2441 ServiceEntry
= ServiceEntry
->Flink
)
2443 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2447 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2450 dwState
= SERVICE_ACTIVE
;
2451 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2452 dwState
= SERVICE_INACTIVE
;
2454 if ((dwState
& dwServiceState
) == 0)
2457 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2458 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2459 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2461 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2464 /* Copy the service name */
2465 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2466 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2467 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2469 /* Copy the display name */
2470 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2471 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2472 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2474 /* Copy the status information */
2475 memcpy(&lpStatusPtr
->ServiceStatus
,
2476 &CurrentService
->Status
,
2477 sizeof(SERVICE_STATUS
));
2480 dwRequiredSize
+= dwSize
;
2485 *pcbBytesNeeded
= 0;
2486 if (lpResumeHandle
) *lpResumeHandle
= 0;
2490 /* Unlock the service database */
2491 ScmUnlockDatabase();
2493 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2500 DWORD
ROpenSCManagerW(
2501 LPWSTR lpMachineName
,
2502 LPWSTR lpDatabaseName
,
2503 DWORD dwDesiredAccess
,
2504 LPSC_RPC_HANDLE lpScHandle
)
2509 DPRINT("ROpenSCManagerW() called\n");
2510 DPRINT("lpMachineName = %p\n", lpMachineName
);
2511 DPRINT("lpMachineName: %S\n", lpMachineName
);
2512 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2513 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2514 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2517 return ERROR_SHUTDOWN_IN_PROGRESS
;
2520 return ERROR_INVALID_PARAMETER
;
2522 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2524 if (dwError
!= ERROR_SUCCESS
)
2526 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2530 /* Check the desired access */
2531 dwError
= ScmCheckAccess(hHandle
,
2532 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2533 if (dwError
!= ERROR_SUCCESS
)
2535 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2536 HeapFree(GetProcessHeap(), 0, hHandle
);
2540 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2541 DPRINT("*hScm = %p\n", *lpScHandle
);
2543 DPRINT("ROpenSCManagerW() done\n");
2545 return ERROR_SUCCESS
;
2550 DWORD
ROpenServiceW(
2551 SC_RPC_HANDLE hSCManager
,
2552 LPWSTR lpServiceName
,
2553 DWORD dwDesiredAccess
,
2554 LPSC_RPC_HANDLE lpServiceHandle
)
2557 PMANAGER_HANDLE hManager
;
2559 DWORD dwError
= ERROR_SUCCESS
;
2561 DPRINT("ROpenServiceW() called\n");
2562 DPRINT("hSCManager = %p\n", hSCManager
);
2563 DPRINT("lpServiceName = %p\n", lpServiceName
);
2564 DPRINT("lpServiceName: %S\n", lpServiceName
);
2565 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2568 return ERROR_SHUTDOWN_IN_PROGRESS
;
2570 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2571 if (hManager
== NULL
)
2573 DPRINT1("Invalid service manager handle!\n");
2574 return ERROR_INVALID_HANDLE
;
2577 if (!lpServiceHandle
)
2578 return ERROR_INVALID_PARAMETER
;
2581 return ERROR_INVALID_ADDRESS
;
2583 /* Lock the service database exclusive */
2584 ScmLockDatabaseExclusive();
2586 /* Get service database entry */
2587 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2588 if (lpService
== NULL
)
2590 DPRINT("Could not find a service!\n");
2591 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
2595 /* Create a service handle */
2596 dwError
= ScmCreateServiceHandle(lpService
,
2598 if (dwError
!= ERROR_SUCCESS
)
2600 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2604 /* Check the desired access */
2605 dwError
= ScmCheckAccess(hHandle
,
2607 if (dwError
!= ERROR_SUCCESS
)
2609 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2610 HeapFree(GetProcessHeap(), 0, hHandle
);
2614 lpService
->dwRefCount
++;
2615 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2617 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2618 DPRINT("*hService = %p\n", *lpServiceHandle
);
2621 /* Unlock the service database */
2622 ScmUnlockDatabase();
2624 DPRINT("ROpenServiceW() done\n");
2631 DWORD
RQueryServiceConfigW(
2632 SC_RPC_HANDLE hService
,
2633 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2635 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2637 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2638 DWORD dwError
= ERROR_SUCCESS
;
2639 PSERVICE_HANDLE hSvc
;
2640 PSERVICE lpService
= NULL
;
2641 HKEY hServiceKey
= NULL
;
2642 LPWSTR lpImagePath
= NULL
;
2643 LPWSTR lpServiceStartName
= NULL
;
2644 LPWSTR lpDependencies
= NULL
;
2645 DWORD dwDependenciesLength
= 0;
2646 DWORD dwRequiredSize
;
2647 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2648 WCHAR lpEmptyString
[] = {0,0};
2651 DPRINT("RQueryServiceConfigW() called\n");
2654 return ERROR_SHUTDOWN_IN_PROGRESS
;
2656 hSvc
= ScmGetServiceFromHandle(hService
);
2659 DPRINT1("Invalid service handle!\n");
2660 return ERROR_INVALID_HANDLE
;
2663 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2664 SERVICE_QUERY_CONFIG
))
2666 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2667 return ERROR_ACCESS_DENIED
;
2670 lpService
= hSvc
->ServiceEntry
;
2671 if (lpService
== NULL
)
2673 DPRINT("lpService == NULL!\n");
2674 return ERROR_INVALID_HANDLE
;
2677 /* Lock the service database shared */
2678 ScmLockDatabaseShared();
2680 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2683 if (dwError
!= ERROR_SUCCESS
)
2686 /* Read the image path */
2687 dwError
= ScmReadString(hServiceKey
,
2690 if (dwError
!= ERROR_SUCCESS
)
2693 /* Read the service start name */
2694 ScmReadString(hServiceKey
,
2696 &lpServiceStartName
);
2698 /* Read the dependencies */
2699 ScmReadDependencies(hServiceKey
,
2701 &dwDependenciesLength
);
2703 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2705 if (lpImagePath
!= NULL
)
2706 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2708 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2710 if (lpService
->lpGroup
!= NULL
)
2711 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2713 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2715 if (lpDependencies
!= NULL
)
2716 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2718 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2720 if (lpServiceStartName
!= NULL
)
2721 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2723 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2725 if (lpService
->lpDisplayName
!= NULL
)
2726 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2728 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2730 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2732 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2736 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2737 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2738 lpConfig
->dwStartType
= lpService
->dwStartType
;
2739 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2740 lpConfig
->dwTagId
= lpService
->dwTag
;
2742 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2744 /* Append the image path */
2745 if (lpImagePath
!= NULL
)
2747 wcscpy(lpStr
, lpImagePath
);
2751 wcscpy(lpStr
, lpEmptyString
);
2754 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2755 lpStr
+= (wcslen(lpStr
) + 1);
2757 /* Append the group name */
2758 if (lpService
->lpGroup
!= NULL
)
2760 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2764 wcscpy(lpStr
, lpEmptyString
);
2767 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2768 lpStr
+= (wcslen(lpStr
) + 1);
2770 /* Append Dependencies */
2771 if (lpDependencies
!= NULL
)
2775 dwDependenciesLength
* sizeof(WCHAR
));
2779 wcscpy(lpStr
, lpEmptyString
);
2782 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2783 if (lpDependencies
!= NULL
)
2784 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2786 lpStr
+= (wcslen(lpStr
) + 1);
2788 /* Append the service start name */
2789 if (lpServiceStartName
!= NULL
)
2791 wcscpy(lpStr
, lpServiceStartName
);
2795 wcscpy(lpStr
, lpEmptyString
);
2798 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2799 lpStr
+= (wcslen(lpStr
) + 1);
2801 /* Append the display name */
2802 if (lpService
->lpDisplayName
!= NULL
)
2804 wcscpy(lpStr
, lpService
->lpDisplayName
);
2808 wcscpy(lpStr
, lpEmptyString
);
2811 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2814 if (pcbBytesNeeded
!= NULL
)
2815 *pcbBytesNeeded
= dwRequiredSize
;
2818 /* Unlock the service database */
2819 ScmUnlockDatabase();
2821 if (lpImagePath
!= NULL
)
2822 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2824 if (lpServiceStartName
!= NULL
)
2825 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2827 if (lpDependencies
!= NULL
)
2828 HeapFree(GetProcessHeap(), 0, lpDependencies
);
2830 if (hServiceKey
!= NULL
)
2831 RegCloseKey(hServiceKey
);
2833 DPRINT("RQueryServiceConfigW() done\n");
2840 DWORD
RQueryServiceLockStatusW(
2841 SC_RPC_HANDLE hSCManager
,
2842 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2844 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2847 return ERROR_CALL_NOT_IMPLEMENTED
;
2852 DWORD
RStartServiceW(
2853 SC_RPC_HANDLE hService
,
2855 LPSTRING_PTRSW argv
)
2857 DWORD dwError
= ERROR_SUCCESS
;
2858 PSERVICE_HANDLE hSvc
;
2859 PSERVICE lpService
= NULL
;
2861 DPRINT("RStartServiceW() called\n");
2864 return ERROR_SHUTDOWN_IN_PROGRESS
;
2866 hSvc
= ScmGetServiceFromHandle(hService
);
2869 DPRINT1("Invalid service handle!\n");
2870 return ERROR_INVALID_HANDLE
;
2873 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2876 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2877 return ERROR_ACCESS_DENIED
;
2880 lpService
= hSvc
->ServiceEntry
;
2881 if (lpService
== NULL
)
2883 DPRINT("lpService == NULL!\n");
2884 return ERROR_INVALID_HANDLE
;
2887 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2888 return ERROR_SERVICE_DISABLED
;
2890 if (lpService
->bDeleted
)
2891 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2898 /* Start the service */
2899 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2906 DWORD
RGetServiceDisplayNameW(
2907 SC_RPC_HANDLE hSCManager
,
2908 LPCWSTR lpServiceName
,
2909 LPWSTR lpDisplayName
,
2912 // PMANAGER_HANDLE hManager;
2917 DPRINT("RGetServiceDisplayNameW() called\n");
2918 DPRINT("hSCManager = %p\n", hSCManager
);
2919 DPRINT("lpServiceName: %S\n", lpServiceName
);
2920 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2921 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2923 // hManager = (PMANAGER_HANDLE)hSCManager;
2924 // if (hManager->Handle.Tag != MANAGER_TAG)
2926 // DPRINT("Invalid manager handle!\n");
2927 // return ERROR_INVALID_HANDLE;
2930 /* Get service database entry */
2931 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2932 if (lpService
== NULL
)
2934 DPRINT("Could not find a service!\n");
2936 /* If the service could not be found and lpcchBuffer is less than 2, windows
2937 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2938 if (*lpcchBuffer
< 2)
2941 if (lpDisplayName
!= NULL
)
2943 *lpDisplayName
= '\0';
2947 return ERROR_SERVICE_DOES_NOT_EXIST
;
2950 if (!lpService
->lpDisplayName
)
2952 dwLength
= wcslen(lpService
->lpServiceName
);
2954 if (lpDisplayName
!= NULL
&&
2955 *lpcchBuffer
> dwLength
)
2957 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2962 dwLength
= wcslen(lpService
->lpDisplayName
);
2964 if (lpDisplayName
!= NULL
&&
2965 *lpcchBuffer
> dwLength
)
2967 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2971 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2973 *lpcchBuffer
= dwLength
;
2980 DWORD
RGetServiceKeyNameW(
2981 SC_RPC_HANDLE hSCManager
,
2982 LPCWSTR lpDisplayName
,
2983 LPWSTR lpServiceName
,
2986 // PMANAGER_HANDLE hManager;
2991 DPRINT("RGetServiceKeyNameW() called\n");
2992 DPRINT("hSCManager = %p\n", hSCManager
);
2993 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2994 DPRINT("lpServiceName: %p\n", lpServiceName
);
2995 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2997 // hManager = (PMANAGER_HANDLE)hSCManager;
2998 // if (hManager->Handle.Tag != MANAGER_TAG)
3000 // DPRINT("Invalid manager handle!\n");
3001 // return ERROR_INVALID_HANDLE;
3004 /* Get service database entry */
3005 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
3006 if (lpService
== NULL
)
3008 DPRINT("Could not find a service!\n");
3010 /* If the service could not be found and lpcchBuffer is less than 2, windows
3011 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3012 if (*lpcchBuffer
< 2)
3015 if (lpServiceName
!= NULL
)
3017 *lpServiceName
= '\0';
3021 return ERROR_SERVICE_DOES_NOT_EXIST
;
3024 dwLength
= wcslen(lpService
->lpServiceName
);
3026 if (lpServiceName
!= NULL
&&
3027 *lpcchBuffer
> dwLength
)
3029 wcscpy(lpServiceName
, lpService
->lpServiceName
);
3030 *lpcchBuffer
= dwLength
;
3031 return ERROR_SUCCESS
;
3034 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3036 *lpcchBuffer
= dwLength
;
3043 DWORD
RI_ScSetServiceBitsA(
3044 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3045 DWORD dwServiceBits
,
3047 int bUpdateImmediately
,
3051 return ERROR_CALL_NOT_IMPLEMENTED
;
3056 DWORD
RChangeServiceConfigA(
3057 SC_RPC_HANDLE hService
,
3058 DWORD dwServiceType
,
3060 DWORD dwErrorControl
,
3061 LPSTR lpBinaryPathName
,
3062 LPSTR lpLoadOrderGroup
,
3064 LPSTR lpDependencies
,
3066 LPSTR lpServiceStartName
,
3069 LPSTR lpDisplayName
)
3071 DWORD dwError
= ERROR_SUCCESS
;
3072 PSERVICE_HANDLE hSvc
;
3073 PSERVICE lpService
= NULL
;
3074 HKEY hServiceKey
= NULL
;
3075 LPWSTR lpDisplayNameW
= NULL
;
3076 // LPWSTR lpBinaryPathNameW = NULL;
3077 LPWSTR lpLoadOrderGroupW
= NULL
;
3078 LPWSTR lpDependenciesW
= NULL
;
3079 // LPWSTR lpPasswordW = NULL;
3081 DPRINT("RChangeServiceConfigA() called\n");
3082 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3083 DPRINT("dwStartType = %lu\n", dwStartType
);
3084 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3085 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3086 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3087 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3090 return ERROR_SHUTDOWN_IN_PROGRESS
;
3092 hSvc
= ScmGetServiceFromHandle(hService
);
3095 DPRINT1("Invalid service handle!\n");
3096 return ERROR_INVALID_HANDLE
;
3099 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3100 SERVICE_CHANGE_CONFIG
))
3102 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3103 return ERROR_ACCESS_DENIED
;
3106 lpService
= hSvc
->ServiceEntry
;
3107 if (lpService
== NULL
)
3109 DPRINT("lpService == NULL!\n");
3110 return ERROR_INVALID_HANDLE
;
3113 /* Lock the service database exclusively */
3114 ScmLockDatabaseExclusive();
3116 if (lpService
->bDeleted
)
3118 DPRINT("The service has already been marked for delete!\n");
3119 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
3123 /* Open the service key */
3124 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3127 if (dwError
!= ERROR_SUCCESS
)
3130 /* Write service data to the registry */
3132 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3134 /* Set the display name */
3135 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3137 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3138 if (lpDisplayNameW
== NULL
)
3140 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3144 MultiByteToWideChar(CP_ACP
,
3149 strlen(lpDisplayName
) + 1);
3151 RegSetValueExW(hServiceKey
,
3155 (LPBYTE
)lpDisplayNameW
,
3156 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3158 /* Update lpService->lpDisplayName */
3159 if (lpService
->lpDisplayName
)
3160 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3162 lpService
->lpDisplayName
= lpDisplayNameW
;
3165 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3167 /* Set the service type */
3168 dwError
= RegSetValueExW(hServiceKey
,
3172 (LPBYTE
)&dwServiceType
,
3174 if (dwError
!= ERROR_SUCCESS
)
3177 lpService
->Status
.dwServiceType
= dwServiceType
;
3180 if (dwStartType
!= SERVICE_NO_CHANGE
)
3182 /* Set the start value */
3183 dwError
= RegSetValueExW(hServiceKey
,
3187 (LPBYTE
)&dwStartType
,
3189 if (dwError
!= ERROR_SUCCESS
)
3192 lpService
->dwStartType
= dwStartType
;
3195 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3197 /* Set the error control value */
3198 dwError
= RegSetValueExW(hServiceKey
,
3202 (LPBYTE
)&dwErrorControl
,
3204 if (dwError
!= ERROR_SUCCESS
)
3207 lpService
->dwErrorControl
= dwErrorControl
;
3211 /* FIXME: set the new ImagePath value */
3213 /* Set the image path */
3214 if (dwServiceType
& SERVICE_WIN32
)
3216 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3218 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3219 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, strlen(lpBinaryPathName
)+1);
3220 dwError
= RegSetValueExW(hServiceKey
,
3224 (LPBYTE
)lpBinaryPathNameW
,
3225 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3226 if (dwError
!= ERROR_SUCCESS
)
3230 else if (dwServiceType
& SERVICE_DRIVER
)
3232 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3234 dwError
= RegSetValueExW(hServiceKey
,
3238 (LPBYTE
)lpImagePath
,
3239 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3240 if (dwError
!= ERROR_SUCCESS
)
3246 /* Set the group name */
3247 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3249 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3251 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3252 if (lpLoadOrderGroupW
== NULL
)
3254 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3258 MultiByteToWideChar(CP_ACP
,
3263 strlen(lpLoadOrderGroup
) + 1);
3265 dwError
= RegSetValueExW(hServiceKey
,
3269 (LPBYTE
)lpLoadOrderGroupW
,
3270 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3271 if (dwError
!= ERROR_SUCCESS
)
3273 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3277 dwError
= ScmSetServiceGroup(lpService
,
3280 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3282 if (dwError
!= ERROR_SUCCESS
)
3286 if (lpdwTagId
!= NULL
)
3288 dwError
= ScmAssignNewTag(lpService
);
3289 if (dwError
!= ERROR_SUCCESS
)
3292 dwError
= RegSetValueExW(hServiceKey
,
3296 (LPBYTE
)&lpService
->dwTag
,
3298 if (dwError
!= ERROR_SUCCESS
)
3301 *lpdwTagId
= lpService
->dwTag
;
3304 /* Write dependencies */
3305 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3307 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3309 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3310 if (lpDependenciesW
== NULL
)
3312 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3316 MultiByteToWideChar(CP_ACP
,
3321 strlen(lpDependencies
) + 1);
3323 dwError
= ScmWriteDependencies(hServiceKey
,
3324 (LPWSTR
)lpDependenciesW
,
3327 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3330 if (lpPassword
!= NULL
)
3332 /* FIXME: Write password */
3336 /* Unlock the service database */
3337 ScmUnlockDatabase();
3339 if (hServiceKey
!= NULL
)
3340 RegCloseKey(hServiceKey
);
3342 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3349 DWORD
RCreateServiceA(
3350 SC_RPC_HANDLE hSCManager
,
3351 LPSTR lpServiceName
,
3352 LPSTR lpDisplayName
,
3353 DWORD dwDesiredAccess
,
3354 DWORD dwServiceType
,
3356 DWORD dwErrorControl
,
3357 LPSTR lpBinaryPathName
,
3358 LPSTR lpLoadOrderGroup
,
3360 LPBYTE lpDependencies
,
3362 LPSTR lpServiceStartName
,
3365 LPSC_RPC_HANDLE lpServiceHandle
)
3367 DWORD dwError
= ERROR_SUCCESS
;
3368 LPWSTR lpServiceNameW
= NULL
;
3369 LPWSTR lpDisplayNameW
= NULL
;
3370 LPWSTR lpBinaryPathNameW
= NULL
;
3371 LPWSTR lpLoadOrderGroupW
= NULL
;
3372 LPWSTR lpDependenciesW
= NULL
;
3373 LPWSTR lpServiceStartNameW
= NULL
;
3374 DWORD dwDependenciesLength
= 0;
3381 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3382 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3383 if (!lpServiceNameW
)
3385 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3388 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3393 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3394 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3395 if (!lpDisplayNameW
)
3397 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3400 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3403 if (lpBinaryPathName
)
3405 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3406 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3407 if (!lpBinaryPathNameW
)
3409 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3412 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3415 if (lpLoadOrderGroup
)
3417 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3418 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3419 if (!lpLoadOrderGroupW
)
3421 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3424 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3429 lpStr
= (LPSTR
)lpDependencies
;
3432 dwLength
= strlen(lpStr
) + 1;
3433 dwDependenciesLength
+= dwLength
;
3434 lpStr
= lpStr
+ dwLength
;
3436 dwDependenciesLength
++;
3438 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3439 if (!lpDependenciesW
)
3441 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3444 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3447 if (lpServiceStartName
)
3449 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3450 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3451 if (!lpServiceStartNameW
)
3453 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3456 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3459 dwError
= RCreateServiceW(hSCManager
,
3469 (LPBYTE
)lpDependenciesW
,
3470 dwDependenciesLength
,
3471 lpServiceStartNameW
,
3477 if (lpServiceNameW
!=NULL
)
3478 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3480 if (lpDisplayNameW
!= NULL
)
3481 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3483 if (lpBinaryPathNameW
!= NULL
)
3484 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3486 if (lpLoadOrderGroupW
!= NULL
)
3487 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3489 if (lpDependenciesW
!= NULL
)
3490 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3492 if (lpServiceStartNameW
!= NULL
)
3493 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3500 DWORD
REnumDependentServicesA(
3501 SC_RPC_HANDLE hService
,
3502 DWORD dwServiceState
,
3505 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3506 LPBOUNDED_DWORD_256K lpServicesReturned
)
3508 DWORD dwError
= ERROR_SUCCESS
;
3509 DWORD dwServicesReturned
= 0;
3510 DWORD dwServiceCount
;
3511 HKEY hServicesKey
= NULL
;
3512 PSERVICE_HANDLE hSvc
;
3513 PSERVICE lpService
= NULL
;
3514 PSERVICE
*lpServicesArray
= NULL
;
3515 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3518 *pcbBytesNeeded
= 0;
3519 *lpServicesReturned
= 0;
3521 DPRINT("REnumDependentServicesA() called\n");
3523 hSvc
= ScmGetServiceFromHandle(hService
);
3526 DPRINT1("Invalid service handle!\n");
3527 return ERROR_INVALID_HANDLE
;
3530 lpService
= hSvc
->ServiceEntry
;
3532 /* Check access rights */
3533 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3534 SC_MANAGER_ENUMERATE_SERVICE
))
3536 DPRINT("Insufficient access rights! 0x%lx\n",
3537 hSvc
->Handle
.DesiredAccess
);
3538 return ERROR_ACCESS_DENIED
;
3541 /* Open the Services Reg key */
3542 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3543 L
"System\\CurrentControlSet\\Services",
3548 if (dwError
!= ERROR_SUCCESS
)
3551 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3552 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3553 are the same for both. Verified in WINXP. */
3555 /* First determine the bytes needed and get the number of dependent services*/
3556 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3561 &dwServicesReturned
);
3562 if (dwError
!= ERROR_SUCCESS
)
3565 /* If buffer size is less than the bytes needed or pointer is null*/
3566 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3568 dwError
= ERROR_MORE_DATA
;
3572 /* Allocate memory for array of service pointers */
3573 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3575 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3576 if (!lpServicesArray
)
3578 DPRINT("Could not allocate a buffer!!\n");
3579 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3583 dwServicesReturned
= 0;
3584 *pcbBytesNeeded
= 0;
3586 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3591 &dwServicesReturned
);
3592 if (dwError
!= ERROR_SUCCESS
)
3597 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3598 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3600 /* Copy EnumDepenedentService to Buffer */
3601 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3603 lpService
= lpServicesArray
[dwServiceCount
];
3605 /* Copy the status info */
3606 memcpy(&lpServicesPtr
->ServiceStatus
,
3608 sizeof(SERVICE_STATUS
));
3610 /* Copy display name */
3611 WideCharToMultiByte(CP_ACP
,
3613 lpService
->lpDisplayName
,
3616 wcslen(lpService
->lpDisplayName
),
3619 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3620 lpStr
+= strlen(lpStr
) + 1;
3622 /* Copy service name */
3623 WideCharToMultiByte(CP_ACP
,
3625 lpService
->lpServiceName
,
3628 wcslen(lpService
->lpServiceName
),
3631 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3632 lpStr
+= strlen(lpStr
) + 1;
3637 *lpServicesReturned
= dwServicesReturned
;
3640 if (lpServicesArray
)
3641 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3643 RegCloseKey(hServicesKey
);
3645 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3652 DWORD
REnumServicesStatusA(
3653 SC_RPC_HANDLE hSCManager
,
3654 DWORD dwServiceType
,
3655 DWORD dwServiceState
,
3658 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3659 LPBOUNDED_DWORD_256K lpServicesReturned
,
3660 LPBOUNDED_DWORD_256K lpResumeHandle
)
3662 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3663 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3664 LPWSTR lpStringPtrW
;
3667 DWORD dwServiceCount
;
3669 DPRINT("REnumServicesStatusA() called\n");
3671 if ((dwBufSize
> 0) && (lpBuffer
))
3673 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3676 DPRINT("Failed to allocate buffer!\n");
3677 return ERROR_NOT_ENOUGH_MEMORY
;
3681 dwError
= REnumServicesStatusW(hSCManager
,
3684 (LPBYTE
)lpStatusPtrW
,
3690 /* if no services were returned then we are Done */
3691 if (*lpServicesReturned
== 0)
3694 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3695 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3696 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3697 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3698 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3700 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3702 /* Copy the service name */
3703 WideCharToMultiByte(CP_ACP
,
3708 wcslen(lpStringPtrW
),
3712 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3713 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3714 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3716 /* Copy the display name */
3717 WideCharToMultiByte(CP_ACP
,
3722 wcslen(lpStringPtrW
),
3726 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3727 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3728 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3730 /* Copy the status information */
3731 memcpy(&lpStatusPtrA
->ServiceStatus
,
3732 &lpStatusPtrW
->ServiceStatus
,
3733 sizeof(SERVICE_STATUS
));
3740 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3742 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3749 DWORD
ROpenSCManagerA(
3750 LPSTR lpMachineName
,
3751 LPSTR lpDatabaseName
,
3752 DWORD dwDesiredAccess
,
3753 LPSC_RPC_HANDLE lpScHandle
)
3755 UNICODE_STRING MachineName
;
3756 UNICODE_STRING DatabaseName
;
3759 DPRINT("ROpenSCManagerA() called\n");
3762 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3766 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3769 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3770 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3775 RtlFreeUnicodeString(&MachineName
);
3778 RtlFreeUnicodeString(&DatabaseName
);
3785 DWORD
ROpenServiceA(
3786 SC_RPC_HANDLE hSCManager
,
3787 LPSTR lpServiceName
,
3788 DWORD dwDesiredAccess
,
3789 LPSC_RPC_HANDLE lpServiceHandle
)
3791 UNICODE_STRING ServiceName
;
3794 DPRINT("ROpenServiceA() called\n");
3797 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3800 dwError
= ROpenServiceW(hSCManager
,
3801 lpServiceName
? ServiceName
.Buffer
: NULL
,
3806 RtlFreeUnicodeString(&ServiceName
);
3813 DWORD
RQueryServiceConfigA(
3814 SC_RPC_HANDLE hService
,
3815 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3817 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3819 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3820 DWORD dwError
= ERROR_SUCCESS
;
3821 PSERVICE_HANDLE hSvc
;
3822 PSERVICE lpService
= NULL
;
3823 HKEY hServiceKey
= NULL
;
3824 LPWSTR lpImagePath
= NULL
;
3825 LPWSTR lpServiceStartName
= NULL
;
3826 LPWSTR lpDependencies
= NULL
;
3827 DWORD dwDependenciesLength
= 0;
3828 DWORD dwRequiredSize
;
3829 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3830 CHAR lpEmptyString
[]={0,0};
3833 DPRINT("RQueryServiceConfigA() called\n");
3836 return ERROR_SHUTDOWN_IN_PROGRESS
;
3838 hSvc
= ScmGetServiceFromHandle(hService
);
3841 DPRINT1("Invalid service handle!\n");
3842 return ERROR_INVALID_HANDLE
;
3845 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3846 SERVICE_QUERY_CONFIG
))
3848 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3849 return ERROR_ACCESS_DENIED
;
3852 lpService
= hSvc
->ServiceEntry
;
3853 if (lpService
== NULL
)
3855 DPRINT("lpService == NULL!\n");
3856 return ERROR_INVALID_HANDLE
;
3859 /* Lock the service database shared */
3860 ScmLockDatabaseShared();
3862 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3865 if (dwError
!= ERROR_SUCCESS
)
3868 /* Read the image path */
3869 dwError
= ScmReadString(hServiceKey
,
3872 if (dwError
!= ERROR_SUCCESS
)
3875 /* Read the service start name */
3876 ScmReadString(hServiceKey
,
3878 &lpServiceStartName
);
3880 /* Read the dependencies */
3881 ScmReadDependencies(hServiceKey
,
3883 &dwDependenciesLength
);
3885 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3887 if (lpImagePath
!= NULL
)
3888 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3890 dwRequiredSize
+= 2;
3892 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3893 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3895 dwRequiredSize
+= 2;
3897 /* Add Dependencies length */
3898 if (lpDependencies
!= NULL
)
3899 dwRequiredSize
+= dwDependenciesLength
;
3901 dwRequiredSize
+= 2;
3903 if (lpServiceStartName
!= NULL
)
3904 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3906 dwRequiredSize
+= 2;
3908 if (lpService
->lpDisplayName
!= NULL
)
3909 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3911 dwRequiredSize
+= 2;
3913 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3915 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3919 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3920 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3921 lpConfig
->dwStartType
= lpService
->dwStartType
;
3922 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3923 lpConfig
->dwTagId
= lpService
->dwTag
;
3925 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3927 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3932 WideCharToMultiByte(CP_ACP
,
3937 wcslen(lpImagePath
) + 1,
3943 strcpy(lpStr
, lpEmptyString
);
3946 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3947 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3949 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
3951 WideCharToMultiByte(CP_ACP
,
3953 lpService
->lpGroup
->lpGroupName
,
3956 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
3962 strcpy(lpStr
, lpEmptyString
);
3965 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3966 lpStr
+= (strlen(lpStr
) + 1);
3968 /* Append Dependencies */
3971 WideCharToMultiByte(CP_ACP
,
3974 dwDependenciesLength
,
3976 dwDependenciesLength
,
3982 strcpy(lpStr
, lpEmptyString
);
3985 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3987 lpStr
+= dwDependenciesLength
;
3989 lpStr
+= (strlen(lpStr
) + 1);
3991 if (lpServiceStartName
)
3993 WideCharToMultiByte(CP_ACP
,
3998 wcslen(lpServiceStartName
) + 1,
4004 strcpy(lpStr
, lpEmptyString
);
4007 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4008 lpStr
+= (strlen(lpStr
) + 1);
4010 if (lpService
->lpDisplayName
)
4012 WideCharToMultiByte(CP_ACP
,
4014 lpService
->lpDisplayName
,
4017 wcslen(lpService
->lpDisplayName
) + 1,
4023 strcpy(lpStr
, lpEmptyString
);
4026 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4029 if (pcbBytesNeeded
!= NULL
)
4030 *pcbBytesNeeded
= dwRequiredSize
;
4033 /* Unlock the service database */
4034 ScmUnlockDatabase();
4036 if (lpImagePath
!= NULL
)
4037 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4039 if (lpServiceStartName
!= NULL
)
4040 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4042 if (lpDependencies
!= NULL
)
4043 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4045 if (hServiceKey
!= NULL
)
4046 RegCloseKey(hServiceKey
);
4048 DPRINT("RQueryServiceConfigA() done\n");
4055 DWORD
RQueryServiceLockStatusA(
4056 SC_RPC_HANDLE hSCManager
,
4057 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
4059 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4062 return ERROR_CALL_NOT_IMPLEMENTED
;
4067 DWORD
RStartServiceA(
4068 SC_RPC_HANDLE hService
,
4070 LPSTRING_PTRSA argv
)
4072 DWORD dwError
= ERROR_SUCCESS
;
4073 PSERVICE_HANDLE hSvc
;
4074 PSERVICE lpService
= NULL
;
4076 DPRINT("RStartServiceA() called\n");
4079 return ERROR_SHUTDOWN_IN_PROGRESS
;
4081 hSvc
= ScmGetServiceFromHandle(hService
);
4084 DPRINT1("Invalid service handle!\n");
4085 return ERROR_INVALID_HANDLE
;
4088 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4091 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4092 return ERROR_ACCESS_DENIED
;
4095 lpService
= hSvc
->ServiceEntry
;
4096 if (lpService
== NULL
)
4098 DPRINT("lpService == NULL!\n");
4099 return ERROR_INVALID_HANDLE
;
4102 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4103 return ERROR_SERVICE_DISABLED
;
4105 if (lpService
->bDeleted
)
4106 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4108 /* FIXME: Convert argument vector to Unicode */
4110 /* Start the service */
4111 dwError
= ScmStartService(lpService
, 0, NULL
);
4113 /* FIXME: Free argument vector */
4120 DWORD
RGetServiceDisplayNameA(
4121 SC_RPC_HANDLE hSCManager
,
4122 LPCSTR lpServiceName
,
4123 LPSTR lpDisplayName
,
4124 LPBOUNDED_DWORD_4K lpcchBuffer
)
4126 // PMANAGER_HANDLE hManager;
4127 PSERVICE lpService
= NULL
;
4130 LPWSTR lpServiceNameW
;
4132 DPRINT("RGetServiceDisplayNameA() called\n");
4133 DPRINT("hSCManager = %p\n", hSCManager
);
4134 DPRINT("lpServiceName: %s\n", lpServiceName
);
4135 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4136 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4138 // hManager = (PMANAGER_HANDLE)hSCManager;
4139 // if (hManager->Handle.Tag != MANAGER_TAG)
4141 // DPRINT("Invalid manager handle!\n");
4142 // return ERROR_INVALID_HANDLE;
4145 if (lpServiceName
!= NULL
)
4147 dwLength
= strlen(lpServiceName
) + 1;
4148 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4150 dwLength
* sizeof(WCHAR
));
4151 if (!lpServiceNameW
)
4152 return ERROR_NOT_ENOUGH_MEMORY
;
4154 MultiByteToWideChar(CP_ACP
,
4161 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4163 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4166 if (lpService
== NULL
)
4168 DPRINT("Could not find a service!\n");
4170 /* If the service could not be found and lpcchBuffer is 0, windows
4171 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4172 if (*lpcchBuffer
== 0)
4175 if (lpDisplayName
!= NULL
)
4177 *lpDisplayName
= '\0';
4180 return ERROR_SERVICE_DOES_NOT_EXIST
;
4183 if (!lpService
->lpDisplayName
)
4185 dwLength
= wcslen(lpService
->lpServiceName
);
4186 if (lpDisplayName
!= NULL
&&
4187 *lpcchBuffer
> dwLength
)
4189 WideCharToMultiByte(CP_ACP
,
4191 lpService
->lpServiceName
,
4192 wcslen(lpService
->lpServiceName
),
4197 return ERROR_SUCCESS
;
4202 dwLength
= wcslen(lpService
->lpDisplayName
);
4203 if (lpDisplayName
!= NULL
&&
4204 *lpcchBuffer
> dwLength
)
4206 WideCharToMultiByte(CP_ACP
,
4208 lpService
->lpDisplayName
,
4209 wcslen(lpService
->lpDisplayName
),
4214 return ERROR_SUCCESS
;
4218 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4220 *lpcchBuffer
= dwLength
* 2;
4227 DWORD
RGetServiceKeyNameA(
4228 SC_RPC_HANDLE hSCManager
,
4229 LPCSTR lpDisplayName
,
4230 LPSTR lpServiceName
,
4231 LPBOUNDED_DWORD_4K lpcchBuffer
)
4236 LPWSTR lpDisplayNameW
;
4238 DPRINT("RGetServiceKeyNameA() called\n");
4239 DPRINT("hSCManager = %p\n", hSCManager
);
4240 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4241 DPRINT("lpServiceName: %p\n", lpServiceName
);
4242 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4244 dwLength
= strlen(lpDisplayName
) + 1;
4245 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4247 dwLength
* sizeof(WCHAR
));
4248 if (!lpDisplayNameW
)
4249 return ERROR_NOT_ENOUGH_MEMORY
;
4251 MultiByteToWideChar(CP_ACP
,
4258 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4260 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4262 if (lpService
== NULL
)
4264 DPRINT("Could not find the service!\n");
4266 /* If the service could not be found and lpcchBuffer is 0,
4267 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4268 if (*lpcchBuffer
== 0)
4271 if (lpServiceName
!= NULL
)
4273 *lpServiceName
= '\0';
4277 return ERROR_SERVICE_DOES_NOT_EXIST
;
4280 dwLength
= wcslen(lpService
->lpServiceName
);
4281 if (lpServiceName
!= NULL
&&
4282 *lpcchBuffer
> dwLength
)
4284 WideCharToMultiByte(CP_ACP
,
4286 lpService
->lpServiceName
,
4287 wcslen(lpService
->lpServiceName
),
4292 return ERROR_SUCCESS
;
4295 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4297 *lpcchBuffer
= dwLength
* 2;
4304 DWORD
RI_ScGetCurrentGroupStateW(
4305 SC_RPC_HANDLE hSCManager
,
4306 LPWSTR lpLoadOrderGroup
,
4310 return ERROR_CALL_NOT_IMPLEMENTED
;
4315 DWORD
REnumServiceGroupW(
4316 SC_RPC_HANDLE hSCManager
,
4317 DWORD dwServiceType
,
4318 DWORD dwServiceState
,
4321 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4322 LPBOUNDED_DWORD_256K lpServicesReturned
,
4323 LPBOUNDED_DWORD_256K lpResumeIndex
,
4324 LPCWSTR pszGroupName
)
4327 return ERROR_CALL_NOT_IMPLEMENTED
;
4332 // WARNING: This function is untested
4335 DWORD
RChangeServiceConfig2A(
4336 SC_RPC_HANDLE hService
,
4337 SC_RPC_CONFIG_INFOA Info
)
4339 SC_RPC_CONFIG_INFOW InfoW
;
4340 DWORD dwRet
, dwLength
;
4343 DPRINT("RChangeServiceConfig2A() called\n");
4344 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4346 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4348 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4350 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4351 LPSERVICE_DESCRIPTIONA lpServiceDescriptonA
;
4353 lpServiceDescriptonA
= Info
.psd
;
4355 ///if (lpServiceDescriptonA &&
4356 ///lpServiceDescriptonA->lpDescription)
4358 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4360 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4362 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4363 if (!lpServiceDescriptonW
)
4365 return ERROR_NOT_ENOUGH_MEMORY
;
4368 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4370 MultiByteToWideChar(CP_ACP
,
4374 lpServiceDescriptonW
->lpDescription
,
4377 ptr
= lpServiceDescriptonW
;
4378 InfoW
.psd
= lpServiceDescriptonW
;
4381 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4383 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4384 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4385 DWORD dwRebootLen
= 0;
4386 DWORD dwCommandLen
= 0;
4388 lpServiceFailureActionsA
= Info
.psfa
;
4390 if (lpServiceFailureActionsA
)
4392 if (lpServiceFailureActionsA
->lpRebootMsg
)
4394 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4396 if (lpServiceFailureActionsA
->lpCommand
)
4398 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4400 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4402 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4405 if (!lpServiceFailureActionsW
)
4407 return ERROR_NOT_ENOUGH_MEMORY
;
4410 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4411 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4412 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4414 if (lpServiceFailureActionsA
->lpRebootMsg
)
4416 MultiByteToWideChar(CP_ACP
,
4418 lpServiceFailureActionsA
->lpRebootMsg
,
4420 lpServiceFailureActionsW
->lpRebootMsg
,
4424 if (lpServiceFailureActionsA
->lpCommand
)
4426 MultiByteToWideChar(CP_ACP
,
4428 lpServiceFailureActionsA
->lpCommand
,
4430 lpServiceFailureActionsW
->lpCommand
,
4434 ptr
= lpServiceFailureActionsW
;
4438 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4440 HeapFree(GetProcessHeap(), 0, ptr
);
4447 DWORD
RChangeServiceConfig2W(
4448 SC_RPC_HANDLE hService
,
4449 SC_RPC_CONFIG_INFOW Info
)
4451 DWORD dwError
= ERROR_SUCCESS
;
4452 PSERVICE_HANDLE hSvc
;
4453 PSERVICE lpService
= NULL
;
4454 HKEY hServiceKey
= NULL
;
4456 DPRINT("RChangeServiceConfig2W() called\n");
4457 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4460 return ERROR_SHUTDOWN_IN_PROGRESS
;
4462 hSvc
= ScmGetServiceFromHandle(hService
);
4465 DPRINT1("Invalid service handle!\n");
4466 return ERROR_INVALID_HANDLE
;
4469 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4470 SERVICE_CHANGE_CONFIG
))
4472 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4473 return ERROR_ACCESS_DENIED
;
4476 lpService
= hSvc
->ServiceEntry
;
4477 if (lpService
== NULL
)
4479 DPRINT("lpService == NULL!\n");
4480 return ERROR_INVALID_HANDLE
;
4483 /* Lock the service database exclusively */
4484 ScmLockDatabaseExclusive();
4486 if (lpService
->bDeleted
)
4488 DPRINT("The service has already been marked for delete!\n");
4489 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
4493 /* Open the service key */
4494 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4497 if (dwError
!= ERROR_SUCCESS
)
4500 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4502 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4504 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4505 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4507 if (lpServiceDescription
!= NULL
&&
4508 lpServiceDescription
->lpDescription
!= NULL
)
4510 DPRINT("Setting value %S\n", lpServiceDescription
->lpDescription
);
4511 dwError
= RegSetValueExW(hServiceKey
,
4515 (LPBYTE
)lpServiceDescription
->lpDescription
,
4516 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4517 if (dwError
!= ERROR_SUCCESS
)
4521 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4524 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4529 /* Unlock the service database */
4530 ScmUnlockDatabase();
4532 if (hServiceKey
!= NULL
)
4533 RegCloseKey(hServiceKey
);
4535 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4542 DWORD
RQueryServiceConfig2A(
4543 SC_RPC_HANDLE hService
,
4547 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4549 DWORD dwError
= ERROR_SUCCESS
;
4550 PSERVICE_HANDLE hSvc
;
4551 PSERVICE lpService
= NULL
;
4552 HKEY hServiceKey
= NULL
;
4553 LPWSTR lpDescriptionW
= NULL
;
4554 LPSTR lpDescription
= NULL
;
4556 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4557 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4560 return ERROR_INVALID_ADDRESS
;
4563 return ERROR_SHUTDOWN_IN_PROGRESS
;
4565 hSvc
= ScmGetServiceFromHandle(hService
);
4568 DPRINT1("Invalid service handle!\n");
4569 return ERROR_INVALID_HANDLE
;
4572 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4573 SERVICE_QUERY_CONFIG
))
4575 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4576 return ERROR_ACCESS_DENIED
;
4579 lpService
= hSvc
->ServiceEntry
;
4580 if (lpService
== NULL
)
4582 DPRINT("lpService == NULL!\n");
4583 return ERROR_INVALID_HANDLE
;
4586 /* Lock the service database shared */
4587 ScmLockDatabaseShared();
4589 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4592 if (dwError
!= ERROR_SUCCESS
)
4595 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4597 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4600 dwError
= ScmReadString(hServiceKey
,
4603 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4606 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4607 if (dwError
== ERROR_SUCCESS
)
4608 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4610 if (cbBufSize
< *pcbBytesNeeded
)
4612 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4616 if (dwError
== ERROR_SUCCESS
)
4618 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4620 WideCharToMultiByte(CP_ACP
,
4625 wcslen(lpDescriptionW
),
4628 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4632 lpServiceDescription
->lpDescription
= NULL
;
4633 dwError
= ERROR_SUCCESS
;
4637 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4640 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4645 /* Unlock the service database */
4646 ScmUnlockDatabase();
4648 if (lpDescription
!= NULL
)
4649 HeapFree(GetProcessHeap(), 0, lpDescription
);
4651 if (hServiceKey
!= NULL
)
4652 RegCloseKey(hServiceKey
);
4654 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4661 DWORD
RQueryServiceConfig2W(
4662 SC_RPC_HANDLE hService
,
4666 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4668 DWORD dwError
= ERROR_SUCCESS
;
4669 PSERVICE_HANDLE hSvc
;
4670 PSERVICE lpService
= NULL
;
4671 HKEY hServiceKey
= NULL
;
4672 DWORD dwRequiredSize
;
4673 LPWSTR lpDescription
= NULL
;
4674 LPWSTR lpFailureCommand
= NULL
;
4675 LPWSTR lpRebootMessage
= NULL
;
4677 DPRINT("RQueryServiceConfig2W() called\n");
4680 return ERROR_INVALID_ADDRESS
;
4683 return ERROR_SHUTDOWN_IN_PROGRESS
;
4685 hSvc
= ScmGetServiceFromHandle(hService
);
4688 DPRINT1("Invalid service handle!\n");
4689 return ERROR_INVALID_HANDLE
;
4692 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4693 SERVICE_QUERY_CONFIG
))
4695 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4696 return ERROR_ACCESS_DENIED
;
4699 lpService
= hSvc
->ServiceEntry
;
4700 if (lpService
== NULL
)
4702 DPRINT("lpService == NULL!\n");
4703 return ERROR_INVALID_HANDLE
;
4706 /* Lock the service database shared */
4707 ScmLockDatabaseShared();
4709 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4712 if (dwError
!= ERROR_SUCCESS
)
4715 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4717 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4720 dwError
= ScmReadString(hServiceKey
,
4723 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4726 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONW
);
4727 if (dwError
== ERROR_SUCCESS
)
4728 *pcbBytesNeeded
+= ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4730 if (cbBufSize
< *pcbBytesNeeded
)
4732 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4736 if (dwError
== ERROR_SUCCESS
)
4738 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4739 wcscpy(lpStr
, lpDescription
);
4740 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4744 lpServiceDescription
->lpDescription
= NULL
;
4745 dwError
= ERROR_SUCCESS
;
4748 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4751 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
4755 dwError
= ScmReadString(hServiceKey
,
4759 dwError
= ScmReadString(hServiceKey
,
4763 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
4765 if (lpFailureCommand
)
4766 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
4768 if (lpRebootMessage
)
4769 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
4771 if (cbBufSize
< dwRequiredSize
)
4773 *pcbBytesNeeded
= dwRequiredSize
;
4774 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4778 lpFailureActions
->cActions
= 0;
4779 lpFailureActions
->dwResetPeriod
= 0;
4780 lpFailureActions
->lpCommand
= NULL
;
4781 lpFailureActions
->lpRebootMsg
= NULL
;
4782 lpFailureActions
->lpsaActions
= NULL
;
4784 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
4785 if (lpRebootMessage
)
4787 wcscpy(lpStr
, lpRebootMessage
);
4788 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
4789 lpStr
+= wcslen(lpRebootMessage
) + 1;
4792 if (lpFailureCommand
)
4794 wcscpy(lpStr
, lpFailureCommand
);
4795 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
4796 lpStr
+= wcslen(lpRebootMessage
) + 1;
4798 dwError
= STATUS_SUCCESS
;
4803 /* Unlock the service database */
4804 ScmUnlockDatabase();
4806 if (lpDescription
!= NULL
)
4807 HeapFree(GetProcessHeap(), 0, lpDescription
);
4809 if (lpRebootMessage
!= NULL
)
4810 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
4812 if (lpFailureCommand
!= NULL
)
4813 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
4815 if (hServiceKey
!= NULL
)
4816 RegCloseKey(hServiceKey
);
4818 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4825 DWORD
RQueryServiceStatusEx(
4826 SC_RPC_HANDLE hService
,
4827 SC_STATUS_TYPE InfoLevel
,
4830 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4832 LPSERVICE_STATUS_PROCESS lpStatus
;
4833 PSERVICE_HANDLE hSvc
;
4836 DPRINT("RQueryServiceStatusEx() called\n");
4839 return ERROR_SHUTDOWN_IN_PROGRESS
;
4841 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4842 return ERROR_INVALID_LEVEL
;
4844 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4846 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4847 return ERROR_INSUFFICIENT_BUFFER
;
4849 hSvc
= ScmGetServiceFromHandle(hService
);
4852 DPRINT1("Invalid service handle!\n");
4853 return ERROR_INVALID_HANDLE
;
4856 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4857 SERVICE_QUERY_STATUS
))
4859 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4860 return ERROR_ACCESS_DENIED
;
4863 lpService
= hSvc
->ServiceEntry
;
4864 if (lpService
== NULL
)
4866 DPRINT("lpService == NULL!\n");
4867 return ERROR_INVALID_HANDLE
;
4870 /* Lock the service database shared */
4871 ScmLockDatabaseShared();
4873 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4875 /* Return service status information */
4876 RtlCopyMemory(lpStatus
,
4878 sizeof(SERVICE_STATUS
));
4880 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
4881 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4883 /* Unlock the service database */
4884 ScmUnlockDatabase();
4886 return ERROR_SUCCESS
;
4891 DWORD
REnumServicesStatusExA(
4892 SC_RPC_HANDLE hSCManager
,
4893 SC_ENUM_TYPE InfoLevel
,
4894 DWORD dwServiceType
,
4895 DWORD dwServiceState
,
4898 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4899 LPBOUNDED_DWORD_256K lpServicesReturned
,
4900 LPBOUNDED_DWORD_256K lpResumeIndex
,
4901 LPCSTR pszGroupName
)
4903 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
4904 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
4905 LPWSTR lpStringPtrW
;
4907 LPWSTR pszGroupNameW
= NULL
;
4909 DWORD dwServiceCount
;
4911 DPRINT("REnumServicesStatusExA() called\n");
4915 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
4918 DPRINT("Failed to allocate buffer!\n");
4919 return ERROR_NOT_ENOUGH_MEMORY
;
4922 MultiByteToWideChar(CP_ACP
,
4927 strlen(pszGroupName
) + 1);
4930 if ((cbBufSize
> 0) && (lpBuffer
))
4932 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
4935 DPRINT("Failed to allocate buffer!\n");
4936 return ERROR_NOT_ENOUGH_MEMORY
;
4940 dwError
= REnumServicesStatusExW(hSCManager
,
4944 (LPBYTE
)lpStatusPtrW
,
4951 /* if no services were returned then we are Done */
4952 if (*lpServicesReturned
== 0)
4955 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
4956 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
4957 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
4958 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
4959 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4961 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
4963 /* Copy the service name */
4964 WideCharToMultiByte(CP_ACP
,
4969 wcslen(lpStringPtrW
),
4973 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4974 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4975 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4977 /* Copy the display name */
4978 WideCharToMultiByte(CP_ACP
,
4983 wcslen(lpStringPtrW
),
4987 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4988 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4989 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4991 /* Copy the status information */
4992 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
4993 &lpStatusPtrW
->ServiceStatusProcess
,
4994 sizeof(SERVICE_STATUS
));
4996 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
4997 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5003 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
5006 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
5008 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
5015 DWORD
REnumServicesStatusExW(
5016 SC_RPC_HANDLE hSCManager
,
5017 SC_ENUM_TYPE InfoLevel
,
5018 DWORD dwServiceType
,
5019 DWORD dwServiceState
,
5022 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5023 LPBOUNDED_DWORD_256K lpServicesReturned
,
5024 LPBOUNDED_DWORD_256K lpResumeIndex
,
5025 LPCWSTR pszGroupName
)
5027 PMANAGER_HANDLE hManager
;
5029 DWORD dwError
= ERROR_SUCCESS
;
5030 PLIST_ENTRY ServiceEntry
;
5031 PSERVICE CurrentService
;
5033 DWORD dwRequiredSize
;
5034 DWORD dwServiceCount
;
5036 DWORD dwLastResumeCount
= 0;
5037 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
5040 DPRINT("REnumServicesStatusExW() called\n");
5043 return ERROR_SHUTDOWN_IN_PROGRESS
;
5045 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
5046 return ERROR_INVALID_LEVEL
;
5048 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
5049 if (hManager
== NULL
)
5051 DPRINT1("Invalid service manager handle!\n");
5052 return ERROR_INVALID_HANDLE
;
5055 *pcbBytesNeeded
= 0;
5056 *lpServicesReturned
= 0;
5058 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
5060 DPRINT("Not a valid Service Type!\n");
5061 return ERROR_INVALID_PARAMETER
;
5064 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
5066 DPRINT("Not a valid Service State!\n");
5067 return ERROR_INVALID_PARAMETER
;
5070 /* Check access rights */
5071 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
5072 SC_MANAGER_ENUMERATE_SERVICE
))
5074 DPRINT("Insufficient access rights! 0x%lx\n",
5075 hManager
->Handle
.DesiredAccess
);
5076 return ERROR_ACCESS_DENIED
;
5080 dwLastResumeCount
= *lpResumeIndex
;
5082 /* FIXME: Lock the service list shared */
5084 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
5085 if (lpService
== NULL
)
5087 dwError
= ERROR_SUCCESS
;
5094 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5095 ServiceEntry
!= &ServiceListHead
;
5096 ServiceEntry
= ServiceEntry
->Flink
)
5098 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5102 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5105 dwState
= SERVICE_ACTIVE
;
5106 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5107 dwState
= SERVICE_INACTIVE
;
5109 if ((dwState
& dwServiceState
) == 0)
5114 if (*pszGroupName
== 0)
5116 if (CurrentService
->lpGroup
!= NULL
)
5121 if ((CurrentService
->lpGroup
== NULL
) ||
5122 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5127 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5128 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5129 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5131 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5133 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5134 dwRequiredSize
+= dwSize
;
5136 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5140 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5146 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5147 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5150 ServiceEntry
!= &ServiceListHead
;
5151 ServiceEntry
= ServiceEntry
->Flink
)
5153 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5157 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5160 dwState
= SERVICE_ACTIVE
;
5161 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5162 dwState
= SERVICE_INACTIVE
;
5164 if ((dwState
& dwServiceState
) == 0)
5169 if (*pszGroupName
== 0)
5171 if (CurrentService
->lpGroup
!= NULL
)
5176 if ((CurrentService
->lpGroup
== NULL
) ||
5177 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5182 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5183 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5184 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5186 dwError
= ERROR_MORE_DATA
;
5189 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5192 *lpResumeIndex
= dwLastResumeCount
;
5194 *lpServicesReturned
= dwServiceCount
;
5195 *pcbBytesNeeded
= dwRequiredSize
;
5197 /* If there was no services that matched */
5198 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5200 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5204 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5205 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5206 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5209 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5210 ServiceEntry
!= &ServiceListHead
;
5211 ServiceEntry
= ServiceEntry
->Flink
)
5213 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5217 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5220 dwState
= SERVICE_ACTIVE
;
5221 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5222 dwState
= SERVICE_INACTIVE
;
5224 if ((dwState
& dwServiceState
) == 0)
5229 if (*pszGroupName
== 0)
5231 if (CurrentService
->lpGroup
!= NULL
)
5236 if ((CurrentService
->lpGroup
== NULL
) ||
5237 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5242 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5243 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5244 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5246 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5248 /* Copy the service name */
5250 CurrentService
->lpServiceName
);
5251 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5252 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5254 /* Copy the display name */
5256 CurrentService
->lpDisplayName
);
5257 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5258 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5260 /* Copy the status information */
5261 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5262 &CurrentService
->Status
,
5263 sizeof(SERVICE_STATUS
));
5264 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
5265 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5268 dwRequiredSize
+= dwSize
;
5278 *pcbBytesNeeded
= 0;
5284 /* FIXME: Unlock the service list */
5286 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5293 DWORD
RSendTSMessage(
5294 handle_t BindingHandle
) /* FIXME */
5297 return ERROR_CALL_NOT_IMPLEMENTED
;
5302 DWORD
RCreateServiceWOW64A(
5303 handle_t BindingHandle
,
5304 LPSTR lpServiceName
,
5305 LPSTR lpDisplayName
,
5306 DWORD dwDesiredAccess
,
5307 DWORD dwServiceType
,
5309 DWORD dwErrorControl
,
5310 LPSTR lpBinaryPathName
,
5311 LPSTR lpLoadOrderGroup
,
5313 LPBYTE lpDependencies
,
5315 LPSTR lpServiceStartName
,
5318 LPSC_RPC_HANDLE lpServiceHandle
)
5321 return ERROR_CALL_NOT_IMPLEMENTED
;
5326 DWORD
RCreateServiceWOW64W(
5327 handle_t BindingHandle
,
5328 LPWSTR lpServiceName
,
5329 LPWSTR lpDisplayName
,
5330 DWORD dwDesiredAccess
,
5331 DWORD dwServiceType
,
5333 DWORD dwErrorControl
,
5334 LPWSTR lpBinaryPathName
,
5335 LPWSTR lpLoadOrderGroup
,
5337 LPBYTE lpDependencies
,
5339 LPWSTR lpServiceStartName
,
5342 LPSC_RPC_HANDLE lpServiceHandle
)
5345 return ERROR_CALL_NOT_IMPLEMENTED
;
5350 DWORD
RQueryServiceTagInfo(
5351 handle_t BindingHandle
) /* FIXME */
5354 return ERROR_CALL_NOT_IMPLEMENTED
;
5359 DWORD
RNotifyServiceStatusChange(
5360 SC_RPC_HANDLE hService
,
5361 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5362 GUID
*pClientProcessGuid
,
5363 GUID
*pSCMProcessGuid
,
5364 PBOOL pfCreateRemoteQueue
,
5365 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5368 return ERROR_CALL_NOT_IMPLEMENTED
;
5373 DWORD
RGetNotifyResults(
5374 SC_NOTIFY_RPC_HANDLE hNotify
,
5375 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5378 return ERROR_CALL_NOT_IMPLEMENTED
;
5383 DWORD
RCloseNotifyHandle(
5384 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5388 return ERROR_CALL_NOT_IMPLEMENTED
;
5393 DWORD
RControlServiceExA(
5394 SC_RPC_HANDLE hService
,
5399 return ERROR_CALL_NOT_IMPLEMENTED
;
5404 DWORD
RControlServiceExW(
5405 SC_RPC_HANDLE hService
,
5410 return ERROR_CALL_NOT_IMPLEMENTED
;
5415 DWORD
RSendPnPMessage(
5416 handle_t BindingHandle
) /* FIXME */
5419 return ERROR_CALL_NOT_IMPLEMENTED
;
5424 DWORD
RValidatePnPService(
5425 handle_t BindingHandle
) /* FIXME */
5428 return ERROR_CALL_NOT_IMPLEMENTED
;
5433 DWORD
ROpenServiceStatusHandle(
5434 handle_t BindingHandle
) /* FIXME */
5437 return ERROR_CALL_NOT_IMPLEMENTED
;
5443 handle_t BindingHandle
) /* FIXME */
5446 return ERROR_CALL_NOT_IMPLEMENTED
;
5450 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5452 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5456 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5458 HeapFree(GetProcessHeap(), 0, ptr
);
5462 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5467 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5472 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)