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
;
731 DWORD
RDeleteService(
732 SC_RPC_HANDLE hService
)
734 PSERVICE_HANDLE hSvc
;
738 DPRINT("RDeleteService() called\n");
741 return ERROR_SHUTDOWN_IN_PROGRESS
;
743 hSvc
= ScmGetServiceFromHandle(hService
);
746 DPRINT1("Invalid service handle!\n");
747 return ERROR_INVALID_HANDLE
;
750 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
752 return ERROR_ACCESS_DENIED
;
754 lpService
= hSvc
->ServiceEntry
;
755 if (lpService
== NULL
)
757 DPRINT("lpService == NULL!\n");
758 return ERROR_INVALID_HANDLE
;
761 /* Lock the service database exclusively */
762 ScmLockDatabaseExclusive();
764 if (lpService
->bDeleted
)
766 DPRINT("The service has already been marked for delete!\n");
767 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
771 /* Mark service for delete */
772 lpService
->bDeleted
= TRUE
;
774 dwError
= ScmMarkServiceForDelete(lpService
);
777 /* Unlock the service database */
780 DPRINT("RDeleteService() done\n");
787 DWORD
RLockServiceDatabase(
788 SC_RPC_HANDLE hSCManager
,
789 LPSC_RPC_LOCK lpLock
)
791 PMANAGER_HANDLE hMgr
;
793 DPRINT("RLockServiceDatabase() called\n");
797 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
800 DPRINT1("Invalid service manager handle!\n");
801 return ERROR_INVALID_HANDLE
;
804 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
806 return ERROR_ACCESS_DENIED
;
808 // return ScmLockDatabase(0, hMgr->0xC, hLock);
810 /* FIXME: Lock the database */
811 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
813 return ERROR_SUCCESS
;
818 DWORD
RQueryServiceObjectSecurity(
819 SC_RPC_HANDLE hService
,
820 SECURITY_INFORMATION dwSecurityInformation
,
821 LPBYTE lpSecurityDescriptor
,
823 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
825 PSERVICE_HANDLE hSvc
;
827 ULONG DesiredAccess
= 0;
833 SECURITY_DESCRIPTOR ObjectDescriptor
;
835 DPRINT("RQueryServiceObjectSecurity() called\n");
837 hSvc
= ScmGetServiceFromHandle(hService
);
840 DPRINT1("Invalid service handle!\n");
841 return ERROR_INVALID_HANDLE
;
844 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
|
845 GROUP_SECURITY_INFORMATION
|
846 OWNER_SECURITY_INFORMATION
))
847 DesiredAccess
|= READ_CONTROL
;
849 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
850 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
852 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
855 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
856 return ERROR_ACCESS_DENIED
;
859 lpService
= hSvc
->ServiceEntry
;
860 if (lpService
== NULL
)
862 DPRINT("lpService == NULL!\n");
863 return ERROR_INVALID_HANDLE
;
866 /* FIXME: Lock the service list */
869 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
871 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
872 dwSecurityInformation
,
873 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
877 /* FIXME: Unlock the service list */
879 if (NT_SUCCESS(Status
))
881 *pcbBytesNeeded
= dwBytesNeeded
;
882 dwError
= STATUS_SUCCESS
;
884 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
886 *pcbBytesNeeded
= dwBytesNeeded
;
887 dwError
= ERROR_INSUFFICIENT_BUFFER
;
889 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
891 dwError
= ERROR_GEN_FAILURE
;
895 dwError
= RtlNtStatusToDosError(Status
);
903 DWORD
RSetServiceObjectSecurity(
904 SC_RPC_HANDLE hService
,
905 DWORD dwSecurityInformation
,
906 LPBYTE lpSecurityDescriptor
,
907 DWORD dwSecuityDescriptorSize
)
909 PSERVICE_HANDLE hSvc
;
911 ULONG DesiredAccess
= 0;
912 /* HANDLE hToken = NULL; */
914 /* NTSTATUS Status; */
917 DPRINT("RSetServiceObjectSecurity() called\n");
919 hSvc
= ScmGetServiceFromHandle(hService
);
922 DPRINT1("Invalid service handle!\n");
923 return ERROR_INVALID_HANDLE
;
926 if (dwSecurityInformation
== 0 ||
927 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
928 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
929 return ERROR_INVALID_PARAMETER
;
931 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
932 return ERROR_INVALID_PARAMETER
;
934 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
935 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
937 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
938 DesiredAccess
|= WRITE_DAC
;
940 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
941 DesiredAccess
|= WRITE_OWNER
;
943 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
944 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
945 return ERROR_INVALID_PARAMETER
;
947 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
948 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
949 return ERROR_INVALID_PARAMETER
;
951 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
954 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
955 return ERROR_ACCESS_DENIED
;
958 lpService
= hSvc
->ServiceEntry
;
959 if (lpService
== NULL
)
961 DPRINT("lpService == NULL!\n");
962 return ERROR_INVALID_HANDLE
;
965 if (lpService
->bDeleted
)
966 return ERROR_SERVICE_MARKED_FOR_DELETE
;
969 RpcImpersonateClient(NULL
);
971 Status
= NtOpenThreadToken(NtCurrentThread(),
975 if (!NT_SUCCESS(Status
))
976 return RtlNtStatusToDosError(Status
);
980 /* FIXME: Lock service database */
982 Status
= RtlSetSecurityObject(dwSecurityInformation
,
983 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
984 &lpService
->lpSecurityDescriptor
,
987 if (!NT_SUCCESS(Status
))
989 dwError
= RtlNtStatusToDosError(Status
);
994 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
995 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
997 if (dwError
!= ERROR_SUCCESS
)
1001 dwError
= ERROR_SUCCESS
;
1002 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
1003 // lpService->lpSecurityDescriptor);
1005 RegFlushKey(hServiceKey
);
1006 RegCloseKey(hServiceKey
);
1015 /* FIXME: Unlock service database */
1017 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1024 DWORD
RQueryServiceStatus(
1025 SC_RPC_HANDLE hService
,
1026 LPSERVICE_STATUS lpServiceStatus
)
1028 PSERVICE_HANDLE hSvc
;
1031 DPRINT("RQueryServiceStatus() called\n");
1034 return ERROR_SHUTDOWN_IN_PROGRESS
;
1036 hSvc
= ScmGetServiceFromHandle(hService
);
1039 DPRINT1("Invalid service handle!\n");
1040 return ERROR_INVALID_HANDLE
;
1043 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1044 SERVICE_QUERY_STATUS
))
1046 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1047 return ERROR_ACCESS_DENIED
;
1050 lpService
= hSvc
->ServiceEntry
;
1051 if (lpService
== NULL
)
1053 DPRINT("lpService == NULL!\n");
1054 return ERROR_INVALID_HANDLE
;
1057 /* Lock the srevice database shared */
1058 ScmLockDatabaseShared();
1060 /* Return service status information */
1061 RtlCopyMemory(lpServiceStatus
,
1063 sizeof(SERVICE_STATUS
));
1065 /* Unlock the service database */
1066 ScmUnlockDatabase();
1068 return ERROR_SUCCESS
;
1073 ScmIsValidServiceState(DWORD dwCurrentState
)
1075 switch (dwCurrentState
)
1077 case SERVICE_STOPPED
:
1078 case SERVICE_START_PENDING
:
1079 case SERVICE_STOP_PENDING
:
1080 case SERVICE_RUNNING
:
1081 case SERVICE_CONTINUE_PENDING
:
1082 case SERVICE_PAUSE_PENDING
:
1083 case SERVICE_PAUSED
:
1093 DWORD
RSetServiceStatus(
1094 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1095 LPSERVICE_STATUS lpServiceStatus
)
1099 DPRINT("RSetServiceStatus() called\n");
1100 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1101 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1102 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1103 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1104 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1105 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1106 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1107 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1109 if (hServiceStatus
== 0)
1111 DPRINT("hServiceStatus == NULL!\n");
1112 return ERROR_INVALID_HANDLE
;
1115 lpService
= (PSERVICE
)hServiceStatus
;
1116 if (lpService
== NULL
)
1118 DPRINT("lpService == NULL!\n");
1119 return ERROR_INVALID_HANDLE
;
1122 /* Check current state */
1123 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1125 DPRINT("Invalid service state!\n");
1126 return ERROR_INVALID_DATA
;
1129 /* Check service type */
1130 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1131 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1133 DPRINT("Invalid service type!\n");
1134 return ERROR_INVALID_DATA
;
1137 /* Check accepted controls */
1138 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1140 DPRINT("Invalid controls accepted!\n");
1141 return ERROR_INVALID_DATA
;
1144 /* Lock the service database exclusively */
1145 ScmLockDatabaseExclusive();
1147 RtlCopyMemory(&lpService
->Status
,
1149 sizeof(SERVICE_STATUS
));
1151 /* Unlock the service database */
1152 ScmUnlockDatabase();
1154 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1155 DPRINT("RSetServiceStatus() done\n");
1157 return ERROR_SUCCESS
;
1162 DWORD
RUnlockServiceDatabase(
1166 return ERROR_SUCCESS
;
1171 DWORD
RNotifyBootConfigStatus(
1172 SVCCTL_HANDLEW lpMachineName
,
1173 DWORD BootAcceptable
)
1175 DPRINT1("RNotifyBootConfigStatus(%p %lu) called\n", lpMachineName
, BootAcceptable
);
1176 return ERROR_SUCCESS
;
1179 // return ERROR_CALL_NOT_IMPLEMENTED;
1184 DWORD
RI_ScSetServiceBitsW(
1185 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1186 DWORD dwServiceBits
,
1188 int bUpdateImmediately
,
1192 return ERROR_CALL_NOT_IMPLEMENTED
;
1197 DWORD
RChangeServiceConfigW(
1198 SC_RPC_HANDLE hService
,
1199 DWORD dwServiceType
,
1201 DWORD dwErrorControl
,
1202 LPWSTR lpBinaryPathName
,
1203 LPWSTR lpLoadOrderGroup
,
1205 LPBYTE lpDependencies
,
1207 LPWSTR lpServiceStartName
,
1210 LPWSTR lpDisplayName
)
1212 DWORD dwError
= ERROR_SUCCESS
;
1213 PSERVICE_HANDLE hSvc
;
1214 PSERVICE lpService
= NULL
;
1215 HKEY hServiceKey
= NULL
;
1216 LPWSTR lpDisplayNameW
= NULL
;
1218 DPRINT("RChangeServiceConfigW() called\n");
1219 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1220 DPRINT("dwStartType = %lu\n", dwStartType
);
1221 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1222 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1223 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1224 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1227 return ERROR_SHUTDOWN_IN_PROGRESS
;
1229 hSvc
= ScmGetServiceFromHandle(hService
);
1232 DPRINT1("Invalid service handle!\n");
1233 return ERROR_INVALID_HANDLE
;
1236 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1237 SERVICE_CHANGE_CONFIG
))
1239 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1240 return ERROR_ACCESS_DENIED
;
1243 lpService
= hSvc
->ServiceEntry
;
1244 if (lpService
== NULL
)
1246 DPRINT("lpService == NULL!\n");
1247 return ERROR_INVALID_HANDLE
;
1250 /* Lock the service database exclusively */
1251 ScmLockDatabaseExclusive();
1253 if (lpService
->bDeleted
)
1255 DPRINT("The service has already been marked for delete!\n");
1256 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
1260 /* Open the service key */
1261 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1264 if (dwError
!= ERROR_SUCCESS
)
1267 /* Write service data to the registry */
1268 /* Set the display name */
1269 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1271 RegSetValueExW(hServiceKey
,
1275 (LPBYTE
)lpDisplayName
,
1276 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1278 /* Update the display name */
1279 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1281 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1282 if (lpDisplayNameW
== NULL
)
1284 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1288 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1289 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1291 lpService
->lpDisplayName
= lpDisplayNameW
;
1294 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1296 /* Set the service type */
1297 dwError
= RegSetValueExW(hServiceKey
,
1301 (LPBYTE
)&dwServiceType
,
1303 if (dwError
!= ERROR_SUCCESS
)
1306 lpService
->Status
.dwServiceType
= dwServiceType
;
1309 if (dwStartType
!= SERVICE_NO_CHANGE
)
1311 /* Set the start value */
1312 dwError
= RegSetValueExW(hServiceKey
,
1316 (LPBYTE
)&dwStartType
,
1318 if (dwError
!= ERROR_SUCCESS
)
1321 lpService
->dwStartType
= dwStartType
;
1324 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1326 /* Set the error control value */
1327 dwError
= RegSetValueExW(hServiceKey
,
1331 (LPBYTE
)&dwErrorControl
,
1333 if (dwError
!= ERROR_SUCCESS
)
1336 lpService
->dwErrorControl
= dwErrorControl
;
1340 /* FIXME: set the new ImagePath value */
1342 /* Set the image path */
1343 if (dwServiceType
& SERVICE_WIN32
)
1345 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1347 dwError
= RegSetValueExW(hServiceKey
,
1351 (LPBYTE
)lpBinaryPathName
,
1352 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1353 if (dwError
!= ERROR_SUCCESS
)
1357 else if (dwServiceType
& SERVICE_DRIVER
)
1359 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1361 dwError
= RegSetValueExW(hServiceKey
,
1365 (LPBYTE
)lpImagePath
,
1366 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1367 if (dwError
!= ERROR_SUCCESS
)
1373 /* Set the group name */
1374 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1376 dwError
= RegSetValueExW(hServiceKey
,
1380 (LPBYTE
)lpLoadOrderGroup
,
1381 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1382 if (dwError
!= ERROR_SUCCESS
)
1385 dwError
= ScmSetServiceGroup(lpService
,
1387 if (dwError
!= ERROR_SUCCESS
)
1391 if (lpdwTagId
!= NULL
)
1393 dwError
= ScmAssignNewTag(lpService
);
1394 if (dwError
!= ERROR_SUCCESS
)
1397 dwError
= RegSetValueExW(hServiceKey
,
1401 (LPBYTE
)&lpService
->dwTag
,
1403 if (dwError
!= ERROR_SUCCESS
)
1406 *lpdwTagId
= lpService
->dwTag
;
1409 /* Write dependencies */
1410 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1412 dwError
= ScmWriteDependencies(hServiceKey
,
1413 (LPWSTR
)lpDependencies
,
1415 if (dwError
!= ERROR_SUCCESS
)
1419 if (lpPassword
!= NULL
)
1421 /* FIXME: Write password */
1425 if (hServiceKey
!= NULL
)
1426 RegCloseKey(hServiceKey
);
1428 /* Unlock the service database */
1429 ScmUnlockDatabase();
1431 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1437 /* Create a path suitable for the bootloader out of the full path */
1439 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1441 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1444 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1445 OBJECT_ATTRIBUTES ObjectAttributes
;
1447 HANDLE SymbolicLinkHandle
;
1449 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1451 ServiceNameLen
= wcslen(CanonName
);
1453 /* First check, if it's already good */
1454 if (ServiceNameLen
> 12 &&
1455 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1457 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1458 if (*RelativeName
== NULL
)
1460 DPRINT("Error allocating memory for boot driver name!\n");
1461 return ERROR_NOT_ENOUGH_MEMORY
;
1465 wcscpy(*RelativeName
, CanonName
);
1467 DPRINT("Bootdriver name %S\n", *RelativeName
);
1468 return ERROR_SUCCESS
;
1471 /* If it has %SystemRoot% prefix, substitute it to \System*/
1472 if (ServiceNameLen
> 13 &&
1473 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1475 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1476 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1478 if (*RelativeName
== NULL
)
1480 DPRINT("Error allocating memory for boot driver name!\n");
1481 return ERROR_NOT_ENOUGH_MEMORY
;
1485 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1486 wcscat(*RelativeName
, CanonName
+ 13);
1488 DPRINT("Bootdriver name %S\n", *RelativeName
);
1489 return ERROR_SUCCESS
;
1492 /* Get buffer size needed for expanding env strings */
1493 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1495 if (BufferSize
<= 1)
1497 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1498 return ERROR_INVALID_ENVIRONMENT
;
1501 /* Allocate memory, since the size is known now */
1502 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1505 DPRINT("Error allocating memory for boot driver name!\n");
1506 return ERROR_NOT_ENOUGH_MEMORY
;
1510 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1513 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1514 LocalFree(Expanded
);
1515 return ERROR_NOT_ENOUGH_MEMORY
;
1518 /* Convert to NY-style path */
1519 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1521 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1522 return ERROR_INVALID_ENVIRONMENT
;
1525 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1527 /* No need to keep the dos-path anymore */
1528 LocalFree(Expanded
);
1530 /* Copy it to the allocated place */
1531 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1534 DPRINT("Error allocating memory for boot driver name!\n");
1535 return ERROR_NOT_ENOUGH_MEMORY
;
1538 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1539 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1540 Expanded
[ExpandedLen
] = 0;
1542 if (ServiceNameLen
> ExpandedLen
&&
1543 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1545 /* Only \SystemRoot\ is missing */
1546 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1547 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1548 if (*RelativeName
== NULL
)
1550 DPRINT("Error allocating memory for boot driver name!\n");
1551 LocalFree(Expanded
);
1552 return ERROR_NOT_ENOUGH_MEMORY
;
1555 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1556 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1558 RtlFreeUnicodeString(&NtPathName
);
1559 return ERROR_SUCCESS
;
1562 /* The most complex case starts here */
1563 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1564 InitializeObjectAttributes(&ObjectAttributes
,
1566 OBJ_CASE_INSENSITIVE
,
1570 /* Open this symlink */
1571 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1573 if (NT_SUCCESS(Status
))
1575 LinkTarget
.Length
= 0;
1576 LinkTarget
.MaximumLength
= 0;
1578 DPRINT("Opened symbolic link object\n");
1580 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1581 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1583 /* Check if required buffer size is sane */
1584 if (BufferSize
> 0xFFFD)
1586 DPRINT("Too large buffer required\n");
1589 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1590 LocalFree(Expanded
);
1591 return ERROR_NOT_ENOUGH_MEMORY
;
1594 /* Alloc the string */
1595 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1596 if (!LinkTarget
.Buffer
)
1598 DPRINT("Unable to alloc buffer\n");
1599 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1600 LocalFree(Expanded
);
1601 return ERROR_NOT_ENOUGH_MEMORY
;
1604 /* Do a real query now */
1605 LinkTarget
.Length
= BufferSize
;
1606 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1608 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1609 if (NT_SUCCESS(Status
))
1611 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1613 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1614 if ((ServiceNameLen
> ExpandedLen
) &&
1615 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1617 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1618 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1620 if (*RelativeName
== NULL
)
1622 DPRINT("Unable to alloc buffer\n");
1623 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1624 LocalFree(Expanded
);
1625 RtlFreeUnicodeString(&NtPathName
);
1626 return ERROR_NOT_ENOUGH_MEMORY
;
1629 /* Copy it over, substituting the first part
1631 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1632 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1635 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1636 LocalFree(Expanded
);
1637 RtlFreeUnicodeString(&NtPathName
);
1639 /* Return success */
1640 return ERROR_SUCCESS
;
1644 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1645 LocalFree(Expanded
);
1646 RtlFreeUnicodeString(&NtPathName
);
1647 return ERROR_INVALID_PARAMETER
;
1652 DPRINT("Error, Status = %08X\n", Status
);
1653 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1654 LocalFree(Expanded
);
1655 RtlFreeUnicodeString(&NtPathName
);
1656 return ERROR_INVALID_PARAMETER
;
1661 DPRINT("Error, Status = %08X\n", Status
);
1662 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1663 LocalFree(Expanded
);
1664 RtlFreeUnicodeString(&NtPathName
);
1665 return ERROR_INVALID_PARAMETER
;
1670 DPRINT("Error, Status = %08X\n", Status
);
1671 LocalFree(Expanded
);
1672 return ERROR_INVALID_PARAMETER
;
1676 *RelativeName
= NULL
;
1677 return ERROR_INVALID_PARAMETER
;
1681 ScmCanonDriverImagePath(DWORD dwStartType
,
1682 const wchar_t *lpServiceName
,
1683 wchar_t **lpCanonName
)
1685 DWORD ServiceNameLen
, Result
;
1686 UNICODE_STRING NtServiceName
;
1687 WCHAR
*RelativeName
;
1688 const WCHAR
*SourceName
= lpServiceName
;
1690 /* Calculate the length of the service's name */
1691 ServiceNameLen
= wcslen(lpServiceName
);
1693 /* 12 is wcslen(L"\\SystemRoot\\") */
1694 if (ServiceNameLen
> 12 &&
1695 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1697 /* SystemRoot prefix is already included */
1699 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1701 if (*lpCanonName
== NULL
)
1703 DPRINT("Error allocating memory for canonized service name!\n");
1704 return ERROR_NOT_ENOUGH_MEMORY
;
1707 /* If it's a boot-time driver, it must be systemroot relative */
1708 if (dwStartType
== SERVICE_BOOT_START
)
1712 wcscpy(*lpCanonName
, SourceName
);
1714 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1718 /* Check if it has %SystemRoot% (len=13) */
1719 if (ServiceNameLen
> 13 &&
1720 !_wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1722 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1723 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1725 if (*lpCanonName
== NULL
)
1727 DPRINT("Error allocating memory for canonized service name!\n");
1728 return ERROR_NOT_ENOUGH_MEMORY
;
1731 /* If it's a boot-time driver, it must be systemroot relative */
1732 if (dwStartType
== SERVICE_BOOT_START
)
1733 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1735 wcscat(*lpCanonName
, lpServiceName
+ 13);
1737 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1741 /* Check if it's a relative path name */
1742 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1744 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1746 if (*lpCanonName
== NULL
)
1748 DPRINT("Error allocating memory for canonized service name!\n");
1749 return ERROR_NOT_ENOUGH_MEMORY
;
1752 /* Just copy it over without changing */
1753 wcscpy(*lpCanonName
, lpServiceName
);
1758 /* It seems to be a DOS path, convert it */
1759 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1761 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
1762 return ERROR_INVALID_PARAMETER
;
1765 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1767 if (*lpCanonName
== NULL
)
1769 DPRINT("Error allocating memory for canonized service name!\n");
1770 RtlFreeUnicodeString(&NtServiceName
);
1771 return ERROR_NOT_ENOUGH_MEMORY
;
1774 /* Copy the string */
1775 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1777 /* The unicode string is not needed anymore */
1778 RtlFreeUnicodeString(&NtServiceName
);
1780 if (dwStartType
!= SERVICE_BOOT_START
)
1782 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1786 /* The service is boot-started, so must be relative */
1787 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1790 /* There is a problem, free name and return */
1791 LocalFree(*lpCanonName
);
1792 DPRINT("Error converting named!\n");
1796 ASSERT(RelativeName
);
1798 /* Copy that string */
1799 wcscpy(*lpCanonName
, RelativeName
+ 12);
1801 /* Free the allocated buffer */
1802 LocalFree(RelativeName
);
1804 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1812 DWORD
RCreateServiceW(
1813 SC_RPC_HANDLE hSCManager
,
1814 LPCWSTR lpServiceName
,
1815 LPCWSTR lpDisplayName
,
1816 DWORD dwDesiredAccess
,
1817 DWORD dwServiceType
,
1819 DWORD dwErrorControl
,
1820 LPCWSTR lpBinaryPathName
,
1821 LPCWSTR lpLoadOrderGroup
,
1823 LPBYTE lpDependencies
,
1825 LPCWSTR lpServiceStartName
,
1828 LPSC_RPC_HANDLE lpServiceHandle
)
1830 PMANAGER_HANDLE hManager
;
1831 DWORD dwError
= ERROR_SUCCESS
;
1832 PSERVICE lpService
= NULL
;
1833 SC_HANDLE hServiceHandle
= NULL
;
1834 LPWSTR lpImagePath
= NULL
;
1835 HKEY hServiceKey
= NULL
;
1836 LPWSTR lpObjectName
;
1838 DPRINT("RCreateServiceW() called\n");
1839 DPRINT("lpServiceName = %S\n", lpServiceName
);
1840 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1841 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1842 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1843 DPRINT("dwStartType = %lu\n", dwStartType
);
1844 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1845 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1846 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1849 return ERROR_SHUTDOWN_IN_PROGRESS
;
1851 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
1852 if (hManager
== NULL
)
1854 DPRINT1("Invalid service manager handle!\n");
1855 return ERROR_INVALID_HANDLE
;
1858 /* Check access rights */
1859 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1860 SC_MANAGER_CREATE_SERVICE
))
1862 DPRINT("Insufficient access rights! 0x%lx\n",
1863 hManager
->Handle
.DesiredAccess
);
1864 return ERROR_ACCESS_DENIED
;
1867 if (wcslen(lpServiceName
) == 0)
1869 return ERROR_INVALID_NAME
;
1872 if (wcslen(lpBinaryPathName
) == 0)
1874 return ERROR_INVALID_PARAMETER
;
1877 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1878 (lpServiceStartName
))
1880 return ERROR_INVALID_PARAMETER
;
1883 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1884 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1885 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1887 return ERROR_INVALID_PARAMETER
;
1890 if (dwStartType
> SERVICE_DISABLED
)
1892 return ERROR_INVALID_PARAMETER
;
1895 /* Lock the service database exclusively */
1896 ScmLockDatabaseExclusive();
1898 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1901 /* Unlock the service database */
1902 ScmUnlockDatabase();
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
)
1914 /* Unlock the service database */
1915 ScmUnlockDatabase();
1917 return ERROR_DUPLICATE_SERVICE_NAME
;
1920 if (dwServiceType
& SERVICE_DRIVER
)
1922 dwError
= ScmCanonDriverImagePath(dwStartType
,
1925 if (dwError
!= ERROR_SUCCESS
)
1930 if (dwStartType
== SERVICE_BOOT_START
||
1931 dwStartType
== SERVICE_SYSTEM_START
)
1933 /* Unlock the service database */
1934 ScmUnlockDatabase();
1936 return ERROR_INVALID_PARAMETER
;
1940 /* Allocate a new service entry */
1941 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1943 if (dwError
!= ERROR_SUCCESS
)
1946 /* Fill the new service entry */
1947 lpService
->Status
.dwServiceType
= dwServiceType
;
1948 lpService
->dwStartType
= dwStartType
;
1949 lpService
->dwErrorControl
= dwErrorControl
;
1951 /* Fill the display name */
1952 if (lpDisplayName
!= NULL
&&
1953 *lpDisplayName
!= 0 &&
1954 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1956 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1957 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1958 if (lpService
->lpDisplayName
== NULL
)
1960 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1963 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1966 /* Assign the service to a group */
1967 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1969 dwError
= ScmSetServiceGroup(lpService
,
1971 if (dwError
!= ERROR_SUCCESS
)
1975 /* Assign a new tag */
1976 if (lpdwTagId
!= NULL
)
1978 dwError
= ScmAssignNewTag(lpService
);
1979 if (dwError
!= ERROR_SUCCESS
)
1983 /* Write service data to the registry */
1984 /* Create the service key */
1985 dwError
= ScmCreateServiceKey(lpServiceName
,
1988 if (dwError
!= ERROR_SUCCESS
)
1991 /* Set the display name */
1992 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1994 RegSetValueExW(hServiceKey
,
1998 (LPBYTE
)lpDisplayName
,
1999 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2002 /* Set the service type */
2003 dwError
= RegSetValueExW(hServiceKey
,
2007 (LPBYTE
)&dwServiceType
,
2009 if (dwError
!= ERROR_SUCCESS
)
2012 /* Set the start value */
2013 dwError
= RegSetValueExW(hServiceKey
,
2017 (LPBYTE
)&dwStartType
,
2019 if (dwError
!= ERROR_SUCCESS
)
2022 /* Set the error control value */
2023 dwError
= RegSetValueExW(hServiceKey
,
2027 (LPBYTE
)&dwErrorControl
,
2029 if (dwError
!= ERROR_SUCCESS
)
2032 /* Set the image path */
2033 if (dwServiceType
& SERVICE_WIN32
)
2035 dwError
= RegSetValueExW(hServiceKey
,
2039 (LPBYTE
)lpBinaryPathName
,
2040 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
2041 if (dwError
!= ERROR_SUCCESS
)
2044 else if (dwServiceType
& SERVICE_DRIVER
)
2046 dwError
= RegSetValueExW(hServiceKey
,
2050 (LPBYTE
)lpImagePath
,
2051 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2052 if (dwError
!= ERROR_SUCCESS
)
2056 /* Set the group name */
2057 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2059 dwError
= RegSetValueExW(hServiceKey
,
2063 (LPBYTE
)lpLoadOrderGroup
,
2064 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
2065 if (dwError
!= ERROR_SUCCESS
)
2069 if (lpdwTagId
!= NULL
)
2071 dwError
= RegSetValueExW(hServiceKey
,
2075 (LPBYTE
)&lpService
->dwTag
,
2077 if (dwError
!= ERROR_SUCCESS
)
2081 /* Write dependencies */
2082 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2084 dwError
= ScmWriteDependencies(hServiceKey
,
2085 (LPWSTR
)lpDependencies
,
2087 if (dwError
!= ERROR_SUCCESS
)
2091 /* Write service start name */
2092 if (dwServiceType
& SERVICE_WIN32
)
2094 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2095 dwError
= RegSetValueExW(hServiceKey
,
2099 (LPBYTE
)lpObjectName
,
2100 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
2101 if (dwError
!= ERROR_SUCCESS
)
2105 if (lpPassword
!= NULL
)
2107 /* FIXME: Write password */
2110 dwError
= ScmCreateServiceHandle(lpService
,
2112 if (dwError
!= ERROR_SUCCESS
)
2115 dwError
= ScmCheckAccess(hServiceHandle
,
2117 if (dwError
!= ERROR_SUCCESS
)
2120 lpService
->dwRefCount
= 1;
2121 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2124 /* Unlock the service database */
2125 ScmUnlockDatabase();
2127 if (hServiceKey
!= NULL
)
2128 RegCloseKey(hServiceKey
);
2130 if (dwError
== ERROR_SUCCESS
)
2132 DPRINT("hService %p\n", hServiceHandle
);
2133 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2135 if (lpdwTagId
!= NULL
)
2136 *lpdwTagId
= lpService
->dwTag
;
2140 /* Release the display name buffer */
2141 if (lpService
->lpServiceName
!= NULL
)
2142 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2146 /* Remove the service handle */
2147 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2150 if (lpService
!= NULL
)
2152 /* FIXME: remove the service entry */
2156 if (lpImagePath
!= NULL
)
2157 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2159 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2166 DWORD
REnumDependentServicesW(
2167 SC_RPC_HANDLE hService
,
2168 DWORD dwServiceState
,
2171 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2172 LPBOUNDED_DWORD_256K lpServicesReturned
)
2174 DWORD dwError
= ERROR_SUCCESS
;
2175 DWORD dwServicesReturned
= 0;
2176 DWORD dwServiceCount
;
2177 HKEY hServicesKey
= NULL
;
2178 PSERVICE_HANDLE hSvc
;
2179 PSERVICE lpService
= NULL
;
2180 PSERVICE
*lpServicesArray
= NULL
;
2181 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2184 *pcbBytesNeeded
= 0;
2185 *lpServicesReturned
= 0;
2187 DPRINT("REnumDependentServicesW() called\n");
2189 hSvc
= ScmGetServiceFromHandle(hService
);
2192 DPRINT1("Invalid service handle!\n");
2193 return ERROR_INVALID_HANDLE
;
2196 lpService
= hSvc
->ServiceEntry
;
2198 /* Check access rights */
2199 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2200 SC_MANAGER_ENUMERATE_SERVICE
))
2202 DPRINT("Insufficient access rights! 0x%lx\n",
2203 hSvc
->Handle
.DesiredAccess
);
2204 return ERROR_ACCESS_DENIED
;
2207 /* Open the Services Reg key */
2208 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2209 L
"System\\CurrentControlSet\\Services",
2213 if (dwError
!= ERROR_SUCCESS
)
2216 /* First determine the bytes needed and get the number of dependent services */
2217 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2222 &dwServicesReturned
);
2223 if (dwError
!= ERROR_SUCCESS
)
2226 /* If buffer size is less than the bytes needed or pointer is null */
2227 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2229 dwError
= ERROR_MORE_DATA
;
2233 /* Allocate memory for array of service pointers */
2234 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2236 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2237 if (!lpServicesArray
)
2239 DPRINT("Could not allocate a buffer!!\n");
2240 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2244 dwServicesReturned
= 0;
2245 *pcbBytesNeeded
= 0;
2247 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2252 &dwServicesReturned
);
2253 if (dwError
!= ERROR_SUCCESS
)
2258 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2259 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2261 /* Copy EnumDepenedentService to Buffer */
2262 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2264 lpService
= lpServicesArray
[dwServiceCount
];
2266 /* Copy status info */
2267 memcpy(&lpServicesPtr
->ServiceStatus
,
2269 sizeof(SERVICE_STATUS
));
2271 /* Copy display name */
2272 wcscpy(lpStr
, lpService
->lpDisplayName
);
2273 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2274 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2276 /* Copy service name */
2277 wcscpy(lpStr
, lpService
->lpServiceName
);
2278 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2279 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2284 *lpServicesReturned
= dwServicesReturned
;
2287 if (lpServicesArray
!= NULL
)
2288 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2290 RegCloseKey(hServicesKey
);
2292 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2299 DWORD
REnumServicesStatusW(
2300 SC_RPC_HANDLE hSCManager
,
2301 DWORD dwServiceType
,
2302 DWORD dwServiceState
,
2305 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2306 LPBOUNDED_DWORD_256K lpServicesReturned
,
2307 LPBOUNDED_DWORD_256K lpResumeHandle
)
2309 PMANAGER_HANDLE hManager
;
2311 DWORD dwError
= ERROR_SUCCESS
;
2312 PLIST_ENTRY ServiceEntry
;
2313 PSERVICE CurrentService
;
2315 DWORD dwRequiredSize
;
2316 DWORD dwServiceCount
;
2318 DWORD dwLastResumeCount
= 0;
2319 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2322 DPRINT("REnumServicesStatusW() called\n");
2325 return ERROR_SHUTDOWN_IN_PROGRESS
;
2327 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2328 if (hManager
== NULL
)
2330 DPRINT1("Invalid service manager handle!\n");
2331 return ERROR_INVALID_HANDLE
;
2335 *pcbBytesNeeded
= 0;
2336 *lpServicesReturned
= 0;
2338 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2340 DPRINT("Not a valid Service Type!\n");
2341 return ERROR_INVALID_PARAMETER
;
2344 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2346 DPRINT("Not a valid Service State!\n");
2347 return ERROR_INVALID_PARAMETER
;
2350 /* Check access rights */
2351 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2352 SC_MANAGER_ENUMERATE_SERVICE
))
2354 DPRINT("Insufficient access rights! 0x%lx\n",
2355 hManager
->Handle
.DesiredAccess
);
2356 return ERROR_ACCESS_DENIED
;
2360 dwLastResumeCount
= *lpResumeHandle
;
2362 /* Lock the service database shared */
2363 ScmLockDatabaseShared();
2365 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2366 if (lpService
== NULL
)
2368 dwError
= ERROR_SUCCESS
;
2375 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2376 ServiceEntry
!= &ServiceListHead
;
2377 ServiceEntry
= ServiceEntry
->Flink
)
2379 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2383 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2386 dwState
= SERVICE_ACTIVE
;
2387 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2388 dwState
= SERVICE_INACTIVE
;
2390 if ((dwState
& dwServiceState
) == 0)
2393 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2394 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2395 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2397 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2399 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2403 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2404 dwRequiredSize
+= dwSize
;
2406 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2409 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2410 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2413 ServiceEntry
!= &ServiceListHead
;
2414 ServiceEntry
= ServiceEntry
->Flink
)
2416 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2420 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2423 dwState
= SERVICE_ACTIVE
;
2424 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2425 dwState
= SERVICE_INACTIVE
;
2427 if ((dwState
& dwServiceState
) == 0)
2430 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2431 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2432 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2434 dwError
= ERROR_MORE_DATA
;
2437 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2440 *lpResumeHandle
= dwLastResumeCount
;
2442 *lpServicesReturned
= dwServiceCount
;
2443 *pcbBytesNeeded
= dwRequiredSize
;
2445 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2446 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2447 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2450 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2451 ServiceEntry
!= &ServiceListHead
;
2452 ServiceEntry
= ServiceEntry
->Flink
)
2454 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2458 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2461 dwState
= SERVICE_ACTIVE
;
2462 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2463 dwState
= SERVICE_INACTIVE
;
2465 if ((dwState
& dwServiceState
) == 0)
2468 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2469 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2470 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2472 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2475 /* Copy the service name */
2476 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2477 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2478 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2480 /* Copy the display name */
2481 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2482 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2483 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2485 /* Copy the status information */
2486 memcpy(&lpStatusPtr
->ServiceStatus
,
2487 &CurrentService
->Status
,
2488 sizeof(SERVICE_STATUS
));
2491 dwRequiredSize
+= dwSize
;
2496 *pcbBytesNeeded
= 0;
2497 if (lpResumeHandle
) *lpResumeHandle
= 0;
2501 /* Unlock the service database */
2502 ScmUnlockDatabase();
2504 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2511 DWORD
ROpenSCManagerW(
2512 LPWSTR lpMachineName
,
2513 LPWSTR lpDatabaseName
,
2514 DWORD dwDesiredAccess
,
2515 LPSC_RPC_HANDLE lpScHandle
)
2520 DPRINT("ROpenSCManagerW() called\n");
2521 DPRINT("lpMachineName = %p\n", lpMachineName
);
2522 DPRINT("lpMachineName: %S\n", lpMachineName
);
2523 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2524 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2525 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2528 return ERROR_SHUTDOWN_IN_PROGRESS
;
2531 return ERROR_INVALID_PARAMETER
;
2533 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2535 if (dwError
!= ERROR_SUCCESS
)
2537 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2541 /* Check the desired access */
2542 dwError
= ScmCheckAccess(hHandle
,
2543 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2544 if (dwError
!= ERROR_SUCCESS
)
2546 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2547 HeapFree(GetProcessHeap(), 0, hHandle
);
2551 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2552 DPRINT("*hScm = %p\n", *lpScHandle
);
2554 DPRINT("ROpenSCManagerW() done\n");
2556 return ERROR_SUCCESS
;
2561 DWORD
ROpenServiceW(
2562 SC_RPC_HANDLE hSCManager
,
2563 LPWSTR lpServiceName
,
2564 DWORD dwDesiredAccess
,
2565 LPSC_RPC_HANDLE lpServiceHandle
)
2568 PMANAGER_HANDLE hManager
;
2570 DWORD dwError
= ERROR_SUCCESS
;
2572 DPRINT("ROpenServiceW() called\n");
2573 DPRINT("hSCManager = %p\n", hSCManager
);
2574 DPRINT("lpServiceName = %p\n", lpServiceName
);
2575 DPRINT("lpServiceName: %S\n", lpServiceName
);
2576 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2579 return ERROR_SHUTDOWN_IN_PROGRESS
;
2581 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2582 if (hManager
== NULL
)
2584 DPRINT1("Invalid service manager handle!\n");
2585 return ERROR_INVALID_HANDLE
;
2588 if (!lpServiceHandle
)
2589 return ERROR_INVALID_PARAMETER
;
2592 return ERROR_INVALID_ADDRESS
;
2594 /* Lock the service database exclusive */
2595 ScmLockDatabaseExclusive();
2597 /* Get service database entry */
2598 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2599 if (lpService
== NULL
)
2601 DPRINT("Could not find a service!\n");
2602 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
2606 /* Create a service handle */
2607 dwError
= ScmCreateServiceHandle(lpService
,
2609 if (dwError
!= ERROR_SUCCESS
)
2611 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2615 /* Check the desired access */
2616 dwError
= ScmCheckAccess(hHandle
,
2618 if (dwError
!= ERROR_SUCCESS
)
2620 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2621 HeapFree(GetProcessHeap(), 0, hHandle
);
2625 lpService
->dwRefCount
++;
2626 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2628 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2629 DPRINT("*hService = %p\n", *lpServiceHandle
);
2632 /* Unlock the service database */
2633 ScmUnlockDatabase();
2635 DPRINT("ROpenServiceW() done\n");
2642 DWORD
RQueryServiceConfigW(
2643 SC_RPC_HANDLE hService
,
2644 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2646 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2648 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2649 DWORD dwError
= ERROR_SUCCESS
;
2650 PSERVICE_HANDLE hSvc
;
2651 PSERVICE lpService
= NULL
;
2652 HKEY hServiceKey
= NULL
;
2653 LPWSTR lpImagePath
= NULL
;
2654 LPWSTR lpServiceStartName
= NULL
;
2655 LPWSTR lpDependencies
= NULL
;
2656 DWORD dwDependenciesLength
= 0;
2657 DWORD dwRequiredSize
;
2658 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2659 WCHAR lpEmptyString
[] = {0,0};
2662 DPRINT("RQueryServiceConfigW() called\n");
2665 return ERROR_SHUTDOWN_IN_PROGRESS
;
2667 hSvc
= ScmGetServiceFromHandle(hService
);
2670 DPRINT1("Invalid service handle!\n");
2671 return ERROR_INVALID_HANDLE
;
2674 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2675 SERVICE_QUERY_CONFIG
))
2677 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2678 return ERROR_ACCESS_DENIED
;
2681 lpService
= hSvc
->ServiceEntry
;
2682 if (lpService
== NULL
)
2684 DPRINT("lpService == NULL!\n");
2685 return ERROR_INVALID_HANDLE
;
2688 /* Lock the service database shared */
2689 ScmLockDatabaseShared();
2691 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2694 if (dwError
!= ERROR_SUCCESS
)
2697 /* Read the image path */
2698 dwError
= ScmReadString(hServiceKey
,
2701 if (dwError
!= ERROR_SUCCESS
)
2704 /* Read the service start name */
2705 ScmReadString(hServiceKey
,
2707 &lpServiceStartName
);
2709 /* Read the dependencies */
2710 ScmReadDependencies(hServiceKey
,
2712 &dwDependenciesLength
);
2714 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2716 if (lpImagePath
!= NULL
)
2717 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2719 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2721 if (lpService
->lpGroup
!= NULL
)
2722 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2724 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2726 if (lpDependencies
!= NULL
)
2727 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2729 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2731 if (lpServiceStartName
!= NULL
)
2732 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2734 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2736 if (lpService
->lpDisplayName
!= NULL
)
2737 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2739 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2741 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2743 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2747 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2748 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2749 lpConfig
->dwStartType
= lpService
->dwStartType
;
2750 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2751 lpConfig
->dwTagId
= lpService
->dwTag
;
2753 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2755 /* Append the image path */
2756 if (lpImagePath
!= NULL
)
2758 wcscpy(lpStr
, lpImagePath
);
2762 wcscpy(lpStr
, lpEmptyString
);
2765 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2766 lpStr
+= (wcslen(lpStr
) + 1);
2768 /* Append the group name */
2769 if (lpService
->lpGroup
!= NULL
)
2771 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2775 wcscpy(lpStr
, lpEmptyString
);
2778 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2779 lpStr
+= (wcslen(lpStr
) + 1);
2781 /* Append Dependencies */
2782 if (lpDependencies
!= NULL
)
2786 dwDependenciesLength
* sizeof(WCHAR
));
2790 wcscpy(lpStr
, lpEmptyString
);
2793 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2794 if (lpDependencies
!= NULL
)
2795 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2797 lpStr
+= (wcslen(lpStr
) + 1);
2799 /* Append the service start name */
2800 if (lpServiceStartName
!= NULL
)
2802 wcscpy(lpStr
, lpServiceStartName
);
2806 wcscpy(lpStr
, lpEmptyString
);
2809 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2810 lpStr
+= (wcslen(lpStr
) + 1);
2812 /* Append the display name */
2813 if (lpService
->lpDisplayName
!= NULL
)
2815 wcscpy(lpStr
, lpService
->lpDisplayName
);
2819 wcscpy(lpStr
, lpEmptyString
);
2822 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2825 if (pcbBytesNeeded
!= NULL
)
2826 *pcbBytesNeeded
= dwRequiredSize
;
2829 /* Unlock the service database */
2830 ScmUnlockDatabase();
2832 if (lpImagePath
!= NULL
)
2833 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2835 if (lpServiceStartName
!= NULL
)
2836 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2838 if (lpDependencies
!= NULL
)
2839 HeapFree(GetProcessHeap(), 0, lpDependencies
);
2841 if (hServiceKey
!= NULL
)
2842 RegCloseKey(hServiceKey
);
2844 DPRINT("RQueryServiceConfigW() done\n");
2851 DWORD
RQueryServiceLockStatusW(
2852 SC_RPC_HANDLE hSCManager
,
2853 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2855 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2858 return ERROR_CALL_NOT_IMPLEMENTED
;
2863 DWORD
RStartServiceW(
2864 SC_RPC_HANDLE hService
,
2866 LPSTRING_PTRSW argv
)
2868 DWORD dwError
= ERROR_SUCCESS
;
2869 PSERVICE_HANDLE hSvc
;
2870 PSERVICE lpService
= NULL
;
2872 DPRINT("RStartServiceW() called\n");
2875 return ERROR_SHUTDOWN_IN_PROGRESS
;
2877 hSvc
= ScmGetServiceFromHandle(hService
);
2880 DPRINT1("Invalid service handle!\n");
2881 return ERROR_INVALID_HANDLE
;
2884 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2887 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2888 return ERROR_ACCESS_DENIED
;
2891 lpService
= hSvc
->ServiceEntry
;
2892 if (lpService
== NULL
)
2894 DPRINT("lpService == NULL!\n");
2895 return ERROR_INVALID_HANDLE
;
2898 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2899 return ERROR_SERVICE_DISABLED
;
2901 if (lpService
->bDeleted
)
2902 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2909 /* Start the service */
2910 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2917 DWORD
RGetServiceDisplayNameW(
2918 SC_RPC_HANDLE hSCManager
,
2919 LPCWSTR lpServiceName
,
2920 LPWSTR lpDisplayName
,
2923 // PMANAGER_HANDLE hManager;
2928 DPRINT("RGetServiceDisplayNameW() called\n");
2929 DPRINT("hSCManager = %p\n", hSCManager
);
2930 DPRINT("lpServiceName: %S\n", lpServiceName
);
2931 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2932 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2934 // hManager = (PMANAGER_HANDLE)hSCManager;
2935 // if (hManager->Handle.Tag != MANAGER_TAG)
2937 // DPRINT("Invalid manager handle!\n");
2938 // return ERROR_INVALID_HANDLE;
2941 /* Get service database entry */
2942 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2943 if (lpService
== NULL
)
2945 DPRINT("Could not find a service!\n");
2947 /* If the service could not be found and lpcchBuffer is less than 2, windows
2948 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2949 if (*lpcchBuffer
< 2)
2952 if (lpDisplayName
!= NULL
)
2954 *lpDisplayName
= '\0';
2958 return ERROR_SERVICE_DOES_NOT_EXIST
;
2961 if (!lpService
->lpDisplayName
)
2963 dwLength
= wcslen(lpService
->lpServiceName
);
2965 if (lpDisplayName
!= NULL
&&
2966 *lpcchBuffer
> dwLength
)
2968 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2973 dwLength
= wcslen(lpService
->lpDisplayName
);
2975 if (lpDisplayName
!= NULL
&&
2976 *lpcchBuffer
> dwLength
)
2978 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2982 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2984 *lpcchBuffer
= dwLength
;
2991 DWORD
RGetServiceKeyNameW(
2992 SC_RPC_HANDLE hSCManager
,
2993 LPCWSTR lpDisplayName
,
2994 LPWSTR lpServiceName
,
2997 // PMANAGER_HANDLE hManager;
3002 DPRINT("RGetServiceKeyNameW() called\n");
3003 DPRINT("hSCManager = %p\n", hSCManager
);
3004 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
3005 DPRINT("lpServiceName: %p\n", lpServiceName
);
3006 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3008 // hManager = (PMANAGER_HANDLE)hSCManager;
3009 // if (hManager->Handle.Tag != MANAGER_TAG)
3011 // DPRINT("Invalid manager handle!\n");
3012 // return ERROR_INVALID_HANDLE;
3015 /* Get service database entry */
3016 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
3017 if (lpService
== NULL
)
3019 DPRINT("Could not find a service!\n");
3021 /* If the service could not be found and lpcchBuffer is less than 2, windows
3022 puts null in lpDisplayName and puts 2 in lpcchBuffer */
3023 if (*lpcchBuffer
< 2)
3026 if (lpServiceName
!= NULL
)
3028 *lpServiceName
= '\0';
3032 return ERROR_SERVICE_DOES_NOT_EXIST
;
3035 dwLength
= wcslen(lpService
->lpServiceName
);
3037 if (lpServiceName
!= NULL
&&
3038 *lpcchBuffer
> dwLength
)
3040 wcscpy(lpServiceName
, lpService
->lpServiceName
);
3041 *lpcchBuffer
= dwLength
;
3042 return ERROR_SUCCESS
;
3045 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3047 *lpcchBuffer
= dwLength
;
3054 DWORD
RI_ScSetServiceBitsA(
3055 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3056 DWORD dwServiceBits
,
3058 int bUpdateImmediately
,
3062 return ERROR_CALL_NOT_IMPLEMENTED
;
3067 DWORD
RChangeServiceConfigA(
3068 SC_RPC_HANDLE hService
,
3069 DWORD dwServiceType
,
3071 DWORD dwErrorControl
,
3072 LPSTR lpBinaryPathName
,
3073 LPSTR lpLoadOrderGroup
,
3075 LPSTR lpDependencies
,
3077 LPSTR lpServiceStartName
,
3080 LPSTR lpDisplayName
)
3082 DWORD dwError
= ERROR_SUCCESS
;
3083 PSERVICE_HANDLE hSvc
;
3084 PSERVICE lpService
= NULL
;
3085 HKEY hServiceKey
= NULL
;
3086 LPWSTR lpDisplayNameW
= NULL
;
3087 // LPWSTR lpBinaryPathNameW = NULL;
3088 LPWSTR lpLoadOrderGroupW
= NULL
;
3089 LPWSTR lpDependenciesW
= NULL
;
3090 // LPWSTR lpPasswordW = NULL;
3092 DPRINT("RChangeServiceConfigA() called\n");
3093 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3094 DPRINT("dwStartType = %lu\n", dwStartType
);
3095 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3096 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3097 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3098 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3101 return ERROR_SHUTDOWN_IN_PROGRESS
;
3103 hSvc
= ScmGetServiceFromHandle(hService
);
3106 DPRINT1("Invalid service handle!\n");
3107 return ERROR_INVALID_HANDLE
;
3110 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3111 SERVICE_CHANGE_CONFIG
))
3113 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3114 return ERROR_ACCESS_DENIED
;
3117 lpService
= hSvc
->ServiceEntry
;
3118 if (lpService
== NULL
)
3120 DPRINT("lpService == NULL!\n");
3121 return ERROR_INVALID_HANDLE
;
3124 /* Lock the service database exclusively */
3125 ScmLockDatabaseExclusive();
3127 if (lpService
->bDeleted
)
3129 DPRINT("The service has already been marked for delete!\n");
3130 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
3134 /* Open the service key */
3135 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3138 if (dwError
!= ERROR_SUCCESS
)
3141 /* Write service data to the registry */
3143 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3145 /* Set the display name */
3146 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3148 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3149 if (lpDisplayNameW
== NULL
)
3151 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3155 MultiByteToWideChar(CP_ACP
,
3160 strlen(lpDisplayName
) + 1);
3162 RegSetValueExW(hServiceKey
,
3166 (LPBYTE
)lpDisplayNameW
,
3167 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3169 /* Update lpService->lpDisplayName */
3170 if (lpService
->lpDisplayName
)
3171 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3173 lpService
->lpDisplayName
= lpDisplayNameW
;
3176 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3178 /* Set the service type */
3179 dwError
= RegSetValueExW(hServiceKey
,
3183 (LPBYTE
)&dwServiceType
,
3185 if (dwError
!= ERROR_SUCCESS
)
3188 lpService
->Status
.dwServiceType
= dwServiceType
;
3191 if (dwStartType
!= SERVICE_NO_CHANGE
)
3193 /* Set the start value */
3194 dwError
= RegSetValueExW(hServiceKey
,
3198 (LPBYTE
)&dwStartType
,
3200 if (dwError
!= ERROR_SUCCESS
)
3203 lpService
->dwStartType
= dwStartType
;
3206 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3208 /* Set the error control value */
3209 dwError
= RegSetValueExW(hServiceKey
,
3213 (LPBYTE
)&dwErrorControl
,
3215 if (dwError
!= ERROR_SUCCESS
)
3218 lpService
->dwErrorControl
= dwErrorControl
;
3222 /* FIXME: set the new ImagePath value */
3224 /* Set the image path */
3225 if (dwServiceType
& SERVICE_WIN32
)
3227 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3229 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3230 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, strlen(lpBinaryPathName
)+1);
3231 dwError
= RegSetValueExW(hServiceKey
,
3235 (LPBYTE
)lpBinaryPathNameW
,
3236 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3237 if (dwError
!= ERROR_SUCCESS
)
3241 else if (dwServiceType
& SERVICE_DRIVER
)
3243 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3245 dwError
= RegSetValueExW(hServiceKey
,
3249 (LPBYTE
)lpImagePath
,
3250 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3251 if (dwError
!= ERROR_SUCCESS
)
3257 /* Set the group name */
3258 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3260 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3262 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3263 if (lpLoadOrderGroupW
== NULL
)
3265 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3269 MultiByteToWideChar(CP_ACP
,
3274 strlen(lpLoadOrderGroup
) + 1);
3276 dwError
= RegSetValueExW(hServiceKey
,
3280 (LPBYTE
)lpLoadOrderGroupW
,
3281 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3282 if (dwError
!= ERROR_SUCCESS
)
3284 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3288 dwError
= ScmSetServiceGroup(lpService
,
3291 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3293 if (dwError
!= ERROR_SUCCESS
)
3297 if (lpdwTagId
!= NULL
)
3299 dwError
= ScmAssignNewTag(lpService
);
3300 if (dwError
!= ERROR_SUCCESS
)
3303 dwError
= RegSetValueExW(hServiceKey
,
3307 (LPBYTE
)&lpService
->dwTag
,
3309 if (dwError
!= ERROR_SUCCESS
)
3312 *lpdwTagId
= lpService
->dwTag
;
3315 /* Write dependencies */
3316 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3318 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3320 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3321 if (lpDependenciesW
== NULL
)
3323 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3327 MultiByteToWideChar(CP_ACP
,
3332 strlen(lpDependencies
) + 1);
3334 dwError
= ScmWriteDependencies(hServiceKey
,
3335 (LPWSTR
)lpDependenciesW
,
3338 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3341 if (lpPassword
!= NULL
)
3343 /* FIXME: Write password */
3347 /* Unlock the service database */
3348 ScmUnlockDatabase();
3350 if (hServiceKey
!= NULL
)
3351 RegCloseKey(hServiceKey
);
3353 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3360 DWORD
RCreateServiceA(
3361 SC_RPC_HANDLE hSCManager
,
3362 LPSTR lpServiceName
,
3363 LPSTR lpDisplayName
,
3364 DWORD dwDesiredAccess
,
3365 DWORD dwServiceType
,
3367 DWORD dwErrorControl
,
3368 LPSTR lpBinaryPathName
,
3369 LPSTR lpLoadOrderGroup
,
3371 LPBYTE lpDependencies
,
3373 LPSTR lpServiceStartName
,
3376 LPSC_RPC_HANDLE lpServiceHandle
)
3378 DWORD dwError
= ERROR_SUCCESS
;
3379 LPWSTR lpServiceNameW
= NULL
;
3380 LPWSTR lpDisplayNameW
= NULL
;
3381 LPWSTR lpBinaryPathNameW
= NULL
;
3382 LPWSTR lpLoadOrderGroupW
= NULL
;
3383 LPWSTR lpDependenciesW
= NULL
;
3384 LPWSTR lpServiceStartNameW
= NULL
;
3385 DWORD dwDependenciesLength
= 0;
3392 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3393 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3394 if (!lpServiceNameW
)
3396 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3399 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3404 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3405 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3406 if (!lpDisplayNameW
)
3408 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3411 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3414 if (lpBinaryPathName
)
3416 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3417 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3418 if (!lpBinaryPathNameW
)
3420 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3423 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3426 if (lpLoadOrderGroup
)
3428 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3429 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3430 if (!lpLoadOrderGroupW
)
3432 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3435 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3440 lpStr
= (LPSTR
)lpDependencies
;
3443 dwLength
= strlen(lpStr
) + 1;
3444 dwDependenciesLength
+= dwLength
;
3445 lpStr
= lpStr
+ dwLength
;
3447 dwDependenciesLength
++;
3449 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3450 if (!lpDependenciesW
)
3452 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3455 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3458 if (lpServiceStartName
)
3460 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3461 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3462 if (!lpServiceStartNameW
)
3464 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3467 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3470 dwError
= RCreateServiceW(hSCManager
,
3480 (LPBYTE
)lpDependenciesW
,
3481 dwDependenciesLength
,
3482 lpServiceStartNameW
,
3488 if (lpServiceNameW
!=NULL
)
3489 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3491 if (lpDisplayNameW
!= NULL
)
3492 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3494 if (lpBinaryPathNameW
!= NULL
)
3495 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3497 if (lpLoadOrderGroupW
!= NULL
)
3498 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3500 if (lpDependenciesW
!= NULL
)
3501 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3503 if (lpServiceStartNameW
!= NULL
)
3504 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3511 DWORD
REnumDependentServicesA(
3512 SC_RPC_HANDLE hService
,
3513 DWORD dwServiceState
,
3516 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3517 LPBOUNDED_DWORD_256K lpServicesReturned
)
3519 DWORD dwError
= ERROR_SUCCESS
;
3520 DWORD dwServicesReturned
= 0;
3521 DWORD dwServiceCount
;
3522 HKEY hServicesKey
= NULL
;
3523 PSERVICE_HANDLE hSvc
;
3524 PSERVICE lpService
= NULL
;
3525 PSERVICE
*lpServicesArray
= NULL
;
3526 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3529 *pcbBytesNeeded
= 0;
3530 *lpServicesReturned
= 0;
3532 DPRINT("REnumDependentServicesA() called\n");
3534 hSvc
= ScmGetServiceFromHandle(hService
);
3537 DPRINT1("Invalid service handle!\n");
3538 return ERROR_INVALID_HANDLE
;
3541 lpService
= hSvc
->ServiceEntry
;
3543 /* Check access rights */
3544 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3545 SC_MANAGER_ENUMERATE_SERVICE
))
3547 DPRINT("Insufficient access rights! 0x%lx\n",
3548 hSvc
->Handle
.DesiredAccess
);
3549 return ERROR_ACCESS_DENIED
;
3552 /* Open the Services Reg key */
3553 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3554 L
"System\\CurrentControlSet\\Services",
3559 if (dwError
!= ERROR_SUCCESS
)
3562 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3563 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3564 are the same for both. Verified in WINXP. */
3566 /* First determine the bytes needed and get the number of dependent services*/
3567 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3572 &dwServicesReturned
);
3573 if (dwError
!= ERROR_SUCCESS
)
3576 /* If buffer size is less than the bytes needed or pointer is null*/
3577 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3579 dwError
= ERROR_MORE_DATA
;
3583 /* Allocate memory for array of service pointers */
3584 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3586 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3587 if (!lpServicesArray
)
3589 DPRINT("Could not allocate a buffer!!\n");
3590 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3594 dwServicesReturned
= 0;
3595 *pcbBytesNeeded
= 0;
3597 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3602 &dwServicesReturned
);
3603 if (dwError
!= ERROR_SUCCESS
)
3608 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3609 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3611 /* Copy EnumDepenedentService to Buffer */
3612 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3614 lpService
= lpServicesArray
[dwServiceCount
];
3616 /* Copy the status info */
3617 memcpy(&lpServicesPtr
->ServiceStatus
,
3619 sizeof(SERVICE_STATUS
));
3621 /* Copy display name */
3622 WideCharToMultiByte(CP_ACP
,
3624 lpService
->lpDisplayName
,
3627 wcslen(lpService
->lpDisplayName
),
3630 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3631 lpStr
+= strlen(lpStr
) + 1;
3633 /* Copy service name */
3634 WideCharToMultiByte(CP_ACP
,
3636 lpService
->lpServiceName
,
3639 wcslen(lpService
->lpServiceName
),
3642 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3643 lpStr
+= strlen(lpStr
) + 1;
3648 *lpServicesReturned
= dwServicesReturned
;
3651 if (lpServicesArray
)
3652 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3654 RegCloseKey(hServicesKey
);
3656 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3663 DWORD
REnumServicesStatusA(
3664 SC_RPC_HANDLE hSCManager
,
3665 DWORD dwServiceType
,
3666 DWORD dwServiceState
,
3669 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3670 LPBOUNDED_DWORD_256K lpServicesReturned
,
3671 LPBOUNDED_DWORD_256K lpResumeHandle
)
3673 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3674 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3675 LPWSTR lpStringPtrW
;
3678 DWORD dwServiceCount
;
3680 DPRINT("REnumServicesStatusA() called\n");
3682 if ((dwBufSize
> 0) && (lpBuffer
))
3684 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3687 DPRINT("Failed to allocate buffer!\n");
3688 return ERROR_NOT_ENOUGH_MEMORY
;
3692 dwError
= REnumServicesStatusW(hSCManager
,
3695 (LPBYTE
)lpStatusPtrW
,
3701 /* if no services were returned then we are Done */
3702 if (*lpServicesReturned
== 0)
3705 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3706 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3707 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3708 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3709 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3711 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3713 /* Copy the service name */
3714 WideCharToMultiByte(CP_ACP
,
3719 wcslen(lpStringPtrW
),
3723 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3724 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3725 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3727 /* Copy the display name */
3728 WideCharToMultiByte(CP_ACP
,
3733 wcslen(lpStringPtrW
),
3737 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3738 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3739 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3741 /* Copy the status information */
3742 memcpy(&lpStatusPtrA
->ServiceStatus
,
3743 &lpStatusPtrW
->ServiceStatus
,
3744 sizeof(SERVICE_STATUS
));
3751 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3753 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3760 DWORD
ROpenSCManagerA(
3761 LPSTR lpMachineName
,
3762 LPSTR lpDatabaseName
,
3763 DWORD dwDesiredAccess
,
3764 LPSC_RPC_HANDLE lpScHandle
)
3766 UNICODE_STRING MachineName
;
3767 UNICODE_STRING DatabaseName
;
3770 DPRINT("ROpenSCManagerA() called\n");
3773 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3777 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3780 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3781 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3786 RtlFreeUnicodeString(&MachineName
);
3789 RtlFreeUnicodeString(&DatabaseName
);
3796 DWORD
ROpenServiceA(
3797 SC_RPC_HANDLE hSCManager
,
3798 LPSTR lpServiceName
,
3799 DWORD dwDesiredAccess
,
3800 LPSC_RPC_HANDLE lpServiceHandle
)
3802 UNICODE_STRING ServiceName
;
3805 DPRINT("ROpenServiceA() called\n");
3808 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3811 dwError
= ROpenServiceW(hSCManager
,
3812 lpServiceName
? ServiceName
.Buffer
: NULL
,
3817 RtlFreeUnicodeString(&ServiceName
);
3824 DWORD
RQueryServiceConfigA(
3825 SC_RPC_HANDLE hService
,
3826 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3828 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3830 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3831 DWORD dwError
= ERROR_SUCCESS
;
3832 PSERVICE_HANDLE hSvc
;
3833 PSERVICE lpService
= NULL
;
3834 HKEY hServiceKey
= NULL
;
3835 LPWSTR lpImagePath
= NULL
;
3836 LPWSTR lpServiceStartName
= NULL
;
3837 LPWSTR lpDependencies
= NULL
;
3838 DWORD dwDependenciesLength
= 0;
3839 DWORD dwRequiredSize
;
3840 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3841 CHAR lpEmptyString
[]={0,0};
3844 DPRINT("RQueryServiceConfigA() called\n");
3847 return ERROR_SHUTDOWN_IN_PROGRESS
;
3849 hSvc
= ScmGetServiceFromHandle(hService
);
3852 DPRINT1("Invalid service handle!\n");
3853 return ERROR_INVALID_HANDLE
;
3856 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3857 SERVICE_QUERY_CONFIG
))
3859 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3860 return ERROR_ACCESS_DENIED
;
3863 lpService
= hSvc
->ServiceEntry
;
3864 if (lpService
== NULL
)
3866 DPRINT("lpService == NULL!\n");
3867 return ERROR_INVALID_HANDLE
;
3870 /* Lock the service database shared */
3871 ScmLockDatabaseShared();
3873 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3876 if (dwError
!= ERROR_SUCCESS
)
3879 /* Read the image path */
3880 dwError
= ScmReadString(hServiceKey
,
3883 if (dwError
!= ERROR_SUCCESS
)
3886 /* Read the service start name */
3887 ScmReadString(hServiceKey
,
3889 &lpServiceStartName
);
3891 /* Read the dependencies */
3892 ScmReadDependencies(hServiceKey
,
3894 &dwDependenciesLength
);
3896 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3898 if (lpImagePath
!= NULL
)
3899 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3901 dwRequiredSize
+= 2;
3903 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3904 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3906 dwRequiredSize
+= 2;
3908 /* Add Dependencies length */
3909 if (lpDependencies
!= NULL
)
3910 dwRequiredSize
+= dwDependenciesLength
;
3912 dwRequiredSize
+= 2;
3914 if (lpServiceStartName
!= NULL
)
3915 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3917 dwRequiredSize
+= 2;
3919 if (lpService
->lpDisplayName
!= NULL
)
3920 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3922 dwRequiredSize
+= 2;
3924 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3926 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3930 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3931 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3932 lpConfig
->dwStartType
= lpService
->dwStartType
;
3933 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3934 lpConfig
->dwTagId
= lpService
->dwTag
;
3936 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3938 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3943 WideCharToMultiByte(CP_ACP
,
3948 wcslen(lpImagePath
) + 1,
3954 strcpy(lpStr
, lpEmptyString
);
3957 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3958 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3960 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
3962 WideCharToMultiByte(CP_ACP
,
3964 lpService
->lpGroup
->lpGroupName
,
3967 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
3973 strcpy(lpStr
, lpEmptyString
);
3976 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3977 lpStr
+= (strlen(lpStr
) + 1);
3979 /* Append Dependencies */
3982 WideCharToMultiByte(CP_ACP
,
3985 dwDependenciesLength
,
3987 dwDependenciesLength
,
3993 strcpy(lpStr
, lpEmptyString
);
3996 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3998 lpStr
+= dwDependenciesLength
;
4000 lpStr
+= (strlen(lpStr
) + 1);
4002 if (lpServiceStartName
)
4004 WideCharToMultiByte(CP_ACP
,
4009 wcslen(lpServiceStartName
) + 1,
4015 strcpy(lpStr
, lpEmptyString
);
4018 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4019 lpStr
+= (strlen(lpStr
) + 1);
4021 if (lpService
->lpDisplayName
)
4023 WideCharToMultiByte(CP_ACP
,
4025 lpService
->lpDisplayName
,
4028 wcslen(lpService
->lpDisplayName
) + 1,
4034 strcpy(lpStr
, lpEmptyString
);
4037 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
4040 if (pcbBytesNeeded
!= NULL
)
4041 *pcbBytesNeeded
= dwRequiredSize
;
4044 /* Unlock the service database */
4045 ScmUnlockDatabase();
4047 if (lpImagePath
!= NULL
)
4048 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4050 if (lpServiceStartName
!= NULL
)
4051 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4053 if (lpDependencies
!= NULL
)
4054 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4056 if (hServiceKey
!= NULL
)
4057 RegCloseKey(hServiceKey
);
4059 DPRINT("RQueryServiceConfigA() done\n");
4066 DWORD
RQueryServiceLockStatusA(
4067 SC_RPC_HANDLE hSCManager
,
4068 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
4070 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4073 return ERROR_CALL_NOT_IMPLEMENTED
;
4078 DWORD
RStartServiceA(
4079 SC_RPC_HANDLE hService
,
4081 LPSTRING_PTRSA argv
)
4083 DWORD dwError
= ERROR_SUCCESS
;
4084 PSERVICE_HANDLE hSvc
;
4085 PSERVICE lpService
= NULL
;
4087 DPRINT("RStartServiceA() called\n");
4090 return ERROR_SHUTDOWN_IN_PROGRESS
;
4092 hSvc
= ScmGetServiceFromHandle(hService
);
4095 DPRINT1("Invalid service handle!\n");
4096 return ERROR_INVALID_HANDLE
;
4099 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4102 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4103 return ERROR_ACCESS_DENIED
;
4106 lpService
= hSvc
->ServiceEntry
;
4107 if (lpService
== NULL
)
4109 DPRINT("lpService == NULL!\n");
4110 return ERROR_INVALID_HANDLE
;
4113 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4114 return ERROR_SERVICE_DISABLED
;
4116 if (lpService
->bDeleted
)
4117 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4119 /* FIXME: Convert argument vector to Unicode */
4121 /* Start the service */
4122 dwError
= ScmStartService(lpService
, 0, NULL
);
4124 /* FIXME: Free argument vector */
4131 DWORD
RGetServiceDisplayNameA(
4132 SC_RPC_HANDLE hSCManager
,
4133 LPCSTR lpServiceName
,
4134 LPSTR lpDisplayName
,
4135 LPBOUNDED_DWORD_4K lpcchBuffer
)
4137 // PMANAGER_HANDLE hManager;
4138 PSERVICE lpService
= NULL
;
4141 LPWSTR lpServiceNameW
;
4143 DPRINT("RGetServiceDisplayNameA() called\n");
4144 DPRINT("hSCManager = %p\n", hSCManager
);
4145 DPRINT("lpServiceName: %s\n", lpServiceName
);
4146 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4147 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4149 // hManager = (PMANAGER_HANDLE)hSCManager;
4150 // if (hManager->Handle.Tag != MANAGER_TAG)
4152 // DPRINT("Invalid manager handle!\n");
4153 // return ERROR_INVALID_HANDLE;
4156 if (lpServiceName
!= NULL
)
4158 dwLength
= strlen(lpServiceName
) + 1;
4159 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4161 dwLength
* sizeof(WCHAR
));
4162 if (!lpServiceNameW
)
4163 return ERROR_NOT_ENOUGH_MEMORY
;
4165 MultiByteToWideChar(CP_ACP
,
4172 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4174 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4177 if (lpService
== NULL
)
4179 DPRINT("Could not find a service!\n");
4181 /* If the service could not be found and lpcchBuffer is 0, windows
4182 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4183 if (*lpcchBuffer
== 0)
4186 if (lpDisplayName
!= NULL
)
4188 *lpDisplayName
= '\0';
4191 return ERROR_SERVICE_DOES_NOT_EXIST
;
4194 if (!lpService
->lpDisplayName
)
4196 dwLength
= wcslen(lpService
->lpServiceName
);
4197 if (lpDisplayName
!= NULL
&&
4198 *lpcchBuffer
> dwLength
)
4200 WideCharToMultiByte(CP_ACP
,
4202 lpService
->lpServiceName
,
4203 wcslen(lpService
->lpServiceName
),
4208 return ERROR_SUCCESS
;
4213 dwLength
= wcslen(lpService
->lpDisplayName
);
4214 if (lpDisplayName
!= NULL
&&
4215 *lpcchBuffer
> dwLength
)
4217 WideCharToMultiByte(CP_ACP
,
4219 lpService
->lpDisplayName
,
4220 wcslen(lpService
->lpDisplayName
),
4225 return ERROR_SUCCESS
;
4229 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4231 *lpcchBuffer
= dwLength
* 2;
4238 DWORD
RGetServiceKeyNameA(
4239 SC_RPC_HANDLE hSCManager
,
4240 LPCSTR lpDisplayName
,
4241 LPSTR lpServiceName
,
4242 LPBOUNDED_DWORD_4K lpcchBuffer
)
4247 LPWSTR lpDisplayNameW
;
4249 DPRINT("RGetServiceKeyNameA() called\n");
4250 DPRINT("hSCManager = %p\n", hSCManager
);
4251 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4252 DPRINT("lpServiceName: %p\n", lpServiceName
);
4253 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4255 dwLength
= strlen(lpDisplayName
) + 1;
4256 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4258 dwLength
* sizeof(WCHAR
));
4259 if (!lpDisplayNameW
)
4260 return ERROR_NOT_ENOUGH_MEMORY
;
4262 MultiByteToWideChar(CP_ACP
,
4269 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4271 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4273 if (lpService
== NULL
)
4275 DPRINT("Could not find the service!\n");
4277 /* If the service could not be found and lpcchBuffer is 0,
4278 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4279 if (*lpcchBuffer
== 0)
4282 if (lpServiceName
!= NULL
)
4284 *lpServiceName
= '\0';
4288 return ERROR_SERVICE_DOES_NOT_EXIST
;
4291 dwLength
= wcslen(lpService
->lpServiceName
);
4292 if (lpServiceName
!= NULL
&&
4293 *lpcchBuffer
> dwLength
)
4295 WideCharToMultiByte(CP_ACP
,
4297 lpService
->lpServiceName
,
4298 wcslen(lpService
->lpServiceName
),
4303 return ERROR_SUCCESS
;
4306 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4308 *lpcchBuffer
= dwLength
* 2;
4315 DWORD
RI_ScGetCurrentGroupStateW(
4316 SC_RPC_HANDLE hSCManager
,
4317 LPWSTR lpLoadOrderGroup
,
4321 return ERROR_CALL_NOT_IMPLEMENTED
;
4326 DWORD
REnumServiceGroupW(
4327 SC_RPC_HANDLE hSCManager
,
4328 DWORD dwServiceType
,
4329 DWORD dwServiceState
,
4332 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4333 LPBOUNDED_DWORD_256K lpServicesReturned
,
4334 LPBOUNDED_DWORD_256K lpResumeIndex
,
4335 LPCWSTR pszGroupName
)
4338 return ERROR_CALL_NOT_IMPLEMENTED
;
4343 // WARNING: This function is untested
4346 DWORD
RChangeServiceConfig2A(
4347 SC_RPC_HANDLE hService
,
4348 SC_RPC_CONFIG_INFOA Info
)
4350 SC_RPC_CONFIG_INFOW InfoW
;
4351 DWORD dwRet
, dwLength
;
4354 DPRINT("RChangeServiceConfig2A() called\n");
4355 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4357 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4359 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4361 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4362 LPSERVICE_DESCRIPTIONA lpServiceDescriptonA
;
4364 lpServiceDescriptonA
= Info
.psd
;
4366 ///if (lpServiceDescriptonA &&
4367 ///lpServiceDescriptonA->lpDescription)
4369 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4371 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4373 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4374 if (!lpServiceDescriptonW
)
4376 return ERROR_NOT_ENOUGH_MEMORY
;
4379 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4381 MultiByteToWideChar(CP_ACP
,
4385 lpServiceDescriptonW
->lpDescription
,
4388 ptr
= lpServiceDescriptonW
;
4389 InfoW
.psd
= lpServiceDescriptonW
;
4392 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4394 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4395 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4396 DWORD dwRebootLen
= 0;
4397 DWORD dwCommandLen
= 0;
4399 lpServiceFailureActionsA
= Info
.psfa
;
4401 if (lpServiceFailureActionsA
)
4403 if (lpServiceFailureActionsA
->lpRebootMsg
)
4405 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4407 if (lpServiceFailureActionsA
->lpCommand
)
4409 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4411 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4413 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4416 if (!lpServiceFailureActionsW
)
4418 return ERROR_NOT_ENOUGH_MEMORY
;
4421 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4422 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4423 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4425 if (lpServiceFailureActionsA
->lpRebootMsg
)
4427 MultiByteToWideChar(CP_ACP
,
4429 lpServiceFailureActionsA
->lpRebootMsg
,
4431 lpServiceFailureActionsW
->lpRebootMsg
,
4435 if (lpServiceFailureActionsA
->lpCommand
)
4437 MultiByteToWideChar(CP_ACP
,
4439 lpServiceFailureActionsA
->lpCommand
,
4441 lpServiceFailureActionsW
->lpCommand
,
4445 ptr
= lpServiceFailureActionsW
;
4449 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4451 HeapFree(GetProcessHeap(), 0, ptr
);
4458 DWORD
RChangeServiceConfig2W(
4459 SC_RPC_HANDLE hService
,
4460 SC_RPC_CONFIG_INFOW Info
)
4462 DWORD dwError
= ERROR_SUCCESS
;
4463 PSERVICE_HANDLE hSvc
;
4464 PSERVICE lpService
= NULL
;
4465 HKEY hServiceKey
= NULL
;
4467 DPRINT("RChangeServiceConfig2W() called\n");
4468 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4471 return ERROR_SHUTDOWN_IN_PROGRESS
;
4473 hSvc
= ScmGetServiceFromHandle(hService
);
4476 DPRINT1("Invalid service handle!\n");
4477 return ERROR_INVALID_HANDLE
;
4480 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4481 SERVICE_CHANGE_CONFIG
))
4483 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4484 return ERROR_ACCESS_DENIED
;
4487 lpService
= hSvc
->ServiceEntry
;
4488 if (lpService
== NULL
)
4490 DPRINT("lpService == NULL!\n");
4491 return ERROR_INVALID_HANDLE
;
4494 /* Lock the service database exclusively */
4495 ScmLockDatabaseExclusive();
4497 if (lpService
->bDeleted
)
4499 DPRINT("The service has already been marked for delete!\n");
4500 dwError
= ERROR_SERVICE_MARKED_FOR_DELETE
;
4504 /* Open the service key */
4505 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4508 if (dwError
!= ERROR_SUCCESS
)
4511 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4513 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4515 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4516 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4518 if (lpServiceDescription
!= NULL
&&
4519 lpServiceDescription
->lpDescription
!= NULL
)
4521 DPRINT("Setting value %S\n", lpServiceDescription
->lpDescription
);
4522 dwError
= RegSetValueExW(hServiceKey
,
4526 (LPBYTE
)lpServiceDescription
->lpDescription
,
4527 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4528 if (dwError
!= ERROR_SUCCESS
)
4532 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4535 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4540 /* Unlock the service database */
4541 ScmUnlockDatabase();
4543 if (hServiceKey
!= NULL
)
4544 RegCloseKey(hServiceKey
);
4546 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4553 DWORD
RQueryServiceConfig2A(
4554 SC_RPC_HANDLE hService
,
4558 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4560 DWORD dwError
= ERROR_SUCCESS
;
4561 PSERVICE_HANDLE hSvc
;
4562 PSERVICE lpService
= NULL
;
4563 HKEY hServiceKey
= NULL
;
4564 LPWSTR lpDescriptionW
= NULL
;
4565 LPSTR lpDescription
= NULL
;
4567 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4568 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4571 return ERROR_INVALID_ADDRESS
;
4574 return ERROR_SHUTDOWN_IN_PROGRESS
;
4576 hSvc
= ScmGetServiceFromHandle(hService
);
4579 DPRINT1("Invalid service handle!\n");
4580 return ERROR_INVALID_HANDLE
;
4583 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4584 SERVICE_QUERY_CONFIG
))
4586 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4587 return ERROR_ACCESS_DENIED
;
4590 lpService
= hSvc
->ServiceEntry
;
4591 if (lpService
== NULL
)
4593 DPRINT("lpService == NULL!\n");
4594 return ERROR_INVALID_HANDLE
;
4597 /* Lock the service database shared */
4598 ScmLockDatabaseShared();
4600 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4603 if (dwError
!= ERROR_SUCCESS
)
4606 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4608 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4611 dwError
= ScmReadString(hServiceKey
,
4614 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4617 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4618 if (dwError
== ERROR_SUCCESS
)
4619 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4621 if (cbBufSize
< *pcbBytesNeeded
)
4623 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4627 if (dwError
== ERROR_SUCCESS
)
4629 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4631 WideCharToMultiByte(CP_ACP
,
4636 wcslen(lpDescriptionW
),
4639 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4643 lpServiceDescription
->lpDescription
= NULL
;
4644 dwError
= ERROR_SUCCESS
;
4648 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4651 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4656 /* Unlock the service database */
4657 ScmUnlockDatabase();
4659 if (lpDescription
!= NULL
)
4660 HeapFree(GetProcessHeap(), 0, lpDescription
);
4662 if (hServiceKey
!= NULL
)
4663 RegCloseKey(hServiceKey
);
4665 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4672 DWORD
RQueryServiceConfig2W(
4673 SC_RPC_HANDLE hService
,
4677 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4679 DWORD dwError
= ERROR_SUCCESS
;
4680 PSERVICE_HANDLE hSvc
;
4681 PSERVICE lpService
= NULL
;
4682 HKEY hServiceKey
= NULL
;
4683 DWORD dwRequiredSize
;
4684 LPWSTR lpDescription
= NULL
;
4685 LPWSTR lpFailureCommand
= NULL
;
4686 LPWSTR lpRebootMessage
= NULL
;
4688 DPRINT("RQueryServiceConfig2W() called\n");
4691 return ERROR_INVALID_ADDRESS
;
4694 return ERROR_SHUTDOWN_IN_PROGRESS
;
4696 hSvc
= ScmGetServiceFromHandle(hService
);
4699 DPRINT1("Invalid service handle!\n");
4700 return ERROR_INVALID_HANDLE
;
4703 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4704 SERVICE_QUERY_CONFIG
))
4706 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4707 return ERROR_ACCESS_DENIED
;
4710 lpService
= hSvc
->ServiceEntry
;
4711 if (lpService
== NULL
)
4713 DPRINT("lpService == NULL!\n");
4714 return ERROR_INVALID_HANDLE
;
4717 /* Lock the service database shared */
4718 ScmLockDatabaseShared();
4720 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4723 if (dwError
!= ERROR_SUCCESS
)
4726 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4728 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4731 dwError
= ScmReadString(hServiceKey
,
4734 if (dwError
!= ERROR_SUCCESS
&& dwError
!= ERROR_FILE_NOT_FOUND
)
4737 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONW
);
4738 if (dwError
== ERROR_SUCCESS
)
4739 *pcbBytesNeeded
+= ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4741 if (cbBufSize
< *pcbBytesNeeded
)
4743 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4747 if (dwError
== ERROR_SUCCESS
)
4749 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4750 wcscpy(lpStr
, lpDescription
);
4751 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4755 lpServiceDescription
->lpDescription
= NULL
;
4756 dwError
= ERROR_SUCCESS
;
4759 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4762 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
4766 dwError
= ScmReadString(hServiceKey
,
4770 dwError
= ScmReadString(hServiceKey
,
4774 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
4776 if (lpFailureCommand
)
4777 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
4779 if (lpRebootMessage
)
4780 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
4782 if (cbBufSize
< dwRequiredSize
)
4784 *pcbBytesNeeded
= dwRequiredSize
;
4785 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4789 lpFailureActions
->cActions
= 0;
4790 lpFailureActions
->dwResetPeriod
= 0;
4791 lpFailureActions
->lpCommand
= NULL
;
4792 lpFailureActions
->lpRebootMsg
= NULL
;
4793 lpFailureActions
->lpsaActions
= NULL
;
4795 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
4796 if (lpRebootMessage
)
4798 wcscpy(lpStr
, lpRebootMessage
);
4799 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
4800 lpStr
+= wcslen(lpRebootMessage
) + 1;
4803 if (lpFailureCommand
)
4805 wcscpy(lpStr
, lpFailureCommand
);
4806 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
4807 lpStr
+= wcslen(lpRebootMessage
) + 1;
4809 dwError
= STATUS_SUCCESS
;
4814 /* Unlock the service database */
4815 ScmUnlockDatabase();
4817 if (lpDescription
!= NULL
)
4818 HeapFree(GetProcessHeap(), 0, lpDescription
);
4820 if (lpRebootMessage
!= NULL
)
4821 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
4823 if (lpFailureCommand
!= NULL
)
4824 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
4826 if (hServiceKey
!= NULL
)
4827 RegCloseKey(hServiceKey
);
4829 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4836 DWORD
RQueryServiceStatusEx(
4837 SC_RPC_HANDLE hService
,
4838 SC_STATUS_TYPE InfoLevel
,
4841 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4843 LPSERVICE_STATUS_PROCESS lpStatus
;
4844 PSERVICE_HANDLE hSvc
;
4847 DPRINT("RQueryServiceStatusEx() called\n");
4850 return ERROR_SHUTDOWN_IN_PROGRESS
;
4852 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4853 return ERROR_INVALID_LEVEL
;
4855 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4857 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4858 return ERROR_INSUFFICIENT_BUFFER
;
4860 hSvc
= ScmGetServiceFromHandle(hService
);
4863 DPRINT1("Invalid service handle!\n");
4864 return ERROR_INVALID_HANDLE
;
4867 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4868 SERVICE_QUERY_STATUS
))
4870 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4871 return ERROR_ACCESS_DENIED
;
4874 lpService
= hSvc
->ServiceEntry
;
4875 if (lpService
== NULL
)
4877 DPRINT("lpService == NULL!\n");
4878 return ERROR_INVALID_HANDLE
;
4881 /* Lock the service database shared */
4882 ScmLockDatabaseShared();
4884 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4886 /* Return service status information */
4887 RtlCopyMemory(lpStatus
,
4889 sizeof(SERVICE_STATUS
));
4891 lpStatus
->dwProcessId
= (lpService
->lpImage
!= NULL
) ? lpService
->lpImage
->dwProcessId
: 0; /* FIXME */
4892 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4894 /* Unlock the service database */
4895 ScmUnlockDatabase();
4897 return ERROR_SUCCESS
;
4902 DWORD
REnumServicesStatusExA(
4903 SC_RPC_HANDLE hSCManager
,
4904 SC_ENUM_TYPE InfoLevel
,
4905 DWORD dwServiceType
,
4906 DWORD dwServiceState
,
4909 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4910 LPBOUNDED_DWORD_256K lpServicesReturned
,
4911 LPBOUNDED_DWORD_256K lpResumeIndex
,
4912 LPCSTR pszGroupName
)
4914 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
4915 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
4916 LPWSTR lpStringPtrW
;
4918 LPWSTR pszGroupNameW
= NULL
;
4920 DWORD dwServiceCount
;
4922 DPRINT("REnumServicesStatusExA() called\n");
4926 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
4929 DPRINT("Failed to allocate buffer!\n");
4930 return ERROR_NOT_ENOUGH_MEMORY
;
4933 MultiByteToWideChar(CP_ACP
,
4938 strlen(pszGroupName
) + 1);
4941 if ((cbBufSize
> 0) && (lpBuffer
))
4943 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
4946 DPRINT("Failed to allocate buffer!\n");
4947 return ERROR_NOT_ENOUGH_MEMORY
;
4951 dwError
= REnumServicesStatusExW(hSCManager
,
4955 (LPBYTE
)lpStatusPtrW
,
4962 /* if no services were returned then we are Done */
4963 if (*lpServicesReturned
== 0)
4966 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
4967 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
4968 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
4969 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
4970 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4972 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
4974 /* Copy the service name */
4975 WideCharToMultiByte(CP_ACP
,
4980 wcslen(lpStringPtrW
),
4984 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4985 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4986 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4988 /* Copy the display name */
4989 WideCharToMultiByte(CP_ACP
,
4994 wcslen(lpStringPtrW
),
4998 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4999 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
5000 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
5002 /* Copy the status information */
5003 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
5004 &lpStatusPtrW
->ServiceStatusProcess
,
5005 sizeof(SERVICE_STATUS
));
5007 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
5008 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5014 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
5017 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
5019 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
5026 DWORD
REnumServicesStatusExW(
5027 SC_RPC_HANDLE hSCManager
,
5028 SC_ENUM_TYPE InfoLevel
,
5029 DWORD dwServiceType
,
5030 DWORD dwServiceState
,
5033 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
5034 LPBOUNDED_DWORD_256K lpServicesReturned
,
5035 LPBOUNDED_DWORD_256K lpResumeIndex
,
5036 LPCWSTR pszGroupName
)
5038 PMANAGER_HANDLE hManager
;
5040 DWORD dwError
= ERROR_SUCCESS
;
5041 PLIST_ENTRY ServiceEntry
;
5042 PSERVICE CurrentService
;
5044 DWORD dwRequiredSize
;
5045 DWORD dwServiceCount
;
5047 DWORD dwLastResumeCount
= 0;
5048 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
5051 DPRINT("REnumServicesStatusExW() called\n");
5054 return ERROR_SHUTDOWN_IN_PROGRESS
;
5056 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
5057 return ERROR_INVALID_LEVEL
;
5059 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
5060 if (hManager
== NULL
)
5062 DPRINT1("Invalid service manager handle!\n");
5063 return ERROR_INVALID_HANDLE
;
5066 *pcbBytesNeeded
= 0;
5067 *lpServicesReturned
= 0;
5069 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
5071 DPRINT("Not a valid Service Type!\n");
5072 return ERROR_INVALID_PARAMETER
;
5075 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
5077 DPRINT("Not a valid Service State!\n");
5078 return ERROR_INVALID_PARAMETER
;
5081 /* Check access rights */
5082 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
5083 SC_MANAGER_ENUMERATE_SERVICE
))
5085 DPRINT("Insufficient access rights! 0x%lx\n",
5086 hManager
->Handle
.DesiredAccess
);
5087 return ERROR_ACCESS_DENIED
;
5091 dwLastResumeCount
= *lpResumeIndex
;
5093 /* Lock the service database shared */
5094 ScmLockDatabaseShared();
5096 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
5097 if (lpService
== NULL
)
5099 dwError
= ERROR_SUCCESS
;
5106 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5107 ServiceEntry
!= &ServiceListHead
;
5108 ServiceEntry
= ServiceEntry
->Flink
)
5110 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5114 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5117 dwState
= SERVICE_ACTIVE
;
5118 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5119 dwState
= SERVICE_INACTIVE
;
5121 if ((dwState
& dwServiceState
) == 0)
5126 if (*pszGroupName
== 0)
5128 if (CurrentService
->lpGroup
!= NULL
)
5133 if ((CurrentService
->lpGroup
== NULL
) ||
5134 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5139 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5140 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5141 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5143 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5145 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5146 dwRequiredSize
+= dwSize
;
5148 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5152 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5158 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5159 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5162 ServiceEntry
!= &ServiceListHead
;
5163 ServiceEntry
= ServiceEntry
->Flink
)
5165 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5169 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5172 dwState
= SERVICE_ACTIVE
;
5173 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5174 dwState
= SERVICE_INACTIVE
;
5176 if ((dwState
& dwServiceState
) == 0)
5181 if (*pszGroupName
== 0)
5183 if (CurrentService
->lpGroup
!= NULL
)
5188 if ((CurrentService
->lpGroup
== NULL
) ||
5189 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5194 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5195 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5196 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5198 dwError
= ERROR_MORE_DATA
;
5201 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5204 *lpResumeIndex
= dwLastResumeCount
;
5206 *lpServicesReturned
= dwServiceCount
;
5207 *pcbBytesNeeded
= dwRequiredSize
;
5209 /* If there was no services that matched */
5210 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5212 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5216 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5217 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5218 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5221 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5222 ServiceEntry
!= &ServiceListHead
;
5223 ServiceEntry
= ServiceEntry
->Flink
)
5225 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5229 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5232 dwState
= SERVICE_ACTIVE
;
5233 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5234 dwState
= SERVICE_INACTIVE
;
5236 if ((dwState
& dwServiceState
) == 0)
5241 if (*pszGroupName
== 0)
5243 if (CurrentService
->lpGroup
!= NULL
)
5248 if ((CurrentService
->lpGroup
== NULL
) ||
5249 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5254 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5255 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5256 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5258 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5260 /* Copy the service name */
5262 CurrentService
->lpServiceName
);
5263 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5264 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5266 /* Copy the display name */
5268 CurrentService
->lpDisplayName
);
5269 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5270 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5272 /* Copy the status information */
5273 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5274 &CurrentService
->Status
,
5275 sizeof(SERVICE_STATUS
));
5276 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
=
5277 (CurrentService
->lpImage
!= NULL
) ? CurrentService
->lpImage
->dwProcessId
: 0; /* FIXME */
5278 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5281 dwRequiredSize
+= dwSize
;
5291 *pcbBytesNeeded
= 0;
5297 /* Unlock the service database */
5298 ScmUnlockDatabase();
5300 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5307 DWORD
RSendTSMessage(
5308 handle_t BindingHandle
) /* FIXME */
5311 return ERROR_CALL_NOT_IMPLEMENTED
;
5316 DWORD
RCreateServiceWOW64A(
5317 handle_t BindingHandle
,
5318 LPSTR lpServiceName
,
5319 LPSTR lpDisplayName
,
5320 DWORD dwDesiredAccess
,
5321 DWORD dwServiceType
,
5323 DWORD dwErrorControl
,
5324 LPSTR lpBinaryPathName
,
5325 LPSTR lpLoadOrderGroup
,
5327 LPBYTE lpDependencies
,
5329 LPSTR lpServiceStartName
,
5332 LPSC_RPC_HANDLE lpServiceHandle
)
5335 return ERROR_CALL_NOT_IMPLEMENTED
;
5340 DWORD
RCreateServiceWOW64W(
5341 handle_t BindingHandle
,
5342 LPWSTR lpServiceName
,
5343 LPWSTR lpDisplayName
,
5344 DWORD dwDesiredAccess
,
5345 DWORD dwServiceType
,
5347 DWORD dwErrorControl
,
5348 LPWSTR lpBinaryPathName
,
5349 LPWSTR lpLoadOrderGroup
,
5351 LPBYTE lpDependencies
,
5353 LPWSTR lpServiceStartName
,
5356 LPSC_RPC_HANDLE lpServiceHandle
)
5359 return ERROR_CALL_NOT_IMPLEMENTED
;
5364 DWORD
RQueryServiceTagInfo(
5365 handle_t BindingHandle
) /* FIXME */
5368 return ERROR_CALL_NOT_IMPLEMENTED
;
5373 DWORD
RNotifyServiceStatusChange(
5374 SC_RPC_HANDLE hService
,
5375 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5376 GUID
*pClientProcessGuid
,
5377 GUID
*pSCMProcessGuid
,
5378 PBOOL pfCreateRemoteQueue
,
5379 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5382 return ERROR_CALL_NOT_IMPLEMENTED
;
5387 DWORD
RGetNotifyResults(
5388 SC_NOTIFY_RPC_HANDLE hNotify
,
5389 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5392 return ERROR_CALL_NOT_IMPLEMENTED
;
5397 DWORD
RCloseNotifyHandle(
5398 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5402 return ERROR_CALL_NOT_IMPLEMENTED
;
5407 DWORD
RControlServiceExA(
5408 SC_RPC_HANDLE hService
,
5413 return ERROR_CALL_NOT_IMPLEMENTED
;
5418 DWORD
RControlServiceExW(
5419 SC_RPC_HANDLE hService
,
5424 return ERROR_CALL_NOT_IMPLEMENTED
;
5429 DWORD
RSendPnPMessage(
5430 handle_t BindingHandle
) /* FIXME */
5433 return ERROR_CALL_NOT_IMPLEMENTED
;
5438 DWORD
RValidatePnPService(
5439 handle_t BindingHandle
) /* FIXME */
5442 return ERROR_CALL_NOT_IMPLEMENTED
;
5447 DWORD
ROpenServiceStatusHandle(
5448 handle_t BindingHandle
) /* FIXME */
5451 return ERROR_CALL_NOT_IMPLEMENTED
;
5457 handle_t BindingHandle
) /* FIXME */
5460 return ERROR_CALL_NOT_IMPLEMENTED
;
5464 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5466 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5470 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5472 HeapFree(GetProcessHeap(), 0, ptr
);
5476 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5481 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5486 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)