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
);
458 DPRINT("RCloseServiceHandle() done\n");
459 return ERROR_SUCCESS
;
461 else if (hService
!= NULL
)
463 DPRINT("Found service handle\n");
465 /* Get the pointer to the service record */
466 lpService
= hService
->ServiceEntry
;
468 /* FIXME: add handle cleanup code */
470 /* Free the handle */
471 HeapFree(GetProcessHeap(), 0, hService
);
474 ASSERT(lpService
->dwRefCount
> 0);
476 lpService
->dwRefCount
--;
477 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
478 lpService
->dwRefCount
);
480 if (lpService
->dwRefCount
== 0)
482 /* If this service has been marked for deletion */
483 if (lpService
->bDeleted
)
485 /* Open the Services Reg key */
486 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
487 L
"System\\CurrentControlSet\\Services",
489 KEY_SET_VALUE
| KEY_READ
,
491 if (dwError
!= ERROR_SUCCESS
)
493 DPRINT("Failed to open services key\n");
497 /* Call the internal function with NULL, just to get bytes we need */
498 Int_EnumDependentServicesW(hServicesKey
,
503 &dwServicesReturned
);
505 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
508 DPRINT("Deletion failed due to running dependencies.\n");
509 RegCloseKey(hServicesKey
);
510 return ERROR_SUCCESS
;
513 /* There are no references and no runnning dependencies,
514 it is now safe to delete the service */
516 /* Delete the Service Key */
517 dwError
= RegDeleteKeyW(hServicesKey
,
518 lpService
->lpServiceName
);
520 RegCloseKey(hServicesKey
);
522 if (dwError
!= ERROR_SUCCESS
)
524 DPRINT("Failed to Delete the Service Registry key\n");
528 /* Delete the Service */
529 ScmDeleteServiceRecord(lpService
);
533 DPRINT("RCloseServiceHandle() done\n");
534 return ERROR_SUCCESS
;
537 DPRINT("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
539 return ERROR_INVALID_HANDLE
;
544 DWORD
RControlService(
545 SC_RPC_HANDLE hService
,
547 LPSERVICE_STATUS lpServiceStatus
)
549 PSERVICE_HANDLE hSvc
;
551 ACCESS_MASK DesiredAccess
;
552 DWORD dwError
= ERROR_SUCCESS
;
553 DWORD pcbBytesNeeded
= 0;
554 DWORD dwServicesReturned
= 0;
555 DWORD dwControlsAccepted
;
556 DWORD dwCurrentState
;
557 HKEY hServicesKey
= NULL
;
559 DPRINT("RControlService() called\n");
562 return ERROR_SHUTDOWN_IN_PROGRESS
;
564 /* Check the service handle */
565 hSvc
= ScmGetServiceFromHandle(hService
);
568 DPRINT1("Invalid service handle!\n");
569 return ERROR_INVALID_HANDLE
;
573 /* Check the service entry point */
574 lpService
= hSvc
->ServiceEntry
;
575 if (lpService
== NULL
)
577 DPRINT1("lpService == NULL!\n");
578 return ERROR_INVALID_HANDLE
;
581 /* Check access rights */
584 case SERVICE_CONTROL_STOP
:
585 DesiredAccess
= SERVICE_STOP
;
588 case SERVICE_CONTROL_PAUSE
:
589 case SERVICE_CONTROL_CONTINUE
:
590 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
593 case SERVICE_INTERROGATE
:
594 DesiredAccess
= SERVICE_INTERROGATE
;
598 if (dwControl
>= 128 && dwControl
<= 255)
599 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
601 DesiredAccess
= SERVICE_QUERY_CONFIG
|
602 SERVICE_CHANGE_CONFIG
|
603 SERVICE_QUERY_STATUS
|
605 SERVICE_PAUSE_CONTINUE
;
609 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
611 return ERROR_ACCESS_DENIED
;
613 if (dwControl
== SERVICE_CONTROL_STOP
)
615 /* Check if the service has dependencies running as windows
616 doesn't stop a service that does */
618 /* Open the Services Reg key */
619 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
620 L
"System\\CurrentControlSet\\Services",
624 if (dwError
!= ERROR_SUCCESS
)
626 DPRINT("Failed to open services key\n");
630 /* Call the internal function with NULL, just to get bytes we need */
631 Int_EnumDependentServicesW(hServicesKey
,
636 &dwServicesReturned
);
638 RegCloseKey(hServicesKey
);
640 /* If pcbBytesNeeded is not zero then there are services running that
641 are dependent on this service */
642 if (pcbBytesNeeded
!= 0)
644 DPRINT("Service has running dependencies. Failed to stop service.\n");
645 return ERROR_DEPENDENT_SERVICES_RUNNING
;
649 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
651 /* Send control code to the driver */
652 dwError
= ScmControlDriver(lpService
,
658 dwControlsAccepted
= lpService
->Status
.dwControlsAccepted
;
659 dwCurrentState
= lpService
->Status
.dwCurrentState
;
661 /* Check the current state before sending a control request */
662 switch (dwCurrentState
)
664 case SERVICE_STOP_PENDING
:
665 case SERVICE_STOPPED
:
666 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
668 case SERVICE_START_PENDING
:
671 case SERVICE_CONTROL_STOP
:
674 case SERVICE_CONTROL_INTERROGATE
:
675 RtlCopyMemory(lpServiceStatus
,
677 sizeof(SERVICE_STATUS
));
678 return ERROR_SUCCESS
;
681 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
686 /* Check if the control code is acceptable to the service */
689 case SERVICE_CONTROL_STOP
:
690 if ((dwControlsAccepted
& SERVICE_ACCEPT_STOP
) == 0)
691 return ERROR_INVALID_SERVICE_CONTROL
;
694 case SERVICE_CONTROL_PAUSE
:
695 case SERVICE_CONTROL_CONTINUE
:
696 if ((dwControlsAccepted
& SERVICE_ACCEPT_PAUSE_CONTINUE
) == 0)
697 return ERROR_INVALID_SERVICE_CONTROL
;
701 /* Send control code to the service */
702 dwError
= ScmSendServiceCommand(lpService
,
707 /* Return service status information */
708 RtlCopyMemory(lpServiceStatus
,
710 sizeof(SERVICE_STATUS
));
713 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
714 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
716 if (dwError
== ERROR_SUCCESS
&&
717 dwControl
== SERVICE_CONTROL_STOP
&&
718 lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
)
720 lpService
->ProcessId
= 0; /* FIXME */
721 lpService
->ThreadId
= 0;
730 DWORD
RDeleteService(
731 SC_RPC_HANDLE hService
)
733 PSERVICE_HANDLE hSvc
;
737 DPRINT("RDeleteService() called\n");
740 return ERROR_SHUTDOWN_IN_PROGRESS
;
742 hSvc
= ScmGetServiceFromHandle(hService
);
745 DPRINT1("Invalid service handle!\n");
746 return ERROR_INVALID_HANDLE
;
749 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
751 return ERROR_ACCESS_DENIED
;
753 lpService
= hSvc
->ServiceEntry
;
754 if (lpService
== NULL
)
756 DPRINT("lpService == NULL!\n");
757 return ERROR_INVALID_HANDLE
;
760 /* FIXME: Acquire service database lock exclusively */
762 if (lpService
->bDeleted
)
764 DPRINT("The service has already been marked for delete!\n");
765 return ERROR_SERVICE_MARKED_FOR_DELETE
;
768 /* Mark service for delete */
769 lpService
->bDeleted
= TRUE
;
771 dwError
= ScmMarkServiceForDelete(lpService
);
773 /* FIXME: Release service database lock */
775 DPRINT("RDeleteService() done\n");
782 DWORD
RLockServiceDatabase(
783 SC_RPC_HANDLE hSCManager
,
784 LPSC_RPC_LOCK lpLock
)
786 PMANAGER_HANDLE hMgr
;
788 DPRINT("RLockServiceDatabase() called\n");
792 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
795 DPRINT1("Invalid service manager handle!\n");
796 return ERROR_INVALID_HANDLE
;
799 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
801 return ERROR_ACCESS_DENIED
;
803 // return ScmLockDatabase(0, hMgr->0xC, hLock);
805 /* FIXME: Lock the database */
806 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
808 return ERROR_SUCCESS
;
813 DWORD
RQueryServiceObjectSecurity(
814 SC_RPC_HANDLE hService
,
815 SECURITY_INFORMATION dwSecurityInformation
,
816 LPBYTE lpSecurityDescriptor
,
818 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
820 PSERVICE_HANDLE hSvc
;
822 ULONG DesiredAccess
= 0;
828 SECURITY_DESCRIPTOR ObjectDescriptor
;
830 DPRINT("RQueryServiceObjectSecurity() called\n");
832 hSvc
= ScmGetServiceFromHandle(hService
);
835 DPRINT1("Invalid service handle!\n");
836 return ERROR_INVALID_HANDLE
;
839 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
840 GROUP_SECURITY_INFORMATION
||
841 OWNER_SECURITY_INFORMATION
))
842 DesiredAccess
|= READ_CONTROL
;
844 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
845 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
847 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
850 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
851 return ERROR_ACCESS_DENIED
;
854 lpService
= hSvc
->ServiceEntry
;
855 if (lpService
== NULL
)
857 DPRINT("lpService == NULL!\n");
858 return ERROR_INVALID_HANDLE
;
861 /* FIXME: Lock the service list */
864 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
866 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
867 dwSecurityInformation
,
868 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
872 /* FIXME: Unlock the service list */
874 if (NT_SUCCESS(Status
))
876 *pcbBytesNeeded
= dwBytesNeeded
;
877 dwError
= STATUS_SUCCESS
;
879 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
881 *pcbBytesNeeded
= dwBytesNeeded
;
882 dwError
= ERROR_INSUFFICIENT_BUFFER
;
884 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
886 dwError
= ERROR_GEN_FAILURE
;
890 dwError
= RtlNtStatusToDosError(Status
);
898 DWORD
RSetServiceObjectSecurity(
899 SC_RPC_HANDLE hService
,
900 DWORD dwSecurityInformation
,
901 LPBYTE lpSecurityDescriptor
,
902 DWORD dwSecuityDescriptorSize
)
904 PSERVICE_HANDLE hSvc
;
906 ULONG DesiredAccess
= 0;
907 /* HANDLE hToken = NULL; */
909 /* NTSTATUS Status; */
912 DPRINT("RSetServiceObjectSecurity() called\n");
914 hSvc
= ScmGetServiceFromHandle(hService
);
917 DPRINT1("Invalid service handle!\n");
918 return ERROR_INVALID_HANDLE
;
921 if (dwSecurityInformation
== 0 ||
922 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
923 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
924 return ERROR_INVALID_PARAMETER
;
926 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
927 return ERROR_INVALID_PARAMETER
;
929 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
930 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
932 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
933 DesiredAccess
|= WRITE_DAC
;
935 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
936 DesiredAccess
|= WRITE_OWNER
;
938 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
939 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
940 return ERROR_INVALID_PARAMETER
;
942 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
943 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
944 return ERROR_INVALID_PARAMETER
;
946 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
949 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
950 return ERROR_ACCESS_DENIED
;
953 lpService
= hSvc
->ServiceEntry
;
954 if (lpService
== NULL
)
956 DPRINT("lpService == NULL!\n");
957 return ERROR_INVALID_HANDLE
;
960 if (lpService
->bDeleted
)
961 return ERROR_SERVICE_MARKED_FOR_DELETE
;
964 RpcImpersonateClient(NULL
);
966 Status
= NtOpenThreadToken(NtCurrentThread(),
970 if (!NT_SUCCESS(Status
))
971 return RtlNtStatusToDosError(Status
);
975 /* FIXME: Lock service database */
977 Status
= RtlSetSecurityObject(dwSecurityInformation
,
978 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
979 &lpService
->lpSecurityDescriptor
,
982 if (!NT_SUCCESS(Status
))
984 dwError
= RtlNtStatusToDosError(Status
);
989 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
990 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
992 if (dwError
!= ERROR_SUCCESS
)
996 dwError
= ERROR_SUCCESS
;
997 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
998 // lpService->lpSecurityDescriptor);
1000 RegFlushKey(hServiceKey
);
1001 RegCloseKey(hServiceKey
);
1010 /* FIXME: Unlock service database */
1012 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1019 DWORD
RQueryServiceStatus(
1020 SC_RPC_HANDLE hService
,
1021 LPSERVICE_STATUS lpServiceStatus
)
1023 PSERVICE_HANDLE hSvc
;
1026 DPRINT("RQueryServiceStatus() called\n");
1029 return ERROR_SHUTDOWN_IN_PROGRESS
;
1031 hSvc
= ScmGetServiceFromHandle(hService
);
1034 DPRINT1("Invalid service handle!\n");
1035 return ERROR_INVALID_HANDLE
;
1038 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1039 SERVICE_QUERY_STATUS
))
1041 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1042 return ERROR_ACCESS_DENIED
;
1045 lpService
= hSvc
->ServiceEntry
;
1046 if (lpService
== NULL
)
1048 DPRINT("lpService == NULL!\n");
1049 return ERROR_INVALID_HANDLE
;
1052 ScmLockDatabaseShared();
1054 /* Return service status information */
1055 RtlCopyMemory(lpServiceStatus
,
1057 sizeof(SERVICE_STATUS
));
1059 ScmUnlockDatabase();
1061 return ERROR_SUCCESS
;
1066 ScmIsValidServiceState(DWORD dwCurrentState
)
1068 switch (dwCurrentState
)
1070 case SERVICE_STOPPED
:
1071 case SERVICE_START_PENDING
:
1072 case SERVICE_STOP_PENDING
:
1073 case SERVICE_RUNNING
:
1074 case SERVICE_CONTINUE_PENDING
:
1075 case SERVICE_PAUSE_PENDING
:
1076 case SERVICE_PAUSED
:
1086 DWORD
RSetServiceStatus(
1087 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1088 LPSERVICE_STATUS lpServiceStatus
)
1092 DPRINT("RSetServiceStatus() called\n");
1093 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1094 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1095 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1096 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1097 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1098 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1099 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1100 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1102 if (hServiceStatus
== 0)
1104 DPRINT("hServiceStatus == NULL!\n");
1105 return ERROR_INVALID_HANDLE
;
1108 lpService
= (PSERVICE
)hServiceStatus
;
1109 if (lpService
== NULL
)
1111 DPRINT("lpService == NULL!\n");
1112 return ERROR_INVALID_HANDLE
;
1115 /* Check current state */
1116 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1118 DPRINT("Invalid service state!\n");
1119 return ERROR_INVALID_DATA
;
1122 /* Check service type */
1123 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1124 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1126 DPRINT("Invalid service type!\n");
1127 return ERROR_INVALID_DATA
;
1130 /* Check accepted controls */
1131 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1133 DPRINT("Invalid controls accepted!\n");
1134 return ERROR_INVALID_DATA
;
1137 ScmLockDatabaseExclusive();
1139 RtlCopyMemory(&lpService
->Status
,
1141 sizeof(SERVICE_STATUS
));
1143 ScmUnlockDatabase();
1145 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1146 DPRINT("RSetServiceStatus() done\n");
1148 return ERROR_SUCCESS
;
1153 DWORD
RUnlockServiceDatabase(
1157 return ERROR_SUCCESS
;
1162 DWORD
RNotifyBootConfigStatus(
1163 SVCCTL_HANDLEW lpMachineName
,
1164 DWORD BootAcceptable
)
1167 return ERROR_CALL_NOT_IMPLEMENTED
;
1172 DWORD
RI_ScSetServiceBitsW(
1173 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1174 DWORD dwServiceBits
,
1176 int bUpdateImmediately
,
1180 return ERROR_CALL_NOT_IMPLEMENTED
;
1185 DWORD
RChangeServiceConfigW(
1186 SC_RPC_HANDLE hService
,
1187 DWORD dwServiceType
,
1189 DWORD dwErrorControl
,
1190 LPWSTR lpBinaryPathName
,
1191 LPWSTR lpLoadOrderGroup
,
1193 LPBYTE lpDependencies
,
1195 LPWSTR lpServiceStartName
,
1198 LPWSTR lpDisplayName
)
1200 DWORD dwError
= ERROR_SUCCESS
;
1201 PSERVICE_HANDLE hSvc
;
1202 PSERVICE lpService
= NULL
;
1203 HKEY hServiceKey
= NULL
;
1204 LPWSTR lpDisplayNameW
= NULL
;
1206 DPRINT("RChangeServiceConfigW() called\n");
1207 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1208 DPRINT("dwStartType = %lu\n", dwStartType
);
1209 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1210 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1211 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1212 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1215 return ERROR_SHUTDOWN_IN_PROGRESS
;
1217 hSvc
= ScmGetServiceFromHandle(hService
);
1220 DPRINT1("Invalid service handle!\n");
1221 return ERROR_INVALID_HANDLE
;
1224 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1225 SERVICE_CHANGE_CONFIG
))
1227 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1228 return ERROR_ACCESS_DENIED
;
1231 lpService
= hSvc
->ServiceEntry
;
1232 if (lpService
== NULL
)
1234 DPRINT("lpService == NULL!\n");
1235 return ERROR_INVALID_HANDLE
;
1238 /* FIXME: Lock database exclusively */
1240 if (lpService
->bDeleted
)
1242 /* FIXME: Unlock database */
1243 DPRINT("The service has already been marked for delete!\n");
1244 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1247 /* Open the service key */
1248 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1251 if (dwError
!= ERROR_SUCCESS
)
1254 /* Write service data to the registry */
1255 /* Set the display name */
1256 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1258 RegSetValueExW(hServiceKey
,
1262 (LPBYTE
)lpDisplayName
,
1263 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1265 /* Update the display name */
1266 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1268 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1269 if (lpDisplayNameW
== NULL
)
1271 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1275 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1276 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1278 lpService
->lpDisplayName
= lpDisplayNameW
;
1281 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1283 /* Set the service type */
1284 dwError
= RegSetValueExW(hServiceKey
,
1288 (LPBYTE
)&dwServiceType
,
1290 if (dwError
!= ERROR_SUCCESS
)
1293 lpService
->Status
.dwServiceType
= dwServiceType
;
1296 if (dwStartType
!= SERVICE_NO_CHANGE
)
1298 /* Set the start value */
1299 dwError
= RegSetValueExW(hServiceKey
,
1303 (LPBYTE
)&dwStartType
,
1305 if (dwError
!= ERROR_SUCCESS
)
1308 lpService
->dwStartType
= dwStartType
;
1311 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1313 /* Set the error control value */
1314 dwError
= RegSetValueExW(hServiceKey
,
1318 (LPBYTE
)&dwErrorControl
,
1320 if (dwError
!= ERROR_SUCCESS
)
1323 lpService
->dwErrorControl
= dwErrorControl
;
1327 /* FIXME: set the new ImagePath value */
1329 /* Set the image path */
1330 if (dwServiceType
& SERVICE_WIN32
)
1332 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1334 dwError
= RegSetValueExW(hServiceKey
,
1338 (LPBYTE
)lpBinaryPathName
,
1339 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1340 if (dwError
!= ERROR_SUCCESS
)
1344 else if (dwServiceType
& SERVICE_DRIVER
)
1346 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1348 dwError
= RegSetValueExW(hServiceKey
,
1352 (LPBYTE
)lpImagePath
,
1353 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1354 if (dwError
!= ERROR_SUCCESS
)
1360 /* Set the group name */
1361 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1363 dwError
= RegSetValueExW(hServiceKey
,
1367 (LPBYTE
)lpLoadOrderGroup
,
1368 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1369 if (dwError
!= ERROR_SUCCESS
)
1372 dwError
= ScmSetServiceGroup(lpService
,
1374 if (dwError
!= ERROR_SUCCESS
)
1378 if (lpdwTagId
!= NULL
)
1380 dwError
= ScmAssignNewTag(lpService
);
1381 if (dwError
!= ERROR_SUCCESS
)
1384 dwError
= RegSetValueExW(hServiceKey
,
1388 (LPBYTE
)&lpService
->dwTag
,
1390 if (dwError
!= ERROR_SUCCESS
)
1393 *lpdwTagId
= lpService
->dwTag
;
1396 /* Write dependencies */
1397 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1399 dwError
= ScmWriteDependencies(hServiceKey
,
1400 (LPWSTR
)lpDependencies
,
1402 if (dwError
!= ERROR_SUCCESS
)
1406 if (lpPassword
!= NULL
)
1408 /* FIXME: Write password */
1411 /* FIXME: Unlock database */
1414 if (hServiceKey
!= NULL
)
1415 RegCloseKey(hServiceKey
);
1417 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1423 /* Create a path suitable for the bootloader out of the full path */
1425 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1427 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1430 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1431 OBJECT_ATTRIBUTES ObjectAttributes
;
1433 HANDLE SymbolicLinkHandle
;
1435 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1437 ServiceNameLen
= wcslen(CanonName
);
1439 /* First check, if it's already good */
1440 if (ServiceNameLen
> 12 &&
1441 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1443 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1444 if (*RelativeName
== NULL
)
1446 DPRINT("Error allocating memory for boot driver name!\n");
1447 return ERROR_NOT_ENOUGH_MEMORY
;
1451 wcscpy(*RelativeName
, CanonName
);
1453 DPRINT("Bootdriver name %S\n", *RelativeName
);
1454 return ERROR_SUCCESS
;
1457 /* If it has %SystemRoot% prefix, substitute it to \System*/
1458 if (ServiceNameLen
> 13 &&
1459 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1461 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1462 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1464 if (*RelativeName
== NULL
)
1466 DPRINT("Error allocating memory for boot driver name!\n");
1467 return ERROR_NOT_ENOUGH_MEMORY
;
1471 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1472 wcscat(*RelativeName
, CanonName
+ 13);
1474 DPRINT("Bootdriver name %S\n", *RelativeName
);
1475 return ERROR_SUCCESS
;
1478 /* Get buffer size needed for expanding env strings */
1479 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1481 if (BufferSize
<= 1)
1483 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1484 return ERROR_INVALID_ENVIRONMENT
;
1487 /* Allocate memory, since the size is known now */
1488 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1491 DPRINT("Error allocating memory for boot driver name!\n");
1492 return ERROR_NOT_ENOUGH_MEMORY
;
1496 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1499 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1500 LocalFree(Expanded
);
1501 return ERROR_NOT_ENOUGH_MEMORY
;
1504 /* Convert to NY-style path */
1505 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1507 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1508 return ERROR_INVALID_ENVIRONMENT
;
1511 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1513 /* No need to keep the dos-path anymore */
1514 LocalFree(Expanded
);
1516 /* Copy it to the allocated place */
1517 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1520 DPRINT("Error allocating memory for boot driver name!\n");
1521 return ERROR_NOT_ENOUGH_MEMORY
;
1524 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1525 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1526 Expanded
[ExpandedLen
] = 0;
1528 if (ServiceNameLen
> ExpandedLen
&&
1529 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1531 /* Only \SystemRoot\ is missing */
1532 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1533 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1534 if (*RelativeName
== NULL
)
1536 DPRINT("Error allocating memory for boot driver name!\n");
1537 LocalFree(Expanded
);
1538 return ERROR_NOT_ENOUGH_MEMORY
;
1541 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1542 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1544 RtlFreeUnicodeString(&NtPathName
);
1545 return ERROR_SUCCESS
;
1548 /* The most complex case starts here */
1549 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1550 InitializeObjectAttributes(&ObjectAttributes
,
1552 OBJ_CASE_INSENSITIVE
,
1556 /* Open this symlink */
1557 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1559 if (NT_SUCCESS(Status
))
1561 LinkTarget
.Length
= 0;
1562 LinkTarget
.MaximumLength
= 0;
1564 DPRINT("Opened symbolic link object\n");
1566 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1567 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1569 /* Check if required buffer size is sane */
1570 if (BufferSize
> 0xFFFD)
1572 DPRINT("Too large buffer required\n");
1575 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1576 LocalFree(Expanded
);
1577 return ERROR_NOT_ENOUGH_MEMORY
;
1580 /* Alloc the string */
1581 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1582 if (!LinkTarget
.Buffer
)
1584 DPRINT("Unable to alloc buffer\n");
1585 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1586 LocalFree(Expanded
);
1587 return ERROR_NOT_ENOUGH_MEMORY
;
1590 /* Do a real query now */
1591 LinkTarget
.Length
= BufferSize
;
1592 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1594 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1595 if (NT_SUCCESS(Status
))
1597 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1599 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1600 if ((ServiceNameLen
> ExpandedLen
) &&
1601 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1603 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1604 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1606 if (*RelativeName
== NULL
)
1608 DPRINT("Unable to alloc buffer\n");
1609 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1610 LocalFree(Expanded
);
1611 RtlFreeUnicodeString(&NtPathName
);
1612 return ERROR_NOT_ENOUGH_MEMORY
;
1615 /* Copy it over, substituting the first part
1617 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1618 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1621 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1622 LocalFree(Expanded
);
1623 RtlFreeUnicodeString(&NtPathName
);
1625 /* Return success */
1626 return ERROR_SUCCESS
;
1630 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1631 LocalFree(Expanded
);
1632 RtlFreeUnicodeString(&NtPathName
);
1633 return ERROR_INVALID_PARAMETER
;
1638 DPRINT("Error, Status = %08X\n", Status
);
1639 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1640 LocalFree(Expanded
);
1641 RtlFreeUnicodeString(&NtPathName
);
1642 return ERROR_INVALID_PARAMETER
;
1647 DPRINT("Error, Status = %08X\n", Status
);
1648 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1649 LocalFree(Expanded
);
1650 RtlFreeUnicodeString(&NtPathName
);
1651 return ERROR_INVALID_PARAMETER
;
1656 DPRINT("Error, Status = %08X\n", Status
);
1657 LocalFree(Expanded
);
1658 return ERROR_INVALID_PARAMETER
;
1662 *RelativeName
= NULL
;
1663 return ERROR_INVALID_PARAMETER
;
1667 ScmCanonDriverImagePath(DWORD dwStartType
,
1668 const wchar_t *lpServiceName
,
1669 wchar_t **lpCanonName
)
1671 DWORD ServiceNameLen
, Result
;
1672 UNICODE_STRING NtServiceName
;
1673 WCHAR
*RelativeName
;
1674 const WCHAR
*SourceName
= lpServiceName
;
1676 /* Calculate the length of the service's name */
1677 ServiceNameLen
= wcslen(lpServiceName
);
1679 /* 12 is wcslen(L"\\SystemRoot\\") */
1680 if (ServiceNameLen
> 12 &&
1681 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1683 /* SystemRoot prefix is already included */
1685 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1687 if (*lpCanonName
== NULL
)
1689 DPRINT("Error allocating memory for canonized service name!\n");
1690 return ERROR_NOT_ENOUGH_MEMORY
;
1693 /* If it's a boot-time driver, it must be systemroot relative */
1694 if (dwStartType
== SERVICE_BOOT_START
)
1698 wcscpy(*lpCanonName
, SourceName
);
1700 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1704 /* Check if it has %SystemRoot% (len=13) */
1705 if (ServiceNameLen
> 13 &&
1706 !_wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1708 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1709 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1711 if (*lpCanonName
== NULL
)
1713 DPRINT("Error allocating memory for canonized service name!\n");
1714 return ERROR_NOT_ENOUGH_MEMORY
;
1717 /* If it's a boot-time driver, it must be systemroot relative */
1718 if (dwStartType
== SERVICE_BOOT_START
)
1719 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1721 wcscat(*lpCanonName
, lpServiceName
+ 13);
1723 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1727 /* Check if it's a relative path name */
1728 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1730 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1732 if (*lpCanonName
== NULL
)
1734 DPRINT("Error allocating memory for canonized service name!\n");
1735 return ERROR_NOT_ENOUGH_MEMORY
;
1738 /* Just copy it over without changing */
1739 wcscpy(*lpCanonName
, lpServiceName
);
1744 /* It seems to be a DOS path, convert it */
1745 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1747 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
1748 return ERROR_INVALID_PARAMETER
;
1751 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1753 if (*lpCanonName
== NULL
)
1755 DPRINT("Error allocating memory for canonized service name!\n");
1756 RtlFreeUnicodeString(&NtServiceName
);
1757 return ERROR_NOT_ENOUGH_MEMORY
;
1760 /* Copy the string */
1761 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1763 /* The unicode string is not needed anymore */
1764 RtlFreeUnicodeString(&NtServiceName
);
1766 if (dwStartType
!= SERVICE_BOOT_START
)
1768 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1772 /* The service is boot-started, so must be relative */
1773 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1776 /* There is a problem, free name and return */
1777 LocalFree(*lpCanonName
);
1778 DPRINT("Error converting named!\n");
1782 ASSERT(RelativeName
);
1784 /* Copy that string */
1785 wcscpy(*lpCanonName
, RelativeName
+ 12);
1787 /* Free the allocated buffer */
1788 LocalFree(RelativeName
);
1790 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1798 DWORD
RCreateServiceW(
1799 SC_RPC_HANDLE hSCManager
,
1800 LPCWSTR lpServiceName
,
1801 LPCWSTR lpDisplayName
,
1802 DWORD dwDesiredAccess
,
1803 DWORD dwServiceType
,
1805 DWORD dwErrorControl
,
1806 LPCWSTR lpBinaryPathName
,
1807 LPCWSTR lpLoadOrderGroup
,
1809 LPBYTE lpDependencies
,
1811 LPCWSTR lpServiceStartName
,
1814 LPSC_RPC_HANDLE lpServiceHandle
)
1816 PMANAGER_HANDLE hManager
;
1817 DWORD dwError
= ERROR_SUCCESS
;
1818 PSERVICE lpService
= NULL
;
1819 SC_HANDLE hServiceHandle
= NULL
;
1820 LPWSTR lpImagePath
= NULL
;
1821 HKEY hServiceKey
= NULL
;
1822 LPWSTR lpObjectName
;
1824 DPRINT("RCreateServiceW() called\n");
1825 DPRINT("lpServiceName = %S\n", lpServiceName
);
1826 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1827 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1828 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1829 DPRINT("dwStartType = %lu\n", dwStartType
);
1830 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1831 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1832 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1835 return ERROR_SHUTDOWN_IN_PROGRESS
;
1837 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
1838 if (hManager
== NULL
)
1840 DPRINT1("Invalid service manager handle!\n");
1841 return ERROR_INVALID_HANDLE
;
1844 /* Check access rights */
1845 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1846 SC_MANAGER_CREATE_SERVICE
))
1848 DPRINT("Insufficient access rights! 0x%lx\n",
1849 hManager
->Handle
.DesiredAccess
);
1850 return ERROR_ACCESS_DENIED
;
1853 if (wcslen(lpServiceName
) == 0)
1855 return ERROR_INVALID_NAME
;
1858 if (wcslen(lpBinaryPathName
) == 0)
1860 return ERROR_INVALID_PARAMETER
;
1863 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1864 (lpServiceStartName
))
1866 return ERROR_INVALID_PARAMETER
;
1869 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1870 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1871 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1873 return ERROR_INVALID_PARAMETER
;
1876 if (dwStartType
> SERVICE_DISABLED
)
1878 return ERROR_INVALID_PARAMETER
;
1881 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1884 /* check if it is marked for deletion */
1885 if (lpService
->bDeleted
)
1886 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1887 /* Return Error exist */
1888 return ERROR_SERVICE_EXISTS
;
1891 if (lpDisplayName
!= NULL
&&
1892 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1893 return ERROR_DUPLICATE_SERVICE_NAME
;
1895 if (dwServiceType
& SERVICE_DRIVER
)
1897 dwError
= ScmCanonDriverImagePath(dwStartType
,
1900 if (dwError
!= ERROR_SUCCESS
)
1905 if (dwStartType
== SERVICE_BOOT_START
||
1906 dwStartType
== SERVICE_SYSTEM_START
)
1908 return ERROR_INVALID_PARAMETER
;
1912 /* Allocate a new service entry */
1913 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1915 if (dwError
!= ERROR_SUCCESS
)
1918 /* Fill the new service entry */
1919 lpService
->Status
.dwServiceType
= dwServiceType
;
1920 lpService
->dwStartType
= dwStartType
;
1921 lpService
->dwErrorControl
= dwErrorControl
;
1923 /* Fill the display name */
1924 if (lpDisplayName
!= NULL
&&
1925 *lpDisplayName
!= 0 &&
1926 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1928 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1929 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1930 if (lpService
->lpDisplayName
== NULL
)
1932 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1935 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1938 /* Assign the service to a group */
1939 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1941 dwError
= ScmSetServiceGroup(lpService
,
1943 if (dwError
!= ERROR_SUCCESS
)
1947 /* Assign a new tag */
1948 if (lpdwTagId
!= NULL
)
1950 dwError
= ScmAssignNewTag(lpService
);
1951 if (dwError
!= ERROR_SUCCESS
)
1955 /* Write service data to the registry */
1956 /* Create the service key */
1957 dwError
= ScmCreateServiceKey(lpServiceName
,
1960 if (dwError
!= ERROR_SUCCESS
)
1963 /* Set the display name */
1964 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1966 RegSetValueExW(hServiceKey
,
1970 (LPBYTE
)lpDisplayName
,
1971 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1974 /* Set the service type */
1975 dwError
= RegSetValueExW(hServiceKey
,
1979 (LPBYTE
)&dwServiceType
,
1981 if (dwError
!= ERROR_SUCCESS
)
1984 /* Set the start value */
1985 dwError
= RegSetValueExW(hServiceKey
,
1989 (LPBYTE
)&dwStartType
,
1991 if (dwError
!= ERROR_SUCCESS
)
1994 /* Set the error control value */
1995 dwError
= RegSetValueExW(hServiceKey
,
1999 (LPBYTE
)&dwErrorControl
,
2001 if (dwError
!= ERROR_SUCCESS
)
2004 /* Set the image path */
2005 if (dwServiceType
& SERVICE_WIN32
)
2007 dwError
= RegSetValueExW(hServiceKey
,
2011 (LPBYTE
)lpBinaryPathName
,
2012 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
2013 if (dwError
!= ERROR_SUCCESS
)
2016 else if (dwServiceType
& SERVICE_DRIVER
)
2018 dwError
= RegSetValueExW(hServiceKey
,
2022 (LPBYTE
)lpImagePath
,
2023 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2024 if (dwError
!= ERROR_SUCCESS
)
2028 /* Set the group name */
2029 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2031 dwError
= RegSetValueExW(hServiceKey
,
2035 (LPBYTE
)lpLoadOrderGroup
,
2036 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
2037 if (dwError
!= ERROR_SUCCESS
)
2041 if (lpdwTagId
!= NULL
)
2043 dwError
= RegSetValueExW(hServiceKey
,
2047 (LPBYTE
)&lpService
->dwTag
,
2049 if (dwError
!= ERROR_SUCCESS
)
2053 /* Write dependencies */
2054 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2056 dwError
= ScmWriteDependencies(hServiceKey
,
2057 (LPWSTR
)lpDependencies
,
2059 if (dwError
!= ERROR_SUCCESS
)
2063 /* Write service start name */
2064 if (dwServiceType
& SERVICE_WIN32
)
2066 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2067 dwError
= RegSetValueExW(hServiceKey
,
2071 (LPBYTE
)lpObjectName
,
2072 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
2073 if (dwError
!= ERROR_SUCCESS
)
2077 if (lpPassword
!= NULL
)
2079 /* FIXME: Write password */
2082 dwError
= ScmCreateServiceHandle(lpService
,
2084 if (dwError
!= ERROR_SUCCESS
)
2087 dwError
= ScmCheckAccess(hServiceHandle
,
2089 if (dwError
!= ERROR_SUCCESS
)
2092 lpService
->dwRefCount
= 1;
2093 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2096 if (hServiceKey
!= NULL
)
2097 RegCloseKey(hServiceKey
);
2099 if (dwError
== ERROR_SUCCESS
)
2101 DPRINT("hService %p\n", hServiceHandle
);
2102 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2104 if (lpdwTagId
!= NULL
)
2105 *lpdwTagId
= lpService
->dwTag
;
2109 /* Release the display name buffer */
2110 if (lpService
->lpServiceName
!= NULL
)
2111 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2115 /* Remove the service handle */
2116 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2119 if (lpService
!= NULL
)
2121 /* FIXME: remove the service entry */
2125 if (lpImagePath
!= NULL
)
2126 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2128 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2135 DWORD
REnumDependentServicesW(
2136 SC_RPC_HANDLE hService
,
2137 DWORD dwServiceState
,
2140 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2141 LPBOUNDED_DWORD_256K lpServicesReturned
)
2143 DWORD dwError
= ERROR_SUCCESS
;
2144 DWORD dwServicesReturned
= 0;
2145 DWORD dwServiceCount
;
2146 HKEY hServicesKey
= NULL
;
2147 PSERVICE_HANDLE hSvc
;
2148 PSERVICE lpService
= NULL
;
2149 PSERVICE
*lpServicesArray
= NULL
;
2150 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2153 *pcbBytesNeeded
= 0;
2154 *lpServicesReturned
= 0;
2156 DPRINT("REnumDependentServicesW() called\n");
2158 hSvc
= ScmGetServiceFromHandle(hService
);
2161 DPRINT1("Invalid service handle!\n");
2162 return ERROR_INVALID_HANDLE
;
2165 lpService
= hSvc
->ServiceEntry
;
2167 /* Check access rights */
2168 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2169 SC_MANAGER_ENUMERATE_SERVICE
))
2171 DPRINT("Insufficient access rights! 0x%lx\n",
2172 hSvc
->Handle
.DesiredAccess
);
2173 return ERROR_ACCESS_DENIED
;
2176 /* Open the Services Reg key */
2177 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2178 L
"System\\CurrentControlSet\\Services",
2182 if (dwError
!= ERROR_SUCCESS
)
2185 /* First determine the bytes needed and get the number of dependent services */
2186 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2191 &dwServicesReturned
);
2192 if (dwError
!= ERROR_SUCCESS
)
2195 /* If buffer size is less than the bytes needed or pointer is null */
2196 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2198 dwError
= ERROR_MORE_DATA
;
2202 /* Allocate memory for array of service pointers */
2203 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2205 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2206 if (!lpServicesArray
)
2208 DPRINT("Could not allocate a buffer!!\n");
2209 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2213 dwServicesReturned
= 0;
2214 *pcbBytesNeeded
= 0;
2216 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2221 &dwServicesReturned
);
2222 if (dwError
!= ERROR_SUCCESS
)
2227 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2228 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2230 /* Copy EnumDepenedentService to Buffer */
2231 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2233 lpService
= lpServicesArray
[dwServiceCount
];
2235 /* Copy status info */
2236 memcpy(&lpServicesPtr
->ServiceStatus
,
2238 sizeof(SERVICE_STATUS
));
2240 /* Copy display name */
2241 wcscpy(lpStr
, lpService
->lpDisplayName
);
2242 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2243 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2245 /* Copy service name */
2246 wcscpy(lpStr
, lpService
->lpServiceName
);
2247 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2248 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2253 *lpServicesReturned
= dwServicesReturned
;
2256 if (lpServicesArray
!= NULL
)
2257 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2259 RegCloseKey(hServicesKey
);
2261 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2268 DWORD
REnumServicesStatusW(
2269 SC_RPC_HANDLE hSCManager
,
2270 DWORD dwServiceType
,
2271 DWORD dwServiceState
,
2274 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2275 LPBOUNDED_DWORD_256K lpServicesReturned
,
2276 LPBOUNDED_DWORD_256K lpResumeHandle
)
2278 PMANAGER_HANDLE hManager
;
2280 DWORD dwError
= ERROR_SUCCESS
;
2281 PLIST_ENTRY ServiceEntry
;
2282 PSERVICE CurrentService
;
2284 DWORD dwRequiredSize
;
2285 DWORD dwServiceCount
;
2287 DWORD dwLastResumeCount
= 0;
2288 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2291 DPRINT("REnumServicesStatusW() called\n");
2294 return ERROR_SHUTDOWN_IN_PROGRESS
;
2296 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2297 if (hManager
== NULL
)
2299 DPRINT1("Invalid service manager handle!\n");
2300 return ERROR_INVALID_HANDLE
;
2304 *pcbBytesNeeded
= 0;
2305 *lpServicesReturned
= 0;
2307 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2309 DPRINT("Not a valid Service Type!\n");
2310 return ERROR_INVALID_PARAMETER
;
2313 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2315 DPRINT("Not a valid Service State!\n");
2316 return ERROR_INVALID_PARAMETER
;
2319 /* Check access rights */
2320 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2321 SC_MANAGER_ENUMERATE_SERVICE
))
2323 DPRINT("Insufficient access rights! 0x%lx\n",
2324 hManager
->Handle
.DesiredAccess
);
2325 return ERROR_ACCESS_DENIED
;
2329 dwLastResumeCount
= *lpResumeHandle
;
2331 /* FIXME: Lock the service list shared */
2333 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2334 if (lpService
== NULL
)
2336 dwError
= ERROR_SUCCESS
;
2343 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2344 ServiceEntry
!= &ServiceListHead
;
2345 ServiceEntry
= ServiceEntry
->Flink
)
2347 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2351 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2354 dwState
= SERVICE_ACTIVE
;
2355 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2356 dwState
= SERVICE_INACTIVE
;
2358 if ((dwState
& dwServiceState
) == 0)
2361 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2362 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2363 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2365 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2367 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2371 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2372 dwRequiredSize
+= dwSize
;
2374 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2377 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2378 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2381 ServiceEntry
!= &ServiceListHead
;
2382 ServiceEntry
= ServiceEntry
->Flink
)
2384 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2388 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2391 dwState
= SERVICE_ACTIVE
;
2392 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2393 dwState
= SERVICE_INACTIVE
;
2395 if ((dwState
& dwServiceState
) == 0)
2398 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2399 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2400 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2402 dwError
= ERROR_MORE_DATA
;
2405 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2408 *lpResumeHandle
= dwLastResumeCount
;
2410 *lpServicesReturned
= dwServiceCount
;
2411 *pcbBytesNeeded
= dwRequiredSize
;
2413 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2414 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2415 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2418 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2419 ServiceEntry
!= &ServiceListHead
;
2420 ServiceEntry
= ServiceEntry
->Flink
)
2422 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2426 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2429 dwState
= SERVICE_ACTIVE
;
2430 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2431 dwState
= SERVICE_INACTIVE
;
2433 if ((dwState
& dwServiceState
) == 0)
2436 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2437 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2438 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2440 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2443 /* Copy the service name */
2444 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2445 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2446 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2448 /* Copy the display name */
2449 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2450 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2451 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2453 /* Copy the status information */
2454 memcpy(&lpStatusPtr
->ServiceStatus
,
2455 &CurrentService
->Status
,
2456 sizeof(SERVICE_STATUS
));
2459 dwRequiredSize
+= dwSize
;
2464 *pcbBytesNeeded
= 0;
2465 if (lpResumeHandle
) *lpResumeHandle
= 0;
2469 /* FIXME: Unlock the service list */
2471 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2478 DWORD
ROpenSCManagerW(
2479 LPWSTR lpMachineName
,
2480 LPWSTR lpDatabaseName
,
2481 DWORD dwDesiredAccess
,
2482 LPSC_RPC_HANDLE lpScHandle
)
2487 DPRINT("ROpenSCManagerW() called\n");
2488 DPRINT("lpMachineName = %p\n", lpMachineName
);
2489 DPRINT("lpMachineName: %S\n", lpMachineName
);
2490 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2491 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2492 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2495 return ERROR_SHUTDOWN_IN_PROGRESS
;
2498 return ERROR_INVALID_PARAMETER
;
2500 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2502 if (dwError
!= ERROR_SUCCESS
)
2504 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2508 /* Check the desired access */
2509 dwError
= ScmCheckAccess(hHandle
,
2510 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2511 if (dwError
!= ERROR_SUCCESS
)
2513 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2514 HeapFree(GetProcessHeap(), 0, hHandle
);
2518 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2519 DPRINT("*hScm = %p\n", *lpScHandle
);
2521 DPRINT("ROpenSCManagerW() done\n");
2523 return ERROR_SUCCESS
;
2528 DWORD
ROpenServiceW(
2529 SC_RPC_HANDLE hSCManager
,
2530 LPWSTR lpServiceName
,
2531 DWORD dwDesiredAccess
,
2532 LPSC_RPC_HANDLE lpServiceHandle
)
2535 PMANAGER_HANDLE hManager
;
2539 DPRINT("ROpenServiceW() called\n");
2540 DPRINT("hSCManager = %p\n", hSCManager
);
2541 DPRINT("lpServiceName = %p\n", lpServiceName
);
2542 DPRINT("lpServiceName: %S\n", lpServiceName
);
2543 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2546 return ERROR_SHUTDOWN_IN_PROGRESS
;
2548 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2549 if (hManager
== NULL
)
2551 DPRINT1("Invalid service manager handle!\n");
2552 return ERROR_INVALID_HANDLE
;
2555 if (!lpServiceHandle
)
2556 return ERROR_INVALID_PARAMETER
;
2559 return ERROR_INVALID_ADDRESS
;
2561 /* FIXME: Lock the service list */
2563 /* Get service database entry */
2564 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2565 if (lpService
== NULL
)
2567 DPRINT("Could not find a service!\n");
2568 return ERROR_SERVICE_DOES_NOT_EXIST
;
2571 /* Create a service handle */
2572 dwError
= ScmCreateServiceHandle(lpService
,
2574 if (dwError
!= ERROR_SUCCESS
)
2576 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2580 /* Check the desired access */
2581 dwError
= ScmCheckAccess(hHandle
,
2583 if (dwError
!= ERROR_SUCCESS
)
2585 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2586 HeapFree(GetProcessHeap(), 0, hHandle
);
2590 lpService
->dwRefCount
++;
2591 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2593 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2594 DPRINT("*hService = %p\n", *lpServiceHandle
);
2596 DPRINT("ROpenServiceW() done\n");
2598 return ERROR_SUCCESS
;
2603 DWORD
RQueryServiceConfigW(
2604 SC_RPC_HANDLE hService
,
2605 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2607 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2609 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2610 DWORD dwError
= ERROR_SUCCESS
;
2611 PSERVICE_HANDLE hSvc
;
2612 PSERVICE lpService
= NULL
;
2613 HKEY hServiceKey
= NULL
;
2614 LPWSTR lpImagePath
= NULL
;
2615 LPWSTR lpServiceStartName
= NULL
;
2616 LPWSTR lpDependencies
= NULL
;
2617 DWORD dwDependenciesLength
= 0;
2618 DWORD dwRequiredSize
;
2619 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2620 WCHAR lpEmptyString
[] = {0,0};
2623 DPRINT("RQueryServiceConfigW() called\n");
2626 return ERROR_SHUTDOWN_IN_PROGRESS
;
2628 hSvc
= ScmGetServiceFromHandle(hService
);
2631 DPRINT1("Invalid service handle!\n");
2632 return ERROR_INVALID_HANDLE
;
2635 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2636 SERVICE_QUERY_CONFIG
))
2638 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2639 return ERROR_ACCESS_DENIED
;
2642 lpService
= hSvc
->ServiceEntry
;
2643 if (lpService
== NULL
)
2645 DPRINT("lpService == NULL!\n");
2646 return ERROR_INVALID_HANDLE
;
2649 /* FIXME: Lock the service database shared */
2651 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2654 if (dwError
!= ERROR_SUCCESS
)
2657 /* Read the image path */
2658 dwError
= ScmReadString(hServiceKey
,
2661 if (dwError
!= ERROR_SUCCESS
)
2664 /* Read the service start name */
2665 ScmReadString(hServiceKey
,
2667 &lpServiceStartName
);
2669 /* Read the dependencies */
2670 ScmReadDependencies(hServiceKey
,
2672 &dwDependenciesLength
);
2674 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2676 if (lpImagePath
!= NULL
)
2677 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2679 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2681 if (lpService
->lpGroup
!= NULL
)
2682 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2684 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2686 if (lpDependencies
!= NULL
)
2687 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2689 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2691 if (lpServiceStartName
!= NULL
)
2692 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2694 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2696 if (lpService
->lpDisplayName
!= NULL
)
2697 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2699 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2701 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2703 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2707 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2708 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2709 lpConfig
->dwStartType
= lpService
->dwStartType
;
2710 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2711 lpConfig
->dwTagId
= lpService
->dwTag
;
2713 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2715 /* Append the image path */
2716 if (lpImagePath
!= NULL
)
2718 wcscpy(lpStr
, lpImagePath
);
2722 wcscpy(lpStr
, lpEmptyString
);
2725 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2726 lpStr
+= (wcslen(lpStr
) + 1);
2728 /* Append the group name */
2729 if (lpService
->lpGroup
!= NULL
)
2731 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2735 wcscpy(lpStr
, lpEmptyString
);
2738 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2739 lpStr
+= (wcslen(lpStr
) + 1);
2741 /* Append Dependencies */
2742 if (lpDependencies
!= NULL
)
2746 dwDependenciesLength
* sizeof(WCHAR
));
2750 wcscpy(lpStr
, lpEmptyString
);
2753 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2754 if (lpDependencies
!= NULL
)
2755 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2757 lpStr
+= (wcslen(lpStr
) + 1);
2759 /* Append the service start name */
2760 if (lpServiceStartName
!= NULL
)
2762 wcscpy(lpStr
, lpServiceStartName
);
2766 wcscpy(lpStr
, lpEmptyString
);
2769 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2770 lpStr
+= (wcslen(lpStr
) + 1);
2772 /* Append the display name */
2773 if (lpService
->lpDisplayName
!= NULL
)
2775 wcscpy(lpStr
, lpService
->lpDisplayName
);
2779 wcscpy(lpStr
, lpEmptyString
);
2782 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2785 if (pcbBytesNeeded
!= NULL
)
2786 *pcbBytesNeeded
= dwRequiredSize
;
2789 if (lpImagePath
!= NULL
)
2790 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2792 if (lpServiceStartName
!= NULL
)
2793 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2795 if (lpDependencies
!= NULL
)
2796 HeapFree(GetProcessHeap(), 0, lpDependencies
);
2798 if (hServiceKey
!= NULL
)
2799 RegCloseKey(hServiceKey
);
2801 /* FIXME: Unlock the service database */
2803 DPRINT("RQueryServiceConfigW() done\n");
2810 DWORD
RQueryServiceLockStatusW(
2811 SC_RPC_HANDLE hSCManager
,
2812 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2814 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2817 return ERROR_CALL_NOT_IMPLEMENTED
;
2822 DWORD
RStartServiceW(
2823 SC_RPC_HANDLE hService
,
2825 LPSTRING_PTRSW argv
)
2827 DWORD dwError
= ERROR_SUCCESS
;
2828 PSERVICE_HANDLE hSvc
;
2829 PSERVICE lpService
= NULL
;
2831 DPRINT("RStartServiceW() called\n");
2834 return ERROR_SHUTDOWN_IN_PROGRESS
;
2836 hSvc
= ScmGetServiceFromHandle(hService
);
2839 DPRINT1("Invalid service handle!\n");
2840 return ERROR_INVALID_HANDLE
;
2843 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2846 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2847 return ERROR_ACCESS_DENIED
;
2850 lpService
= hSvc
->ServiceEntry
;
2851 if (lpService
== NULL
)
2853 DPRINT("lpService == NULL!\n");
2854 return ERROR_INVALID_HANDLE
;
2857 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2858 return ERROR_SERVICE_DISABLED
;
2860 if (lpService
->bDeleted
)
2861 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2868 /* Start the service */
2869 dwError
= ScmSendServiceCommand(lpService
,
2870 SERVICE_CONTROL_START
,
2879 DWORD
RGetServiceDisplayNameW(
2880 SC_RPC_HANDLE hSCManager
,
2881 LPCWSTR lpServiceName
,
2882 LPWSTR lpDisplayName
,
2885 // PMANAGER_HANDLE hManager;
2890 DPRINT("RGetServiceDisplayNameW() called\n");
2891 DPRINT("hSCManager = %p\n", hSCManager
);
2892 DPRINT("lpServiceName: %S\n", lpServiceName
);
2893 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2894 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2896 // hManager = (PMANAGER_HANDLE)hSCManager;
2897 // if (hManager->Handle.Tag != MANAGER_TAG)
2899 // DPRINT("Invalid manager handle!\n");
2900 // return ERROR_INVALID_HANDLE;
2903 /* Get service database entry */
2904 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2905 if (lpService
== NULL
)
2907 DPRINT("Could not find a service!\n");
2909 /* If the service could not be found and lpcchBuffer is less than 2, windows
2910 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2911 if (*lpcchBuffer
< 2)
2914 if (lpDisplayName
!= NULL
)
2916 *lpDisplayName
= '\0';
2920 return ERROR_SERVICE_DOES_NOT_EXIST
;
2923 if (!lpService
->lpDisplayName
)
2925 dwLength
= wcslen(lpService
->lpServiceName
);
2927 if (lpDisplayName
!= NULL
&&
2928 *lpcchBuffer
> dwLength
)
2930 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2935 dwLength
= wcslen(lpService
->lpDisplayName
);
2937 if (lpDisplayName
!= NULL
&&
2938 *lpcchBuffer
> dwLength
)
2940 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2944 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2946 *lpcchBuffer
= dwLength
;
2953 DWORD
RGetServiceKeyNameW(
2954 SC_RPC_HANDLE hSCManager
,
2955 LPCWSTR lpDisplayName
,
2956 LPWSTR lpServiceName
,
2959 // PMANAGER_HANDLE hManager;
2964 DPRINT("RGetServiceKeyNameW() called\n");
2965 DPRINT("hSCManager = %p\n", hSCManager
);
2966 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2967 DPRINT("lpServiceName: %p\n", lpServiceName
);
2968 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2970 // hManager = (PMANAGER_HANDLE)hSCManager;
2971 // if (hManager->Handle.Tag != MANAGER_TAG)
2973 // DPRINT("Invalid manager handle!\n");
2974 // return ERROR_INVALID_HANDLE;
2977 /* Get service database entry */
2978 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2979 if (lpService
== NULL
)
2981 DPRINT("Could not find a service!\n");
2983 /* If the service could not be found and lpcchBuffer is less than 2, windows
2984 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2985 if (*lpcchBuffer
< 2)
2988 if (lpServiceName
!= NULL
)
2990 *lpServiceName
= '\0';
2994 return ERROR_SERVICE_DOES_NOT_EXIST
;
2997 dwLength
= wcslen(lpService
->lpServiceName
);
2999 if (lpServiceName
!= NULL
&&
3000 *lpcchBuffer
> dwLength
)
3002 wcscpy(lpServiceName
, lpService
->lpServiceName
);
3003 *lpcchBuffer
= dwLength
;
3004 return ERROR_SUCCESS
;
3007 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3009 *lpcchBuffer
= dwLength
;
3016 DWORD
RI_ScSetServiceBitsA(
3017 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3018 DWORD dwServiceBits
,
3020 int bUpdateImmediately
,
3024 return ERROR_CALL_NOT_IMPLEMENTED
;
3029 DWORD
RChangeServiceConfigA(
3030 SC_RPC_HANDLE hService
,
3031 DWORD dwServiceType
,
3033 DWORD dwErrorControl
,
3034 LPSTR lpBinaryPathName
,
3035 LPSTR lpLoadOrderGroup
,
3037 LPSTR lpDependencies
,
3039 LPSTR lpServiceStartName
,
3042 LPSTR lpDisplayName
)
3044 DWORD dwError
= ERROR_SUCCESS
;
3045 PSERVICE_HANDLE hSvc
;
3046 PSERVICE lpService
= NULL
;
3047 HKEY hServiceKey
= NULL
;
3048 LPWSTR lpDisplayNameW
= NULL
;
3049 // LPWSTR lpBinaryPathNameW = NULL;
3050 LPWSTR lpLoadOrderGroupW
= NULL
;
3051 LPWSTR lpDependenciesW
= NULL
;
3052 // LPWSTR lpPasswordW = NULL;
3054 DPRINT("RChangeServiceConfigA() called\n");
3055 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3056 DPRINT("dwStartType = %lu\n", dwStartType
);
3057 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3058 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3059 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3060 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3063 return ERROR_SHUTDOWN_IN_PROGRESS
;
3065 hSvc
= ScmGetServiceFromHandle(hService
);
3068 DPRINT1("Invalid service handle!\n");
3069 return ERROR_INVALID_HANDLE
;
3072 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3073 SERVICE_CHANGE_CONFIG
))
3075 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3076 return ERROR_ACCESS_DENIED
;
3079 lpService
= hSvc
->ServiceEntry
;
3080 if (lpService
== NULL
)
3082 DPRINT("lpService == NULL!\n");
3083 return ERROR_INVALID_HANDLE
;
3086 /* FIXME: Lock database exclusively */
3088 if (lpService
->bDeleted
)
3090 /* FIXME: Unlock database */
3091 DPRINT("The service has already been marked for delete!\n");
3092 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3095 /* Open the service key */
3096 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3099 if (dwError
!= ERROR_SUCCESS
)
3102 /* Write service data to the registry */
3104 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3106 /* Set the display name */
3107 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3109 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3110 if (lpDisplayNameW
== NULL
)
3112 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3116 MultiByteToWideChar(CP_ACP
,
3121 strlen(lpDisplayName
) + 1);
3123 RegSetValueExW(hServiceKey
,
3127 (LPBYTE
)lpDisplayNameW
,
3128 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3130 /* Update lpService->lpDisplayName */
3131 if (lpService
->lpDisplayName
)
3132 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3134 lpService
->lpDisplayName
= lpDisplayNameW
;
3137 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3139 /* Set the service type */
3140 dwError
= RegSetValueExW(hServiceKey
,
3144 (LPBYTE
)&dwServiceType
,
3146 if (dwError
!= ERROR_SUCCESS
)
3149 lpService
->Status
.dwServiceType
= dwServiceType
;
3152 if (dwStartType
!= SERVICE_NO_CHANGE
)
3154 /* Set the start value */
3155 dwError
= RegSetValueExW(hServiceKey
,
3159 (LPBYTE
)&dwStartType
,
3161 if (dwError
!= ERROR_SUCCESS
)
3164 lpService
->dwStartType
= dwStartType
;
3167 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3169 /* Set the error control value */
3170 dwError
= RegSetValueExW(hServiceKey
,
3174 (LPBYTE
)&dwErrorControl
,
3176 if (dwError
!= ERROR_SUCCESS
)
3179 lpService
->dwErrorControl
= dwErrorControl
;
3183 /* FIXME: set the new ImagePath value */
3185 /* Set the image path */
3186 if (dwServiceType
& SERVICE_WIN32
)
3188 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3190 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3191 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, strlen(lpBinaryPathName
)+1);
3192 dwError
= RegSetValueExW(hServiceKey
,
3196 (LPBYTE
)lpBinaryPathNameW
,
3197 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3198 if (dwError
!= ERROR_SUCCESS
)
3202 else if (dwServiceType
& SERVICE_DRIVER
)
3204 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3206 dwError
= RegSetValueExW(hServiceKey
,
3210 (LPBYTE
)lpImagePath
,
3211 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3212 if (dwError
!= ERROR_SUCCESS
)
3218 /* Set the group name */
3219 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3221 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3223 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3224 if (lpLoadOrderGroupW
== NULL
)
3226 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3230 MultiByteToWideChar(CP_ACP
,
3235 strlen(lpLoadOrderGroup
) + 1);
3237 dwError
= RegSetValueExW(hServiceKey
,
3241 (LPBYTE
)lpLoadOrderGroupW
,
3242 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3243 if (dwError
!= ERROR_SUCCESS
)
3245 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3249 dwError
= ScmSetServiceGroup(lpService
,
3252 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3254 if (dwError
!= ERROR_SUCCESS
)
3258 if (lpdwTagId
!= NULL
)
3260 dwError
= ScmAssignNewTag(lpService
);
3261 if (dwError
!= ERROR_SUCCESS
)
3264 dwError
= RegSetValueExW(hServiceKey
,
3268 (LPBYTE
)&lpService
->dwTag
,
3270 if (dwError
!= ERROR_SUCCESS
)
3273 *lpdwTagId
= lpService
->dwTag
;
3276 /* Write dependencies */
3277 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3279 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3281 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3282 if (lpDependenciesW
== NULL
)
3284 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3288 MultiByteToWideChar(CP_ACP
,
3293 strlen(lpDependencies
) + 1);
3295 dwError
= ScmWriteDependencies(hServiceKey
,
3296 (LPWSTR
)lpDependenciesW
,
3299 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3302 if (lpPassword
!= NULL
)
3304 /* FIXME: Write password */
3307 /* FIXME: Unlock database */
3310 if (hServiceKey
!= NULL
)
3311 RegCloseKey(hServiceKey
);
3313 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3320 DWORD
RCreateServiceA(
3321 SC_RPC_HANDLE hSCManager
,
3322 LPSTR lpServiceName
,
3323 LPSTR lpDisplayName
,
3324 DWORD dwDesiredAccess
,
3325 DWORD dwServiceType
,
3327 DWORD dwErrorControl
,
3328 LPSTR lpBinaryPathName
,
3329 LPSTR lpLoadOrderGroup
,
3331 LPBYTE lpDependencies
,
3333 LPSTR lpServiceStartName
,
3336 LPSC_RPC_HANDLE lpServiceHandle
)
3338 DWORD dwError
= ERROR_SUCCESS
;
3339 LPWSTR lpServiceNameW
= NULL
;
3340 LPWSTR lpDisplayNameW
= NULL
;
3341 LPWSTR lpBinaryPathNameW
= NULL
;
3342 LPWSTR lpLoadOrderGroupW
= NULL
;
3343 LPWSTR lpDependenciesW
= NULL
;
3344 LPWSTR lpServiceStartNameW
= NULL
;
3345 DWORD dwDependenciesLength
= 0;
3352 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3353 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3354 if (!lpServiceNameW
)
3356 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3359 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3364 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3365 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3366 if (!lpDisplayNameW
)
3368 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3371 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3374 if (lpBinaryPathName
)
3376 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3377 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3378 if (!lpBinaryPathNameW
)
3380 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3383 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3386 if (lpLoadOrderGroup
)
3388 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3389 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3390 if (!lpLoadOrderGroupW
)
3392 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3395 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3400 lpStr
= (LPSTR
)lpDependencies
;
3403 dwLength
= strlen(lpStr
) + 1;
3404 dwDependenciesLength
+= dwLength
;
3405 lpStr
= lpStr
+ dwLength
;
3407 dwDependenciesLength
++;
3409 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3410 if (!lpDependenciesW
)
3412 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3415 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3418 if (lpServiceStartName
)
3420 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3421 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3422 if (!lpServiceStartNameW
)
3424 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3427 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3430 dwError
= RCreateServiceW(hSCManager
,
3440 (LPBYTE
)lpDependenciesW
,
3441 dwDependenciesLength
,
3442 lpServiceStartNameW
,
3448 if (lpServiceNameW
!=NULL
)
3449 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3451 if (lpDisplayNameW
!= NULL
)
3452 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3454 if (lpBinaryPathNameW
!= NULL
)
3455 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3457 if (lpLoadOrderGroupW
!= NULL
)
3458 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3460 if (lpDependenciesW
!= NULL
)
3461 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3463 if (lpServiceStartNameW
!= NULL
)
3464 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3471 DWORD
REnumDependentServicesA(
3472 SC_RPC_HANDLE hService
,
3473 DWORD dwServiceState
,
3476 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3477 LPBOUNDED_DWORD_256K lpServicesReturned
)
3479 DWORD dwError
= ERROR_SUCCESS
;
3480 DWORD dwServicesReturned
= 0;
3481 DWORD dwServiceCount
;
3482 HKEY hServicesKey
= NULL
;
3483 PSERVICE_HANDLE hSvc
;
3484 PSERVICE lpService
= NULL
;
3485 PSERVICE
*lpServicesArray
= NULL
;
3486 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3489 *pcbBytesNeeded
= 0;
3490 *lpServicesReturned
= 0;
3492 DPRINT("REnumDependentServicesA() called\n");
3494 hSvc
= ScmGetServiceFromHandle(hService
);
3497 DPRINT1("Invalid service handle!\n");
3498 return ERROR_INVALID_HANDLE
;
3501 lpService
= hSvc
->ServiceEntry
;
3503 /* Check access rights */
3504 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3505 SC_MANAGER_ENUMERATE_SERVICE
))
3507 DPRINT("Insufficient access rights! 0x%lx\n",
3508 hSvc
->Handle
.DesiredAccess
);
3509 return ERROR_ACCESS_DENIED
;
3512 /* Open the Services Reg key */
3513 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3514 L
"System\\CurrentControlSet\\Services",
3519 if (dwError
!= ERROR_SUCCESS
)
3522 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3523 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3524 are the same for both. Verified in WINXP. */
3526 /* First determine the bytes needed and get the number of dependent services*/
3527 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3532 &dwServicesReturned
);
3533 if (dwError
!= ERROR_SUCCESS
)
3536 /* If buffer size is less than the bytes needed or pointer is null*/
3537 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3539 dwError
= ERROR_MORE_DATA
;
3543 /* Allocate memory for array of service pointers */
3544 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3546 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3547 if (!lpServicesArray
)
3549 DPRINT("Could not allocate a buffer!!\n");
3550 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3554 dwServicesReturned
= 0;
3555 *pcbBytesNeeded
= 0;
3557 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3562 &dwServicesReturned
);
3563 if (dwError
!= ERROR_SUCCESS
)
3568 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3569 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3571 /* Copy EnumDepenedentService to Buffer */
3572 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3574 lpService
= lpServicesArray
[dwServiceCount
];
3576 /* Copy the status info */
3577 memcpy(&lpServicesPtr
->ServiceStatus
,
3579 sizeof(SERVICE_STATUS
));
3581 /* Copy display name */
3582 WideCharToMultiByte(CP_ACP
,
3584 lpService
->lpDisplayName
,
3587 wcslen(lpService
->lpDisplayName
),
3590 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3591 lpStr
+= strlen(lpStr
) + 1;
3593 /* Copy service name */
3594 WideCharToMultiByte(CP_ACP
,
3596 lpService
->lpServiceName
,
3599 wcslen(lpService
->lpServiceName
),
3602 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3603 lpStr
+= strlen(lpStr
) + 1;
3608 *lpServicesReturned
= dwServicesReturned
;
3611 if (lpServicesArray
)
3612 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3614 RegCloseKey(hServicesKey
);
3616 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3623 DWORD
REnumServicesStatusA(
3624 SC_RPC_HANDLE hSCManager
,
3625 DWORD dwServiceType
,
3626 DWORD dwServiceState
,
3629 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3630 LPBOUNDED_DWORD_256K lpServicesReturned
,
3631 LPBOUNDED_DWORD_256K lpResumeHandle
)
3633 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3634 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3635 LPWSTR lpStringPtrW
;
3638 DWORD dwServiceCount
;
3640 DPRINT("REnumServicesStatusA() called\n");
3642 if ((dwBufSize
> 0) && (lpBuffer
))
3644 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3647 DPRINT("Failed to allocate buffer!\n");
3648 return ERROR_NOT_ENOUGH_MEMORY
;
3652 dwError
= REnumServicesStatusW(hSCManager
,
3655 (LPBYTE
)lpStatusPtrW
,
3661 /* if no services were returned then we are Done */
3662 if (*lpServicesReturned
== 0)
3665 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3666 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3667 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3668 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3669 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3671 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3673 /* Copy the service name */
3674 WideCharToMultiByte(CP_ACP
,
3679 wcslen(lpStringPtrW
),
3683 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3684 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3685 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3687 /* Copy the display name */
3688 WideCharToMultiByte(CP_ACP
,
3693 wcslen(lpStringPtrW
),
3697 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3698 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3699 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3701 /* Copy the status information */
3702 memcpy(&lpStatusPtrA
->ServiceStatus
,
3703 &lpStatusPtrW
->ServiceStatus
,
3704 sizeof(SERVICE_STATUS
));
3711 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3713 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3720 DWORD
ROpenSCManagerA(
3721 LPSTR lpMachineName
,
3722 LPSTR lpDatabaseName
,
3723 DWORD dwDesiredAccess
,
3724 LPSC_RPC_HANDLE lpScHandle
)
3726 UNICODE_STRING MachineName
;
3727 UNICODE_STRING DatabaseName
;
3730 DPRINT("ROpenSCManagerA() called\n");
3733 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3737 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3740 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3741 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3746 RtlFreeUnicodeString(&MachineName
);
3749 RtlFreeUnicodeString(&DatabaseName
);
3756 DWORD
ROpenServiceA(
3757 SC_RPC_HANDLE hSCManager
,
3758 LPSTR lpServiceName
,
3759 DWORD dwDesiredAccess
,
3760 LPSC_RPC_HANDLE lpServiceHandle
)
3762 UNICODE_STRING ServiceName
;
3765 DPRINT("ROpenServiceA() called\n");
3768 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3771 dwError
= ROpenServiceW(hSCManager
,
3772 lpServiceName
? ServiceName
.Buffer
: NULL
,
3777 RtlFreeUnicodeString(&ServiceName
);
3784 DWORD
RQueryServiceConfigA(
3785 SC_RPC_HANDLE hService
,
3786 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3788 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3790 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3791 DWORD dwError
= ERROR_SUCCESS
;
3792 PSERVICE_HANDLE hSvc
;
3793 PSERVICE lpService
= NULL
;
3794 HKEY hServiceKey
= NULL
;
3795 LPWSTR lpImagePath
= NULL
;
3796 LPWSTR lpServiceStartName
= NULL
;
3797 LPWSTR lpDependencies
= NULL
;
3798 DWORD dwDependenciesLength
= 0;
3799 DWORD dwRequiredSize
;
3800 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3801 CHAR lpEmptyString
[]={0,0};
3804 DPRINT("RQueryServiceConfigA() called\n");
3807 return ERROR_SHUTDOWN_IN_PROGRESS
;
3809 hSvc
= ScmGetServiceFromHandle(hService
);
3812 DPRINT1("Invalid service handle!\n");
3813 return ERROR_INVALID_HANDLE
;
3816 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3817 SERVICE_QUERY_CONFIG
))
3819 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3820 return ERROR_ACCESS_DENIED
;
3823 lpService
= hSvc
->ServiceEntry
;
3824 if (lpService
== NULL
)
3826 DPRINT("lpService == NULL!\n");
3827 return ERROR_INVALID_HANDLE
;
3830 /* FIXME: Lock the service database shared */
3832 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3835 if (dwError
!= ERROR_SUCCESS
)
3838 /* Read the image path */
3839 dwError
= ScmReadString(hServiceKey
,
3842 if (dwError
!= ERROR_SUCCESS
)
3845 /* Read the service start name */
3846 ScmReadString(hServiceKey
,
3848 &lpServiceStartName
);
3850 /* Read the dependencies */
3851 ScmReadDependencies(hServiceKey
,
3853 &dwDependenciesLength
);
3855 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3857 if (lpImagePath
!= NULL
)
3858 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3860 dwRequiredSize
+= 2;
3862 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3863 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3865 dwRequiredSize
+= 2;
3867 /* Add Dependencies length */
3868 if (lpDependencies
!= NULL
)
3869 dwRequiredSize
+= dwDependenciesLength
;
3871 dwRequiredSize
+= 2;
3873 if (lpServiceStartName
!= NULL
)
3874 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3876 dwRequiredSize
+= 2;
3878 if (lpService
->lpDisplayName
!= NULL
)
3879 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3881 dwRequiredSize
+= 2;
3883 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3885 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3889 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3890 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3891 lpConfig
->dwStartType
= lpService
->dwStartType
;
3892 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3893 lpConfig
->dwTagId
= lpService
->dwTag
;
3895 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3897 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3902 WideCharToMultiByte(CP_ACP
,
3907 wcslen(lpImagePath
) + 1,
3913 strcpy(lpStr
, lpEmptyString
);
3916 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3917 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3919 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
3921 WideCharToMultiByte(CP_ACP
,
3923 lpService
->lpGroup
->lpGroupName
,
3926 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
3932 strcpy(lpStr
, lpEmptyString
);
3935 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3936 lpStr
+= (strlen(lpStr
) + 1);
3938 /* Append Dependencies */
3941 WideCharToMultiByte(CP_ACP
,
3944 dwDependenciesLength
,
3946 dwDependenciesLength
,
3952 strcpy(lpStr
, lpEmptyString
);
3955 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3957 lpStr
+= dwDependenciesLength
;
3959 lpStr
+= (strlen(lpStr
) + 1);
3961 if (lpServiceStartName
)
3963 WideCharToMultiByte(CP_ACP
,
3968 wcslen(lpServiceStartName
) + 1,
3974 strcpy(lpStr
, lpEmptyString
);
3977 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3978 lpStr
+= (strlen(lpStr
) + 1);
3980 if (lpService
->lpDisplayName
)
3982 WideCharToMultiByte(CP_ACP
,
3984 lpService
->lpDisplayName
,
3987 wcslen(lpService
->lpDisplayName
) + 1,
3993 strcpy(lpStr
, lpEmptyString
);
3996 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3999 if (pcbBytesNeeded
!= NULL
)
4000 *pcbBytesNeeded
= dwRequiredSize
;
4003 if (lpImagePath
!= NULL
)
4004 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4006 if (lpServiceStartName
!= NULL
)
4007 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4009 if (lpDependencies
!= NULL
)
4010 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4012 if (hServiceKey
!= NULL
)
4013 RegCloseKey(hServiceKey
);
4015 /* FIXME: Unlock the service database */
4017 DPRINT("RQueryServiceConfigA() done\n");
4024 DWORD
RQueryServiceLockStatusA(
4025 SC_RPC_HANDLE hSCManager
,
4026 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
4028 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4031 return ERROR_CALL_NOT_IMPLEMENTED
;
4036 DWORD
RStartServiceA(
4037 SC_RPC_HANDLE hService
,
4039 LPSTRING_PTRSA argv
)
4041 DWORD dwError
= ERROR_SUCCESS
;
4042 PSERVICE_HANDLE hSvc
;
4043 PSERVICE lpService
= NULL
;
4045 DPRINT("RStartServiceA() called\n");
4048 return ERROR_SHUTDOWN_IN_PROGRESS
;
4050 hSvc
= ScmGetServiceFromHandle(hService
);
4053 DPRINT1("Invalid service handle!\n");
4054 return ERROR_INVALID_HANDLE
;
4057 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4060 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4061 return ERROR_ACCESS_DENIED
;
4064 lpService
= hSvc
->ServiceEntry
;
4065 if (lpService
== NULL
)
4067 DPRINT("lpService == NULL!\n");
4068 return ERROR_INVALID_HANDLE
;
4071 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4072 return ERROR_SERVICE_DISABLED
;
4074 if (lpService
->bDeleted
)
4075 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4077 /* FIXME: Convert argument vector to Unicode */
4079 /* Start the service */
4080 dwError
= ScmSendServiceCommand(lpService
,
4081 SERVICE_CONTROL_START
,
4085 /* FIXME: Free argument vector */
4092 DWORD
RGetServiceDisplayNameA(
4093 SC_RPC_HANDLE hSCManager
,
4094 LPCSTR lpServiceName
,
4095 LPSTR lpDisplayName
,
4096 LPBOUNDED_DWORD_4K lpcchBuffer
)
4098 // PMANAGER_HANDLE hManager;
4099 PSERVICE lpService
= NULL
;
4102 LPWSTR lpServiceNameW
;
4104 DPRINT("RGetServiceDisplayNameA() called\n");
4105 DPRINT("hSCManager = %p\n", hSCManager
);
4106 DPRINT("lpServiceName: %s\n", lpServiceName
);
4107 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4108 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4110 // hManager = (PMANAGER_HANDLE)hSCManager;
4111 // if (hManager->Handle.Tag != MANAGER_TAG)
4113 // DPRINT("Invalid manager handle!\n");
4114 // return ERROR_INVALID_HANDLE;
4117 if (lpServiceName
!= NULL
)
4119 dwLength
= strlen(lpServiceName
) + 1;
4120 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4122 dwLength
* sizeof(WCHAR
));
4123 if (!lpServiceNameW
)
4124 return ERROR_NOT_ENOUGH_MEMORY
;
4126 MultiByteToWideChar(CP_ACP
,
4133 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4135 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4138 if (lpService
== NULL
)
4140 DPRINT("Could not find a service!\n");
4142 /* If the service could not be found and lpcchBuffer is 0, windows
4143 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4144 if (*lpcchBuffer
== 0)
4147 if (lpDisplayName
!= NULL
)
4149 *lpDisplayName
= '\0';
4152 return ERROR_SERVICE_DOES_NOT_EXIST
;
4155 if (!lpService
->lpDisplayName
)
4157 dwLength
= wcslen(lpService
->lpServiceName
);
4158 if (lpDisplayName
!= NULL
&&
4159 *lpcchBuffer
> dwLength
)
4161 WideCharToMultiByte(CP_ACP
,
4163 lpService
->lpServiceName
,
4164 wcslen(lpService
->lpServiceName
),
4169 return ERROR_SUCCESS
;
4174 dwLength
= wcslen(lpService
->lpDisplayName
);
4175 if (lpDisplayName
!= NULL
&&
4176 *lpcchBuffer
> dwLength
)
4178 WideCharToMultiByte(CP_ACP
,
4180 lpService
->lpDisplayName
,
4181 wcslen(lpService
->lpDisplayName
),
4186 return ERROR_SUCCESS
;
4190 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4192 *lpcchBuffer
= dwLength
* 2;
4199 DWORD
RGetServiceKeyNameA(
4200 SC_RPC_HANDLE hSCManager
,
4201 LPCSTR lpDisplayName
,
4202 LPSTR lpServiceName
,
4203 LPBOUNDED_DWORD_4K lpcchBuffer
)
4208 LPWSTR lpDisplayNameW
;
4210 DPRINT("RGetServiceKeyNameA() called\n");
4211 DPRINT("hSCManager = %p\n", hSCManager
);
4212 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4213 DPRINT("lpServiceName: %p\n", lpServiceName
);
4214 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4216 dwLength
= strlen(lpDisplayName
) + 1;
4217 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4219 dwLength
* sizeof(WCHAR
));
4220 if (!lpDisplayNameW
)
4221 return ERROR_NOT_ENOUGH_MEMORY
;
4223 MultiByteToWideChar(CP_ACP
,
4230 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4232 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4234 if (lpService
== NULL
)
4236 DPRINT("Could not find the service!\n");
4238 /* If the service could not be found and lpcchBuffer is 0,
4239 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4240 if (*lpcchBuffer
== 0)
4243 if (lpServiceName
!= NULL
)
4245 *lpServiceName
= '\0';
4249 return ERROR_SERVICE_DOES_NOT_EXIST
;
4252 dwLength
= wcslen(lpService
->lpServiceName
);
4253 if (lpServiceName
!= NULL
&&
4254 *lpcchBuffer
> dwLength
)
4256 WideCharToMultiByte(CP_ACP
,
4258 lpService
->lpServiceName
,
4259 wcslen(lpService
->lpServiceName
),
4264 return ERROR_SUCCESS
;
4267 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4269 *lpcchBuffer
= dwLength
* 2;
4276 DWORD
RI_ScGetCurrentGroupStateW(
4277 SC_RPC_HANDLE hSCManager
,
4278 LPWSTR lpLoadOrderGroup
,
4282 return ERROR_CALL_NOT_IMPLEMENTED
;
4287 DWORD
REnumServiceGroupW(
4288 SC_RPC_HANDLE hSCManager
,
4289 DWORD dwServiceType
,
4290 DWORD dwServiceState
,
4293 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4294 LPBOUNDED_DWORD_256K lpServicesReturned
,
4295 LPBOUNDED_DWORD_256K lpResumeIndex
,
4296 LPCWSTR pszGroupName
)
4299 return ERROR_CALL_NOT_IMPLEMENTED
;
4304 // WARNING: This function is untested
4307 DWORD
RChangeServiceConfig2A(
4308 SC_RPC_HANDLE hService
,
4309 SC_RPC_CONFIG_INFOA Info
)
4311 SC_RPC_CONFIG_INFOW InfoW
;
4312 DWORD dwRet
, dwLength
;
4315 DPRINT("RChangeServiceConfig2A() called\n");
4316 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4318 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4320 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4322 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4323 LPSERVICE_DESCRIPTIONA lpServiceDescriptonA
;
4325 lpServiceDescriptonA
= Info
.psd
;
4327 ///if (lpServiceDescriptonA &&
4328 ///lpServiceDescriptonA->lpDescription)
4330 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4332 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4334 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4335 if (!lpServiceDescriptonW
)
4337 return ERROR_NOT_ENOUGH_MEMORY
;
4340 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4342 MultiByteToWideChar(CP_ACP
,
4346 lpServiceDescriptonW
->lpDescription
,
4349 ptr
= lpServiceDescriptonW
;
4350 InfoW
.psd
= lpServiceDescriptonW
;
4353 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4355 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4356 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4357 DWORD dwRebootLen
= 0;
4358 DWORD dwCommandLen
= 0;
4360 lpServiceFailureActionsA
= Info
.psfa
;
4362 if (lpServiceFailureActionsA
)
4364 if (lpServiceFailureActionsA
->lpRebootMsg
)
4366 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4368 if (lpServiceFailureActionsA
->lpCommand
)
4370 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4372 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4374 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4377 if (!lpServiceFailureActionsW
)
4379 return ERROR_NOT_ENOUGH_MEMORY
;
4382 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4383 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4384 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4386 if (lpServiceFailureActionsA
->lpRebootMsg
)
4388 MultiByteToWideChar(CP_ACP
,
4390 lpServiceFailureActionsA
->lpRebootMsg
,
4392 lpServiceFailureActionsW
->lpRebootMsg
,
4396 if (lpServiceFailureActionsA
->lpCommand
)
4398 MultiByteToWideChar(CP_ACP
,
4400 lpServiceFailureActionsA
->lpCommand
,
4402 lpServiceFailureActionsW
->lpCommand
,
4406 ptr
= lpServiceFailureActionsW
;
4410 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4412 HeapFree(GetProcessHeap(), 0, ptr
);
4419 DWORD
RChangeServiceConfig2W(
4420 SC_RPC_HANDLE hService
,
4421 SC_RPC_CONFIG_INFOW Info
)
4423 DWORD dwError
= ERROR_SUCCESS
;
4424 PSERVICE_HANDLE hSvc
;
4425 PSERVICE lpService
= NULL
;
4426 HKEY hServiceKey
= NULL
;
4428 DPRINT("RChangeServiceConfig2W() called\n");
4429 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4432 return ERROR_SHUTDOWN_IN_PROGRESS
;
4434 hSvc
= ScmGetServiceFromHandle(hService
);
4437 DPRINT1("Invalid service handle!\n");
4438 return ERROR_INVALID_HANDLE
;
4441 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4442 SERVICE_CHANGE_CONFIG
))
4444 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4445 return ERROR_ACCESS_DENIED
;
4448 lpService
= hSvc
->ServiceEntry
;
4449 if (lpService
== NULL
)
4451 DPRINT("lpService == NULL!\n");
4452 return ERROR_INVALID_HANDLE
;
4455 /* FIXME: Lock database exclusively */
4457 if (lpService
->bDeleted
)
4459 /* FIXME: Unlock database */
4460 DPRINT("The service has already been marked for delete!\n");
4461 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4464 /* Open the service key */
4465 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4468 if (dwError
!= ERROR_SUCCESS
)
4471 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4473 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4475 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4476 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4478 if (lpServiceDescription
!= NULL
&&
4479 lpServiceDescription
->lpDescription
!= NULL
)
4481 DPRINT("Setting value %S\n", lpServiceDescription
->lpDescription
);
4482 RegSetValueExW(hServiceKey
,
4486 (LPBYTE
)lpServiceDescription
->lpDescription
,
4487 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4489 if (dwError
!= ERROR_SUCCESS
)
4493 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4496 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4501 /* FIXME: Unlock database */
4502 if (hServiceKey
!= NULL
)
4503 RegCloseKey(hServiceKey
);
4505 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4512 DWORD
RQueryServiceConfig2A(
4513 SC_RPC_HANDLE hService
,
4517 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4519 DWORD dwError
= ERROR_SUCCESS
;
4520 PSERVICE_HANDLE hSvc
;
4521 PSERVICE lpService
= NULL
;
4522 HKEY hServiceKey
= NULL
;
4523 LPWSTR lpDescriptionW
= NULL
;
4524 LPSTR lpDescription
= NULL
;
4526 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4527 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4530 return ERROR_INVALID_ADDRESS
;
4533 return ERROR_SHUTDOWN_IN_PROGRESS
;
4535 hSvc
= ScmGetServiceFromHandle(hService
);
4538 DPRINT1("Invalid service handle!\n");
4539 return ERROR_INVALID_HANDLE
;
4542 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4543 SERVICE_QUERY_CONFIG
))
4545 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4546 return ERROR_ACCESS_DENIED
;
4549 lpService
= hSvc
->ServiceEntry
;
4550 if (lpService
== NULL
)
4552 DPRINT("lpService == NULL!\n");
4553 return ERROR_INVALID_HANDLE
;
4556 /* FIXME: Lock the service database shared */
4558 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4561 if (dwError
!= ERROR_SUCCESS
)
4564 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4566 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4569 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4571 dwError
= ScmReadString(hServiceKey
,
4574 if (dwError
== ERROR_SUCCESS
)
4576 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4579 if (cbBufSize
>= *pcbBytesNeeded
)
4582 if (dwError
== ERROR_SUCCESS
)
4584 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4586 WideCharToMultiByte(CP_ACP
,
4591 wcslen(lpDescriptionW
),
4594 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4598 lpServiceDescription
->lpDescription
= NULL
;
4604 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4608 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4611 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4616 if (lpDescription
!= NULL
)
4617 HeapFree(GetProcessHeap(), 0, lpDescription
);
4619 if (hServiceKey
!= NULL
)
4620 RegCloseKey(hServiceKey
);
4622 /* FIXME: Unlock database */
4624 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4631 DWORD
RQueryServiceConfig2W(
4632 SC_RPC_HANDLE hService
,
4636 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4638 DWORD dwError
= ERROR_SUCCESS
;
4639 PSERVICE_HANDLE hSvc
;
4640 PSERVICE lpService
= NULL
;
4641 HKEY hServiceKey
= NULL
;
4642 DWORD dwRequiredSize
;
4643 LPWSTR lpDescription
= NULL
;
4644 LPWSTR lpFailureCommand
= NULL
;
4645 LPWSTR lpRebootMessage
= NULL
;
4647 DPRINT("RQueryServiceConfig2W() called\n");
4650 return ERROR_INVALID_ADDRESS
;
4653 return ERROR_SHUTDOWN_IN_PROGRESS
;
4655 hSvc
= ScmGetServiceFromHandle(hService
);
4658 DPRINT1("Invalid service handle!\n");
4659 return ERROR_INVALID_HANDLE
;
4662 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4663 SERVICE_QUERY_CONFIG
))
4665 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4666 return ERROR_ACCESS_DENIED
;
4669 lpService
= hSvc
->ServiceEntry
;
4670 if (lpService
== NULL
)
4672 DPRINT("lpService == NULL!\n");
4673 return ERROR_INVALID_HANDLE
;
4676 /* FIXME: Lock the service database shared */
4678 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4681 if (dwError
!= ERROR_SUCCESS
)
4684 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4686 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4689 dwError
= ScmReadString(hServiceKey
,
4692 if (dwError
!= ERROR_SUCCESS
)
4695 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4697 if (cbBufSize
< dwRequiredSize
)
4699 *pcbBytesNeeded
= dwRequiredSize
;
4700 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4704 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4705 wcscpy(lpStr
, lpDescription
);
4706 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4708 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4711 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
4715 dwError
= ScmReadString(hServiceKey
,
4719 dwError
= ScmReadString(hServiceKey
,
4723 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
4725 if (lpFailureCommand
)
4726 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
4728 if (lpRebootMessage
)
4729 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
4731 if (cbBufSize
< dwRequiredSize
)
4733 *pcbBytesNeeded
= dwRequiredSize
;
4734 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4738 lpFailureActions
->cActions
= 0;
4739 lpFailureActions
->dwResetPeriod
= 0;
4740 lpFailureActions
->lpCommand
= NULL
;
4741 lpFailureActions
->lpRebootMsg
= NULL
;
4742 lpFailureActions
->lpsaActions
= NULL
;
4744 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
4745 if (lpRebootMessage
)
4747 wcscpy(lpStr
, lpRebootMessage
);
4748 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
4749 lpStr
+= wcslen(lpRebootMessage
) + 1;
4752 if (lpFailureCommand
)
4754 wcscpy(lpStr
, lpFailureCommand
);
4755 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
4756 lpStr
+= wcslen(lpRebootMessage
) + 1;
4758 dwError
= STATUS_SUCCESS
;
4763 if (lpDescription
!= NULL
)
4764 HeapFree(GetProcessHeap(), 0, lpDescription
);
4766 if (lpRebootMessage
!= NULL
)
4767 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
4769 if (lpFailureCommand
!= NULL
)
4770 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
4772 if (hServiceKey
!= NULL
)
4773 RegCloseKey(hServiceKey
);
4775 /* FIXME: Unlock database */
4777 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4784 DWORD
RQueryServiceStatusEx(
4785 SC_RPC_HANDLE hService
,
4786 SC_STATUS_TYPE InfoLevel
,
4789 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4791 LPSERVICE_STATUS_PROCESS lpStatus
;
4792 PSERVICE_HANDLE hSvc
;
4795 DPRINT("RQueryServiceStatusEx() called\n");
4798 return ERROR_SHUTDOWN_IN_PROGRESS
;
4800 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4801 return ERROR_INVALID_LEVEL
;
4803 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4805 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4806 return ERROR_INSUFFICIENT_BUFFER
;
4808 hSvc
= ScmGetServiceFromHandle(hService
);
4811 DPRINT1("Invalid service handle!\n");
4812 return ERROR_INVALID_HANDLE
;
4815 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4816 SERVICE_QUERY_STATUS
))
4818 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4819 return ERROR_ACCESS_DENIED
;
4822 lpService
= hSvc
->ServiceEntry
;
4823 if (lpService
== NULL
)
4825 DPRINT("lpService == NULL!\n");
4826 return ERROR_INVALID_HANDLE
;
4829 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4831 /* Return service status information */
4832 RtlCopyMemory(lpStatus
,
4834 sizeof(SERVICE_STATUS
));
4836 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
4837 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4839 return ERROR_SUCCESS
;
4844 DWORD
REnumServicesStatusExA(
4845 SC_RPC_HANDLE hSCManager
,
4846 SC_ENUM_TYPE InfoLevel
,
4847 DWORD dwServiceType
,
4848 DWORD dwServiceState
,
4851 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4852 LPBOUNDED_DWORD_256K lpServicesReturned
,
4853 LPBOUNDED_DWORD_256K lpResumeIndex
,
4854 LPCSTR pszGroupName
)
4856 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
4857 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
4858 LPWSTR lpStringPtrW
;
4860 LPWSTR pszGroupNameW
= NULL
;
4862 DWORD dwServiceCount
;
4864 DPRINT("REnumServicesStatusExA() called\n");
4868 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
4871 DPRINT("Failed to allocate buffer!\n");
4872 return ERROR_NOT_ENOUGH_MEMORY
;
4875 MultiByteToWideChar(CP_ACP
,
4880 strlen(pszGroupName
) + 1);
4883 if ((cbBufSize
> 0) && (lpBuffer
))
4885 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
4888 DPRINT("Failed to allocate buffer!\n");
4889 return ERROR_NOT_ENOUGH_MEMORY
;
4893 dwError
= REnumServicesStatusExW(hSCManager
,
4897 (LPBYTE
)lpStatusPtrW
,
4904 /* if no services were returned then we are Done */
4905 if (*lpServicesReturned
== 0)
4908 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
4909 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
4910 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
4911 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
4912 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4914 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
4916 /* Copy the service name */
4917 WideCharToMultiByte(CP_ACP
,
4922 wcslen(lpStringPtrW
),
4926 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4927 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4928 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4930 /* Copy the display name */
4931 WideCharToMultiByte(CP_ACP
,
4936 wcslen(lpStringPtrW
),
4940 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4941 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4942 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4944 /* Copy the status information */
4945 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
4946 &lpStatusPtrW
->ServiceStatusProcess
,
4947 sizeof(SERVICE_STATUS
));
4949 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
4950 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4956 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
4959 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
4961 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
4968 DWORD
REnumServicesStatusExW(
4969 SC_RPC_HANDLE hSCManager
,
4970 SC_ENUM_TYPE InfoLevel
,
4971 DWORD dwServiceType
,
4972 DWORD dwServiceState
,
4975 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4976 LPBOUNDED_DWORD_256K lpServicesReturned
,
4977 LPBOUNDED_DWORD_256K lpResumeIndex
,
4978 LPCWSTR pszGroupName
)
4980 PMANAGER_HANDLE hManager
;
4982 DWORD dwError
= ERROR_SUCCESS
;
4983 PLIST_ENTRY ServiceEntry
;
4984 PSERVICE CurrentService
;
4986 DWORD dwRequiredSize
;
4987 DWORD dwServiceCount
;
4989 DWORD dwLastResumeCount
= 0;
4990 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
4993 DPRINT("REnumServicesStatusExW() called\n");
4996 return ERROR_SHUTDOWN_IN_PROGRESS
;
4998 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
4999 return ERROR_INVALID_LEVEL
;
5001 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
5002 if (hManager
== NULL
)
5004 DPRINT1("Invalid service manager handle!\n");
5005 return ERROR_INVALID_HANDLE
;
5008 *pcbBytesNeeded
= 0;
5009 *lpServicesReturned
= 0;
5011 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
5013 DPRINT("Not a valid Service Type!\n");
5014 return ERROR_INVALID_PARAMETER
;
5017 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
5019 DPRINT("Not a valid Service State!\n");
5020 return ERROR_INVALID_PARAMETER
;
5023 /* Check access rights */
5024 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
5025 SC_MANAGER_ENUMERATE_SERVICE
))
5027 DPRINT("Insufficient access rights! 0x%lx\n",
5028 hManager
->Handle
.DesiredAccess
);
5029 return ERROR_ACCESS_DENIED
;
5032 if (lpResumeIndex
) dwLastResumeCount
= *lpResumeIndex
;
5034 /* Lock the service list shared */
5036 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
5037 if (lpService
== NULL
)
5039 dwError
= ERROR_SUCCESS
;
5046 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5047 ServiceEntry
!= &ServiceListHead
;
5048 ServiceEntry
= ServiceEntry
->Flink
)
5050 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5054 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5057 dwState
= SERVICE_ACTIVE
;
5058 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5059 dwState
= SERVICE_INACTIVE
;
5061 if ((dwState
& dwServiceState
) == 0)
5066 if (*pszGroupName
== 0)
5068 if (CurrentService
->lpGroup
!= NULL
)
5073 if ((CurrentService
->lpGroup
== NULL
) ||
5074 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5079 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5080 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5081 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5083 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5085 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5086 dwRequiredSize
+= dwSize
;
5088 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5092 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5098 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5099 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5102 ServiceEntry
!= &ServiceListHead
;
5103 ServiceEntry
= ServiceEntry
->Flink
)
5105 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5109 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5112 dwState
= SERVICE_ACTIVE
;
5113 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5114 dwState
= SERVICE_INACTIVE
;
5116 if ((dwState
& dwServiceState
) == 0)
5121 if (*pszGroupName
== 0)
5123 if (CurrentService
->lpGroup
!= NULL
)
5128 if ((CurrentService
->lpGroup
== NULL
) ||
5129 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5134 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5135 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5136 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5138 dwError
= ERROR_MORE_DATA
;
5141 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5144 *lpResumeIndex
= dwLastResumeCount
;
5146 *lpServicesReturned
= dwServiceCount
;
5147 *pcbBytesNeeded
= dwRequiredSize
;
5149 /* If there was no services that matched */
5150 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5152 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5156 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5157 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5158 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5161 for (ServiceEntry
= &lpService
->ServiceListEntry
;
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 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5195 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5196 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5198 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5200 /* Copy the service name */
5202 CurrentService
->lpServiceName
);
5203 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5204 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5206 /* Copy the display name */
5208 CurrentService
->lpDisplayName
);
5209 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5210 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5212 /* Copy the status information */
5213 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5214 &CurrentService
->Status
,
5215 sizeof(SERVICE_STATUS
));
5216 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
5217 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5220 dwRequiredSize
+= dwSize
;
5230 *pcbBytesNeeded
= 0;
5236 /* Unlock the service list */
5238 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5245 DWORD
RSendTSMessage(
5246 handle_t BindingHandle
) /* FIXME */
5249 return ERROR_CALL_NOT_IMPLEMENTED
;
5254 DWORD
RCreateServiceWOW64A(
5255 handle_t BindingHandle
,
5256 LPSTR lpServiceName
,
5257 LPSTR lpDisplayName
,
5258 DWORD dwDesiredAccess
,
5259 DWORD dwServiceType
,
5261 DWORD dwErrorControl
,
5262 LPSTR lpBinaryPathName
,
5263 LPSTR lpLoadOrderGroup
,
5265 LPBYTE lpDependencies
,
5267 LPSTR lpServiceStartName
,
5270 LPSC_RPC_HANDLE lpServiceHandle
)
5273 return ERROR_CALL_NOT_IMPLEMENTED
;
5278 DWORD
RCreateServiceWOW64W(
5279 handle_t BindingHandle
,
5280 LPWSTR lpServiceName
,
5281 LPWSTR lpDisplayName
,
5282 DWORD dwDesiredAccess
,
5283 DWORD dwServiceType
,
5285 DWORD dwErrorControl
,
5286 LPWSTR lpBinaryPathName
,
5287 LPWSTR lpLoadOrderGroup
,
5289 LPBYTE lpDependencies
,
5291 LPWSTR lpServiceStartName
,
5294 LPSC_RPC_HANDLE lpServiceHandle
)
5297 return ERROR_CALL_NOT_IMPLEMENTED
;
5302 DWORD
RQueryServiceTagInfo(
5303 handle_t BindingHandle
) /* FIXME */
5306 return ERROR_CALL_NOT_IMPLEMENTED
;
5311 DWORD
RNotifyServiceStatusChange(
5312 SC_RPC_HANDLE hService
,
5313 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5314 GUID
*pClientProcessGuid
,
5315 GUID
*pSCMProcessGuid
,
5316 PBOOL pfCreateRemoteQueue
,
5317 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5320 return ERROR_CALL_NOT_IMPLEMENTED
;
5325 DWORD
RGetNotifyResults(
5326 SC_NOTIFY_RPC_HANDLE hNotify
,
5327 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5330 return ERROR_CALL_NOT_IMPLEMENTED
;
5335 DWORD
RCloseNotifyHandle(
5336 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5340 return ERROR_CALL_NOT_IMPLEMENTED
;
5345 DWORD
RControlServiceExA(
5346 SC_RPC_HANDLE hService
,
5351 return ERROR_CALL_NOT_IMPLEMENTED
;
5356 DWORD
RControlServiceExW(
5357 SC_RPC_HANDLE hService
,
5362 return ERROR_CALL_NOT_IMPLEMENTED
;
5367 DWORD
RSendPnPMessage(
5368 handle_t BindingHandle
) /* FIXME */
5371 return ERROR_CALL_NOT_IMPLEMENTED
;
5376 DWORD
RValidatePnPService(
5377 handle_t BindingHandle
) /* FIXME */
5380 return ERROR_CALL_NOT_IMPLEMENTED
;
5385 DWORD
ROpenServiceStatusHandle(
5386 handle_t BindingHandle
) /* FIXME */
5389 return ERROR_CALL_NOT_IMPLEMENTED
;
5395 handle_t BindingHandle
) /* FIXME */
5398 return ERROR_CALL_NOT_IMPLEMENTED
;
5402 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5404 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5408 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5410 HeapFree(GetProcessHeap(), 0, ptr
);
5414 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5419 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5424 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)