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
32 typedef struct _MANAGER_HANDLE
36 /* FIXME: Insert more data here */
38 WCHAR DatabaseName
[1];
39 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
42 typedef struct _SERVICE_HANDLE
47 PSERVICE ServiceEntry
;
49 /* FIXME: Insert more data here */
51 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
54 #define SC_MANAGER_READ \
55 (STANDARD_RIGHTS_READ | \
56 SC_MANAGER_QUERY_LOCK_STATUS | \
57 SC_MANAGER_ENUMERATE_SERVICE)
59 #define SC_MANAGER_WRITE \
60 (STANDARD_RIGHTS_WRITE | \
61 SC_MANAGER_MODIFY_BOOT_CONFIG | \
62 SC_MANAGER_CREATE_SERVICE)
64 #define SC_MANAGER_EXECUTE \
65 (STANDARD_RIGHTS_EXECUTE | \
67 SC_MANAGER_ENUMERATE_SERVICE | \
68 SC_MANAGER_CONNECT | \
69 SC_MANAGER_CREATE_SERVICE)
72 #define SERVICE_READ \
73 (STANDARD_RIGHTS_READ | \
74 SERVICE_INTERROGATE | \
75 SERVICE_ENUMERATE_DEPENDENTS | \
76 SERVICE_QUERY_STATUS | \
79 #define SERVICE_WRITE \
80 (STANDARD_RIGHTS_WRITE | \
81 SERVICE_CHANGE_CONFIG)
83 #define SERVICE_EXECUTE \
84 (STANDARD_RIGHTS_EXECUTE | \
85 SERVICE_USER_DEFINED_CONTROL | \
86 SERVICE_PAUSE_CONTINUE | \
91 /* VARIABLES ***************************************************************/
93 static GENERIC_MAPPING
94 ScmManagerMapping
= {SC_MANAGER_READ
,
97 SC_MANAGER_ALL_ACCESS
};
99 static GENERIC_MAPPING
100 ScmServiceMapping
= {SERVICE_READ
,
103 SC_MANAGER_ALL_ACCESS
};
106 /* FUNCTIONS ***************************************************************/
109 ScmStartRpcServer(VOID
)
113 DPRINT("ScmStartRpcServer() called\n");
115 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
119 if (Status
!= RPC_S_OK
)
121 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
125 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
128 if (Status
!= RPC_S_OK
)
130 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
134 Status
= RpcServerListen(1, 20, TRUE
);
135 if (Status
!= RPC_S_OK
)
137 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
141 DPRINT("ScmStartRpcServer() done\n");
146 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
151 if (lpDatabaseName
== NULL
)
152 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
154 if (_wcsicmp(lpDatabaseName
,SERVICES_FAILED_DATABASEW
)==0)
156 DPRINT1("Database %S, does not exist\n",lpDatabaseName
);
157 return ERROR_DATABASE_DOES_NOT_EXIST
;
159 else if (_wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
161 DPRINT1("Invalid Database name %S.\n",lpDatabaseName
);
162 return ERROR_INVALID_NAME
;
165 Ptr
= (MANAGER_HANDLE
*) HeapAlloc(GetProcessHeap(),
167 sizeof(MANAGER_HANDLE
) + (wcslen(lpDatabaseName
) + 1) * sizeof(WCHAR
));
169 return ERROR_NOT_ENOUGH_MEMORY
;
171 Ptr
->Handle
.Tag
= MANAGER_TAG
;
172 Ptr
->Handle
.RefCount
= 1;
174 /* FIXME: initialize more data here */
176 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
178 *Handle
= (SC_HANDLE
)Ptr
;
180 return ERROR_SUCCESS
;
185 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
190 Ptr
= (SERVICE_HANDLE
*) HeapAlloc(GetProcessHeap(),
192 sizeof(SERVICE_HANDLE
));
194 return ERROR_NOT_ENOUGH_MEMORY
;
196 Ptr
->Handle
.Tag
= SERVICE_TAG
;
197 Ptr
->Handle
.RefCount
= 1;
199 /* FIXME: initialize more data here */
200 Ptr
->ServiceEntry
= lpServiceEntry
;
202 *Handle
= (SC_HANDLE
)Ptr
;
204 return ERROR_SUCCESS
;
209 ScmCheckAccess(SC_HANDLE Handle
,
210 DWORD dwDesiredAccess
)
212 PMANAGER_HANDLE hMgr
;
214 hMgr
= (PMANAGER_HANDLE
)Handle
;
215 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
217 RtlMapGenericMask(&dwDesiredAccess
,
220 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
222 return ERROR_SUCCESS
;
224 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
226 RtlMapGenericMask(&dwDesiredAccess
,
229 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
231 return ERROR_SUCCESS
;
234 return ERROR_INVALID_HANDLE
;
239 ScmAssignNewTag(PSERVICE lpService
)
242 DPRINT("Assigning new tag to service %S\n", lpService
->lpServiceName
);
243 lpService
->dwTag
= 0;
244 return ERROR_SUCCESS
;
248 /* Internal recursive function */
249 /* Need to search for every dependency on every service */
251 Int_EnumDependentServicesW(HKEY hServicesKey
,
253 DWORD dwServiceState
,
254 PSERVICE
*lpServices
,
255 LPDWORD pcbBytesNeeded
,
256 LPDWORD lpServicesReturned
)
258 DWORD dwError
= ERROR_SUCCESS
;
259 WCHAR szNameBuf
[MAX_PATH
];
260 WCHAR szValueBuf
[MAX_PATH
];
261 WCHAR
*lpszNameBuf
= szNameBuf
;
262 WCHAR
*lpszValueBuf
= szValueBuf
;
266 PSERVICE lpCurrentService
;
267 HKEY hServiceEnumKey
;
268 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
269 DWORD dwDependServiceStrPtr
= 0;
270 DWORD dwRequiredSize
= 0;
272 /* Get the number of service keys */
273 dwError
= RegQueryInfoKeyW(hServicesKey
,
285 if (dwError
!= ERROR_SUCCESS
)
287 DPRINT1("ERROR! Unable to get number of services keys.\n");
291 /* Iterate the service keys to see if another service depends on the this service */
292 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
295 dwError
= RegEnumKeyExW(hServicesKey
,
303 if (dwError
!= ERROR_SUCCESS
)
306 /* Open the Service key */
307 dwError
= RegOpenKeyExW(hServicesKey
,
312 if (dwError
!= ERROR_SUCCESS
)
317 /* Check for the DependOnService Value */
318 dwError
= RegQueryValueExW(hServiceEnumKey
,
322 (LPBYTE
)lpszValueBuf
,
325 /* FIXME: Handle load order. */
327 /* If the service found has a DependOnService value */
328 if (dwError
== ERROR_SUCCESS
)
330 dwDependServiceStrPtr
= 0;
332 /* Can be more than one Dependencies in the DependOnService string */
333 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
335 if (_wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
337 /* Get the current enumed service pointer */
338 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
340 /* Check for valid Service */
341 if (!lpCurrentService
)
343 /* This should never happen! */
344 DPRINT1("This should not happen at this point, report to Developer\n");
345 return ERROR_NOT_FOUND
;
348 /* Determine state the service is in */
349 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
350 dwCurrentServiceState
= SERVICE_INACTIVE
;
352 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
353 if ((dwCurrentServiceState
== dwServiceState
) ||
354 (dwServiceState
== SERVICE_STATE_ALL
))
356 /* Calculate the required size */
357 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
358 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
359 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
361 /* Add the size for service name and display name pointers */
362 dwRequiredSize
+= (2 * sizeof(PVOID
));
364 /* increase the BytesNeeded size */
365 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
367 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
370 /* Recursive call to check for its dependencies */
371 Int_EnumDependentServicesW(hServicesKey
,
378 /* If the lpServices is valid set the service pointer */
380 lpServices
[*lpServicesReturned
] = lpCurrentService
;
382 *lpServicesReturned
= *lpServicesReturned
+ 1;
386 dwDependServiceStrPtr
+= (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
389 else if (*pcbBytesNeeded
)
391 dwError
= ERROR_SUCCESS
;
394 RegCloseKey(hServiceEnumKey
);
402 DWORD
RCloseServiceHandle(
403 LPSC_RPC_HANDLE hSCObject
)
405 PMANAGER_HANDLE hManager
;
406 PSERVICE_HANDLE hService
;
410 DWORD pcbBytesNeeded
= 0;
411 DWORD dwServicesReturned
= 0;
413 DPRINT("RCloseServiceHandle() called\n");
415 DPRINT("hSCObject = %p\n", *hSCObject
);
418 return ERROR_INVALID_HANDLE
;
420 hManager
= (PMANAGER_HANDLE
)*hSCObject
;
421 hService
= (PSERVICE_HANDLE
)*hSCObject
;
422 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
424 DPRINT("Found manager handle\n");
426 hManager
->Handle
.RefCount
--;
427 if (hManager
->Handle
.RefCount
== 0)
429 /* FIXME: add handle cleanup code */
431 HeapFree(GetProcessHeap(), 0, hManager
);
435 DPRINT("RCloseServiceHandle() done\n");
436 return ERROR_SUCCESS
;
438 else if (hService
->Handle
.Tag
== SERVICE_TAG
)
440 DPRINT("Found service handle\n");
442 /* Get the pointer to the service record */
443 lpService
= hService
->ServiceEntry
;
445 ASSERT(hService
->Handle
.RefCount
> 0);
447 hService
->Handle
.RefCount
--;
448 if (hService
->Handle
.RefCount
== 0)
450 /* FIXME: add handle cleanup code */
452 /* Free the handle */
453 HeapFree(GetProcessHeap(), 0, hService
);
457 ASSERT(lpService
->dwRefCount
> 0);
459 lpService
->dwRefCount
--;
460 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
461 lpService
->dwRefCount
);
463 if (lpService
->dwRefCount
== 0)
465 /* If this service has been marked for deletion */
466 if (lpService
->bDeleted
)
468 /* Open the Services Reg key */
469 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
470 L
"System\\CurrentControlSet\\Services",
472 KEY_SET_VALUE
| KEY_READ
,
474 if (dwError
!= ERROR_SUCCESS
)
476 DPRINT1("Failed to open services key\n");
480 /* Call the internal function with NULL, just to get bytes we need */
481 Int_EnumDependentServicesW(hServicesKey
,
486 &dwServicesReturned
);
488 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
491 DPRINT1("Deletion failed due to running dependencies.\n");
492 RegCloseKey(hServicesKey
);
493 return ERROR_SUCCESS
;
496 /* There are no references and no runnning dependencies,
497 it is now safe to delete the service */
499 /* Delete the Service Key */
500 dwError
= RegDeleteKeyW(hServicesKey
,
501 lpService
->lpServiceName
);
503 RegCloseKey(hServicesKey
);
505 if (dwError
!= ERROR_SUCCESS
)
507 DPRINT1("Failed to Delete the Service Registry key\n");
511 /* Delete the Service */
512 ScmDeleteServiceRecord(lpService
);
516 DPRINT("RCloseServiceHandle() done\n");
517 return ERROR_SUCCESS
;
520 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
522 return ERROR_INVALID_HANDLE
;
527 DWORD
RControlService(
528 SC_RPC_HANDLE hService
,
530 LPSERVICE_STATUS lpServiceStatus
)
532 PSERVICE_HANDLE hSvc
;
534 ACCESS_MASK DesiredAccess
;
535 DWORD dwError
= ERROR_SUCCESS
;
536 DWORD pcbBytesNeeded
= 0;
537 DWORD dwServicesReturned
= 0;
538 HKEY hServicesKey
= NULL
;
540 DPRINT("RControlService() called\n");
543 return ERROR_SHUTDOWN_IN_PROGRESS
;
545 /* Check the service handle */
546 hSvc
= (PSERVICE_HANDLE
)hService
;
547 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
549 DPRINT1("Invalid handle tag!\n");
550 return ERROR_INVALID_HANDLE
;
553 /* Check the service entry point */
554 lpService
= hSvc
->ServiceEntry
;
555 if (lpService
== NULL
)
557 DPRINT1("lpService == NULL!\n");
558 return ERROR_INVALID_HANDLE
;
561 /* Check access rights */
564 case SERVICE_CONTROL_STOP
:
565 DesiredAccess
= SERVICE_STOP
;
568 case SERVICE_CONTROL_PAUSE
:
569 case SERVICE_CONTROL_CONTINUE
:
570 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
573 case SERVICE_INTERROGATE
:
574 DesiredAccess
= SERVICE_INTERROGATE
;
578 if (dwControl
>= 128 && dwControl
<= 255)
579 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
581 DesiredAccess
= SERVICE_QUERY_CONFIG
|
582 SERVICE_CHANGE_CONFIG
|
583 SERVICE_QUERY_STATUS
|
585 SERVICE_PAUSE_CONTINUE
;
589 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
591 return ERROR_ACCESS_DENIED
;
593 if (dwControl
== SERVICE_CONTROL_STOP
)
595 /* Check if the service has dependencies running as windows
596 doesn't stop a service that does */
598 /* Open the Services Reg key */
599 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
600 L
"System\\CurrentControlSet\\Services",
604 if (dwError
!= ERROR_SUCCESS
)
606 DPRINT1("Failed to open services key\n");
610 /* Call the internal function with NULL, just to get bytes we need */
611 Int_EnumDependentServicesW(hServicesKey
,
616 &dwServicesReturned
);
618 RegCloseKey(hServicesKey
);
620 /* If pcbBytesNeeded is not zero then there are services running that
621 are dependent on this service */
622 if (pcbBytesNeeded
!= 0)
624 DPRINT("Service has running dependencies. Failed to stop service.\n");
625 return ERROR_DEPENDENT_SERVICES_RUNNING
;
629 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
631 /* Send control code to the driver */
632 dwError
= ScmControlDriver(lpService
,
638 /* Send control code to the service */
639 dwError
= ScmControlService(lpService
,
644 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
645 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
647 if (dwError
== ERROR_SUCCESS
&&
648 dwControl
== SERVICE_CONTROL_STOP
&&
649 lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
)
651 lpService
->ProcessId
= 0; /* FIXME */
652 lpService
->ThreadId
= 0;
655 /* Return service status information */
656 RtlCopyMemory(lpServiceStatus
,
658 sizeof(SERVICE_STATUS
));
665 DWORD
RDeleteService(
666 SC_RPC_HANDLE hService
)
668 PSERVICE_HANDLE hSvc
;
672 DPRINT("RDeleteService() called\n");
675 return ERROR_SHUTDOWN_IN_PROGRESS
;
677 hSvc
= (PSERVICE_HANDLE
)hService
;
678 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
679 return ERROR_INVALID_HANDLE
;
681 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
683 return ERROR_ACCESS_DENIED
;
685 lpService
= hSvc
->ServiceEntry
;
686 if (lpService
== NULL
)
688 DPRINT1("lpService == NULL!\n");
689 return ERROR_INVALID_HANDLE
;
692 /* FIXME: Acquire service database lock exclusively */
694 if (lpService
->bDeleted
)
696 DPRINT1("The service has already been marked for delete!\n");
697 return ERROR_SERVICE_MARKED_FOR_DELETE
;
700 /* Mark service for delete */
701 lpService
->bDeleted
= TRUE
;
703 dwError
= ScmMarkServiceForDelete(lpService
);
705 /* FIXME: Release service database lock */
707 DPRINT("RDeleteService() done\n");
714 DWORD
RLockServiceDatabase(
715 SC_RPC_HANDLE hSCManager
,
716 LPSC_RPC_LOCK lpLock
)
718 PMANAGER_HANDLE hMgr
;
720 DPRINT("RLockServiceDatabase() called\n");
724 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
725 if (!hMgr
|| hMgr
->Handle
.Tag
!= MANAGER_TAG
)
726 return ERROR_INVALID_HANDLE
;
728 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
730 return ERROR_ACCESS_DENIED
;
732 // return ScmLockDatabase(0, hMgr->0xC, hLock);
734 /* FIXME: Lock the database */
735 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
737 return ERROR_SUCCESS
;
742 DWORD
RQueryServiceObjectSecurity(
743 SC_RPC_HANDLE hService
,
744 SECURITY_INFORMATION dwSecurityInformation
,
745 LPBYTE lpSecurityDescriptor
,
747 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
749 PSERVICE_HANDLE hSvc
;
751 ULONG DesiredAccess
= 0;
757 SECURITY_DESCRIPTOR ObjectDescriptor
;
759 DPRINT("RQueryServiceObjectSecurity() called\n");
761 hSvc
= (PSERVICE_HANDLE
)hService
;
762 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
764 DPRINT1("Invalid handle tag!\n");
765 return ERROR_INVALID_HANDLE
;
768 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
769 GROUP_SECURITY_INFORMATION
||
770 OWNER_SECURITY_INFORMATION
))
771 DesiredAccess
|= READ_CONTROL
;
773 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
774 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
776 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
779 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
780 return ERROR_ACCESS_DENIED
;
783 lpService
= hSvc
->ServiceEntry
;
784 if (lpService
== NULL
)
786 DPRINT1("lpService == NULL!\n");
787 return ERROR_INVALID_HANDLE
;
790 /* FIXME: Lock the service list */
793 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
795 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
796 dwSecurityInformation
,
797 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
801 /* FIXME: Unlock the service list */
803 if (NT_SUCCESS(Status
))
805 *pcbBytesNeeded
= dwBytesNeeded
;
806 dwError
= STATUS_SUCCESS
;
808 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
810 *pcbBytesNeeded
= dwBytesNeeded
;
811 dwError
= ERROR_INSUFFICIENT_BUFFER
;
813 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
815 dwError
= ERROR_GEN_FAILURE
;
819 dwError
= RtlNtStatusToDosError(Status
);
827 DWORD
RSetServiceObjectSecurity(
828 SC_RPC_HANDLE hService
,
829 DWORD dwSecurityInformation
,
830 LPBYTE lpSecurityDescriptor
,
831 DWORD dwSecuityDescriptorSize
)
833 PSERVICE_HANDLE hSvc
;
835 ULONG DesiredAccess
= 0;
836 /* HANDLE hToken = NULL; */
838 /* NTSTATUS Status; */
841 DPRINT1("RSetServiceObjectSecurity() called\n");
843 hSvc
= (PSERVICE_HANDLE
)hService
;
844 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
846 DPRINT1("Invalid handle tag!\n");
847 return ERROR_INVALID_HANDLE
;
850 if (dwSecurityInformation
== 0 ||
851 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
852 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
853 return ERROR_INVALID_PARAMETER
;
855 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
856 return ERROR_INVALID_PARAMETER
;
858 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
859 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
861 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
862 DesiredAccess
|= WRITE_DAC
;
864 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
865 DesiredAccess
|= WRITE_OWNER
;
867 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
868 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
869 return ERROR_INVALID_PARAMETER
;
871 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
872 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
873 return ERROR_INVALID_PARAMETER
;
875 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
878 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
879 return ERROR_ACCESS_DENIED
;
882 lpService
= hSvc
->ServiceEntry
;
883 if (lpService
== NULL
)
885 DPRINT1("lpService == NULL!\n");
886 return ERROR_INVALID_HANDLE
;
889 if (lpService
->bDeleted
)
890 return ERROR_SERVICE_MARKED_FOR_DELETE
;
893 RpcImpersonateClient(NULL
);
895 Status
= NtOpenThreadToken(NtCurrentThread(),
899 if (!NT_SUCCESS(Status
))
900 return RtlNtStatusToDosError(Status
);
904 /* FIXME: Lock service database */
906 Status
= RtlSetSecurityObject(dwSecurityInformation
,
907 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
908 &lpService
->lpSecurityDescriptor
,
911 if (!NT_SUCCESS(Status
))
913 dwError
= RtlNtStatusToDosError(Status
);
918 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
919 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
921 if (dwError
!= ERROR_SUCCESS
)
925 dwError
= ERROR_SUCCESS
;
926 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
927 // lpService->lpSecurityDescriptor);
929 RegFlushKey(hServiceKey
);
930 RegCloseKey(hServiceKey
);
939 /* FIXME: Unlock service database */
941 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
948 DWORD
RQueryServiceStatus(
949 SC_RPC_HANDLE hService
,
950 LPSERVICE_STATUS lpServiceStatus
)
952 PSERVICE_HANDLE hSvc
;
955 DPRINT("RQueryServiceStatus() called\n");
958 return ERROR_SHUTDOWN_IN_PROGRESS
;
960 hSvc
= (PSERVICE_HANDLE
)hService
;
961 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
963 DPRINT1("Invalid handle tag!\n");
964 return ERROR_INVALID_HANDLE
;
967 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
968 SERVICE_QUERY_STATUS
))
970 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
971 return ERROR_ACCESS_DENIED
;
974 lpService
= hSvc
->ServiceEntry
;
975 if (lpService
== NULL
)
977 DPRINT1("lpService == NULL!\n");
978 return ERROR_INVALID_HANDLE
;
981 /* Return service status information */
982 RtlCopyMemory(lpServiceStatus
,
984 sizeof(SERVICE_STATUS
));
986 return ERROR_SUCCESS
;
991 ScmIsValidServiceState(DWORD dwCurrentState
)
993 switch (dwCurrentState
)
995 case SERVICE_STOPPED
:
996 case SERVICE_START_PENDING
:
997 case SERVICE_STOP_PENDING
:
998 case SERVICE_RUNNING
:
999 case SERVICE_CONTINUE_PENDING
:
1000 case SERVICE_PAUSE_PENDING
:
1001 case SERVICE_PAUSED
:
1011 DWORD
RSetServiceStatus(
1012 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1013 LPSERVICE_STATUS lpServiceStatus
)
1017 DPRINT("RSetServiceStatus() called\n");
1018 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1019 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1020 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1021 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1022 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1023 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1024 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1025 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1027 if (hServiceStatus
== 0)
1029 DPRINT1("hServiceStatus == NULL!\n");
1030 return ERROR_INVALID_HANDLE
;
1033 lpService
= ScmGetServiceEntryByClientHandle((HANDLE
)hServiceStatus
);
1034 if (lpService
== NULL
)
1036 DPRINT1("lpService == NULL!\n");
1037 return ERROR_INVALID_HANDLE
;
1040 /* Check current state */
1041 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1043 DPRINT1("Invalid service state!\n");
1044 return ERROR_INVALID_DATA
;
1047 /* Check service type */
1048 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1049 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1051 DPRINT1("Invalid service type!\n");
1052 return ERROR_INVALID_DATA
;
1055 /* Check accepted controls */
1056 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1058 DPRINT1("Invalid controls accepted!\n");
1059 return ERROR_INVALID_DATA
;
1063 RtlCopyMemory(&lpService
->Status
,
1065 sizeof(SERVICE_STATUS
));
1067 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1068 DPRINT("RSetServiceStatus() done\n");
1070 return ERROR_SUCCESS
;
1075 DWORD
RUnlockServiceDatabase(
1079 return ERROR_SUCCESS
;
1084 DWORD
RNotifyBootConfigStatus(
1085 SVCCTL_HANDLEW lpMachineName
,
1086 DWORD BootAcceptable
)
1089 return ERROR_CALL_NOT_IMPLEMENTED
;
1094 DWORD
RI_ScSetServiceBitsW(
1095 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1096 DWORD dwServiceBits
,
1098 int bUpdateImmediately
,
1102 return ERROR_CALL_NOT_IMPLEMENTED
;
1107 DWORD
RChangeServiceConfigW(
1108 SC_RPC_HANDLE hService
,
1109 DWORD dwServiceType
,
1111 DWORD dwErrorControl
,
1112 LPWSTR lpBinaryPathName
,
1113 LPWSTR lpLoadOrderGroup
,
1115 LPBYTE lpDependencies
,
1117 LPWSTR lpServiceStartName
,
1120 LPWSTR lpDisplayName
)
1122 DWORD dwError
= ERROR_SUCCESS
;
1123 PSERVICE_HANDLE hSvc
;
1124 PSERVICE lpService
= NULL
;
1125 HKEY hServiceKey
= NULL
;
1126 LPWSTR lpDisplayNameW
= NULL
;
1128 DPRINT("RChangeServiceConfigW() called\n");
1129 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1130 DPRINT("dwStartType = %lu\n", dwStartType
);
1131 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1132 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1133 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1134 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1137 return ERROR_SHUTDOWN_IN_PROGRESS
;
1139 hSvc
= (PSERVICE_HANDLE
)hService
;
1140 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1142 DPRINT1("Invalid handle tag!\n");
1143 return ERROR_INVALID_HANDLE
;
1146 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1147 SERVICE_CHANGE_CONFIG
))
1149 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1150 return ERROR_ACCESS_DENIED
;
1153 lpService
= hSvc
->ServiceEntry
;
1154 if (lpService
== NULL
)
1156 DPRINT1("lpService == NULL!\n");
1157 return ERROR_INVALID_HANDLE
;
1160 /* FIXME: Lock database exclusively */
1162 if (lpService
->bDeleted
)
1164 /* FIXME: Unlock database */
1165 DPRINT1("The service has already been marked for delete!\n");
1166 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1169 /* Open the service key */
1170 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1173 if (dwError
!= ERROR_SUCCESS
)
1176 /* Write service data to the registry */
1177 /* Set the display name */
1178 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1180 RegSetValueExW(hServiceKey
,
1184 (LPBYTE
)lpDisplayName
,
1185 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1187 /* Update the display name */
1188 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1190 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1191 if (lpDisplayNameW
== NULL
)
1193 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1197 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1198 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1200 lpService
->lpDisplayName
= lpDisplayNameW
;
1203 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1205 /* Set the service type */
1206 dwError
= RegSetValueExW(hServiceKey
,
1210 (LPBYTE
)&dwServiceType
,
1212 if (dwError
!= ERROR_SUCCESS
)
1215 lpService
->Status
.dwServiceType
= dwServiceType
;
1218 if (dwStartType
!= SERVICE_NO_CHANGE
)
1220 /* Set the start value */
1221 dwError
= RegSetValueExW(hServiceKey
,
1225 (LPBYTE
)&dwStartType
,
1227 if (dwError
!= ERROR_SUCCESS
)
1230 lpService
->dwStartType
= dwStartType
;
1233 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1235 /* Set the error control value */
1236 dwError
= RegSetValueExW(hServiceKey
,
1240 (LPBYTE
)&dwErrorControl
,
1242 if (dwError
!= ERROR_SUCCESS
)
1245 lpService
->dwErrorControl
= dwErrorControl
;
1249 /* FIXME: set the new ImagePath value */
1251 /* Set the image path */
1252 if (dwServiceType
& SERVICE_WIN32
)
1254 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1256 dwError
= RegSetValueExW(hServiceKey
,
1260 (LPBYTE
)lpBinaryPathName
,
1261 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1262 if (dwError
!= ERROR_SUCCESS
)
1266 else if (dwServiceType
& SERVICE_DRIVER
)
1268 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1270 dwError
= RegSetValueExW(hServiceKey
,
1274 (LPBYTE
)lpImagePath
,
1275 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1276 if (dwError
!= ERROR_SUCCESS
)
1282 /* Set the group name */
1283 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1285 dwError
= RegSetValueExW(hServiceKey
,
1289 (LPBYTE
)lpLoadOrderGroup
,
1290 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1291 if (dwError
!= ERROR_SUCCESS
)
1294 dwError
= ScmSetServiceGroup(lpService
,
1296 if (dwError
!= ERROR_SUCCESS
)
1300 if (lpdwTagId
!= NULL
)
1302 dwError
= ScmAssignNewTag(lpService
);
1303 if (dwError
!= ERROR_SUCCESS
)
1306 dwError
= RegSetValueExW(hServiceKey
,
1310 (LPBYTE
)&lpService
->dwTag
,
1312 if (dwError
!= ERROR_SUCCESS
)
1315 *lpdwTagId
= lpService
->dwTag
;
1318 /* Write dependencies */
1319 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1321 dwError
= ScmWriteDependencies(hServiceKey
,
1322 (LPWSTR
)lpDependencies
,
1324 if (dwError
!= ERROR_SUCCESS
)
1328 if (lpPassword
!= NULL
)
1330 /* FIXME: Write password */
1333 /* FIXME: Unlock database */
1336 if (hServiceKey
!= NULL
)
1337 RegCloseKey(hServiceKey
);
1339 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1345 /* Create a path suitable for the bootloader out of the full path */
1347 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1349 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1352 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1353 OBJECT_ATTRIBUTES ObjectAttributes
;
1355 HANDLE SymbolicLinkHandle
;
1357 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1359 ServiceNameLen
= wcslen(CanonName
);
1361 /* First check, if it's already good */
1362 if (ServiceNameLen
> 12 &&
1363 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1365 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1366 if (*RelativeName
== NULL
)
1368 DPRINT1("Error allocating memory for boot driver name!\n");
1369 return ERROR_NOT_ENOUGH_MEMORY
;
1373 wcscpy(*RelativeName
, CanonName
);
1375 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1376 return ERROR_SUCCESS
;
1379 /* If it has %SystemRoot% prefix, substitute it to \System*/
1380 if (ServiceNameLen
> 13 &&
1381 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1383 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1384 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1386 if (*RelativeName
== NULL
)
1388 DPRINT1("Error allocating memory for boot driver name!\n");
1389 return ERROR_NOT_ENOUGH_MEMORY
;
1393 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1394 wcscat(*RelativeName
, CanonName
+ 13);
1396 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1397 return ERROR_SUCCESS
;
1400 /* Get buffer size needed for expanding env strings */
1401 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1403 if (BufferSize
<= 1)
1405 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1406 return ERROR_INVALID_ENVIRONMENT
;
1409 /* Allocate memory, since the size is known now */
1410 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1413 DPRINT1("Error allocating memory for boot driver name!\n");
1414 return ERROR_NOT_ENOUGH_MEMORY
;
1418 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1421 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1422 LocalFree(Expanded
);
1423 return ERROR_NOT_ENOUGH_MEMORY
;
1426 /* Convert to NY-style path */
1427 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1429 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1430 return ERROR_INVALID_ENVIRONMENT
;
1433 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1435 /* No need to keep the dos-path anymore */
1436 LocalFree(Expanded
);
1438 /* Copy it to the allocated place */
1439 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1442 DPRINT1("Error allocating memory for boot driver name!\n");
1443 return ERROR_NOT_ENOUGH_MEMORY
;
1446 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1447 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1448 Expanded
[ExpandedLen
] = 0;
1450 if (ServiceNameLen
> ExpandedLen
&&
1451 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1453 /* Only \SystemRoot\ is missing */
1454 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1455 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1456 if (*RelativeName
== NULL
)
1458 DPRINT1("Error allocating memory for boot driver name!\n");
1459 LocalFree(Expanded
);
1460 return ERROR_NOT_ENOUGH_MEMORY
;
1463 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1464 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1466 RtlFreeUnicodeString(&NtPathName
);
1467 return ERROR_SUCCESS
;
1470 /* The most complex case starts here */
1471 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1472 InitializeObjectAttributes(&ObjectAttributes
,
1474 OBJ_CASE_INSENSITIVE
,
1478 /* Open this symlink */
1479 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1481 if (NT_SUCCESS(Status
))
1483 LinkTarget
.Length
= 0;
1484 LinkTarget
.MaximumLength
= 0;
1486 DPRINT("Opened symbolic link object\n");
1488 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1489 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1491 /* Check if required buffer size is sane */
1492 if (BufferSize
> 0xFFFD)
1494 DPRINT1("Too large buffer required\n");
1497 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1498 LocalFree(Expanded
);
1499 return ERROR_NOT_ENOUGH_MEMORY
;
1502 /* Alloc the string */
1503 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1504 if (!LinkTarget
.Buffer
)
1506 DPRINT1("Unable to alloc buffer\n");
1507 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1508 LocalFree(Expanded
);
1509 return ERROR_NOT_ENOUGH_MEMORY
;
1512 /* Do a real query now */
1513 LinkTarget
.Length
= BufferSize
;
1514 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1516 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1517 if (NT_SUCCESS(Status
))
1519 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1521 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1522 if ((ServiceNameLen
> ExpandedLen
) &&
1523 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1525 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1526 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1528 if (*RelativeName
== NULL
)
1530 DPRINT1("Unable to alloc buffer\n");
1531 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1532 LocalFree(Expanded
);
1533 RtlFreeUnicodeString(&NtPathName
);
1534 return ERROR_NOT_ENOUGH_MEMORY
;
1537 /* Copy it over, substituting the first part
1539 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1540 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1543 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1544 LocalFree(Expanded
);
1545 RtlFreeUnicodeString(&NtPathName
);
1547 /* Return success */
1548 return ERROR_SUCCESS
;
1552 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1553 LocalFree(Expanded
);
1554 RtlFreeUnicodeString(&NtPathName
);
1555 return ERROR_INVALID_PARAMETER
;
1560 DPRINT1("Error, Status = %08X\n", Status
);
1561 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1562 LocalFree(Expanded
);
1563 RtlFreeUnicodeString(&NtPathName
);
1564 return ERROR_INVALID_PARAMETER
;
1569 DPRINT1("Error, Status = %08X\n", Status
);
1570 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1571 LocalFree(Expanded
);
1572 RtlFreeUnicodeString(&NtPathName
);
1573 return ERROR_INVALID_PARAMETER
;
1578 DPRINT1("Error, Status = %08X\n", Status
);
1579 LocalFree(Expanded
);
1580 return ERROR_INVALID_PARAMETER
;
1584 *RelativeName
= NULL
;
1585 return ERROR_INVALID_PARAMETER
;
1589 ScmCanonDriverImagePath(DWORD dwStartType
,
1590 const wchar_t *lpServiceName
,
1591 wchar_t **lpCanonName
)
1593 DWORD ServiceNameLen
, Result
;
1594 UNICODE_STRING NtServiceName
;
1595 WCHAR
*RelativeName
;
1596 const WCHAR
*SourceName
= lpServiceName
;
1598 /* Calculate the length of the service's name */
1599 ServiceNameLen
= wcslen(lpServiceName
);
1601 /* 12 is wcslen(L"\\SystemRoot\\") */
1602 if (ServiceNameLen
> 12 &&
1603 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1605 /* SystemRoot prefix is already included */
1607 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1609 if (*lpCanonName
== NULL
)
1611 DPRINT1("Error allocating memory for canonized service name!\n");
1612 return ERROR_NOT_ENOUGH_MEMORY
;
1615 /* If it's a boot-time driver, it must be systemroot relative */
1616 if (dwStartType
== SERVICE_BOOT_START
)
1620 wcscpy(*lpCanonName
, SourceName
);
1622 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1626 /* Check if it has %SystemRoot% (len=13) */
1627 if (ServiceNameLen
> 13 &&
1628 !_wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1630 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1631 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1633 if (*lpCanonName
== NULL
)
1635 DPRINT1("Error allocating memory for canonized service name!\n");
1636 return ERROR_NOT_ENOUGH_MEMORY
;
1639 /* If it's a boot-time driver, it must be systemroot relative */
1640 if (dwStartType
== SERVICE_BOOT_START
)
1641 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1643 wcscat(*lpCanonName
, lpServiceName
+ 13);
1645 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1649 /* Check if it's a relative path name */
1650 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1652 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1654 if (*lpCanonName
== NULL
)
1656 DPRINT1("Error allocating memory for canonized service name!\n");
1657 return ERROR_NOT_ENOUGH_MEMORY
;
1660 /* Just copy it over without changing */
1661 wcscpy(*lpCanonName
, lpServiceName
);
1666 /* It seems to be a DOS path, convert it */
1667 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1669 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1670 return ERROR_INVALID_PARAMETER
;
1673 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1675 if (*lpCanonName
== NULL
)
1677 DPRINT1("Error allocating memory for canonized service name!\n");
1678 RtlFreeUnicodeString(&NtServiceName
);
1679 return ERROR_NOT_ENOUGH_MEMORY
;
1682 /* Copy the string */
1683 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1685 /* The unicode string is not needed anymore */
1686 RtlFreeUnicodeString(&NtServiceName
);
1688 if (dwStartType
!= SERVICE_BOOT_START
)
1690 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1694 /* The service is boot-started, so must be relative */
1695 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1698 /* There is a problem, free name and return */
1699 LocalFree(*lpCanonName
);
1700 DPRINT1("Error converting named!\n");
1704 ASSERT(RelativeName
);
1706 /* Copy that string */
1707 wcscpy(*lpCanonName
, RelativeName
+ 12);
1709 /* Free the allocated buffer */
1710 LocalFree(RelativeName
);
1712 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1720 DWORD
RCreateServiceW(
1721 SC_RPC_HANDLE hSCManager
,
1722 LPCWSTR lpServiceName
,
1723 LPCWSTR lpDisplayName
,
1724 DWORD dwDesiredAccess
,
1725 DWORD dwServiceType
,
1727 DWORD dwErrorControl
,
1728 LPCWSTR lpBinaryPathName
,
1729 LPCWSTR lpLoadOrderGroup
,
1731 LPBYTE lpDependencies
,
1733 LPCWSTR lpServiceStartName
,
1736 LPSC_RPC_HANDLE lpServiceHandle
)
1738 PMANAGER_HANDLE hManager
;
1739 DWORD dwError
= ERROR_SUCCESS
;
1740 PSERVICE lpService
= NULL
;
1741 SC_HANDLE hServiceHandle
= NULL
;
1742 LPWSTR lpImagePath
= NULL
;
1743 HKEY hServiceKey
= NULL
;
1744 LPWSTR lpObjectName
;
1746 DPRINT("RCreateServiceW() called\n");
1747 DPRINT("lpServiceName = %S\n", lpServiceName
);
1748 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1749 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1750 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1751 DPRINT("dwStartType = %lu\n", dwStartType
);
1752 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1753 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1754 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1757 return ERROR_SHUTDOWN_IN_PROGRESS
;
1759 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1760 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1762 DPRINT1("Invalid manager handle!\n");
1763 return ERROR_INVALID_HANDLE
;
1766 /* Check access rights */
1767 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1768 SC_MANAGER_CREATE_SERVICE
))
1770 DPRINT1("Insufficient access rights! 0x%lx\n",
1771 hManager
->Handle
.DesiredAccess
);
1772 return ERROR_ACCESS_DENIED
;
1775 if (wcslen(lpServiceName
) == 0)
1777 return ERROR_INVALID_NAME
;
1780 if (wcslen(lpBinaryPathName
) == 0)
1782 return ERROR_INVALID_PARAMETER
;
1785 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1786 (lpServiceStartName
))
1788 return ERROR_INVALID_PARAMETER
;
1791 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1792 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1793 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1795 return ERROR_INVALID_PARAMETER
;
1798 if (dwStartType
> SERVICE_DISABLED
)
1800 return ERROR_INVALID_PARAMETER
;
1803 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1806 /* check if it is marked for deletion */
1807 if (lpService
->bDeleted
)
1808 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1809 /* Return Error exist */
1810 return ERROR_SERVICE_EXISTS
;
1813 if (lpDisplayName
!= NULL
&&
1814 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1815 return ERROR_DUPLICATE_SERVICE_NAME
;
1817 if (dwServiceType
& SERVICE_DRIVER
)
1819 dwError
= ScmCanonDriverImagePath(dwStartType
,
1822 if (dwError
!= ERROR_SUCCESS
)
1827 if (dwStartType
== SERVICE_BOOT_START
||
1828 dwStartType
== SERVICE_SYSTEM_START
)
1830 return ERROR_INVALID_PARAMETER
;
1834 /* Allocate a new service entry */
1835 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1837 if (dwError
!= ERROR_SUCCESS
)
1840 /* Fill the new service entry */
1841 lpService
->Status
.dwServiceType
= dwServiceType
;
1842 lpService
->dwStartType
= dwStartType
;
1843 lpService
->dwErrorControl
= dwErrorControl
;
1845 /* Fill the display name */
1846 if (lpDisplayName
!= NULL
&&
1847 *lpDisplayName
!= 0 &&
1848 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1850 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1851 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1852 if (lpService
->lpDisplayName
== NULL
)
1854 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1857 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1860 /* Assign the service to a group */
1861 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1863 dwError
= ScmSetServiceGroup(lpService
,
1865 if (dwError
!= ERROR_SUCCESS
)
1869 /* Assign a new tag */
1870 if (lpdwTagId
!= NULL
)
1872 dwError
= ScmAssignNewTag(lpService
);
1873 if (dwError
!= ERROR_SUCCESS
)
1877 /* Write service data to the registry */
1878 /* Create the service key */
1879 dwError
= ScmCreateServiceKey(lpServiceName
,
1882 if (dwError
!= ERROR_SUCCESS
)
1885 /* Set the display name */
1886 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1888 RegSetValueExW(hServiceKey
,
1892 (LPBYTE
)lpDisplayName
,
1893 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1896 /* Set the service type */
1897 dwError
= RegSetValueExW(hServiceKey
,
1901 (LPBYTE
)&dwServiceType
,
1903 if (dwError
!= ERROR_SUCCESS
)
1906 /* Set the start value */
1907 dwError
= RegSetValueExW(hServiceKey
,
1911 (LPBYTE
)&dwStartType
,
1913 if (dwError
!= ERROR_SUCCESS
)
1916 /* Set the error control value */
1917 dwError
= RegSetValueExW(hServiceKey
,
1921 (LPBYTE
)&dwErrorControl
,
1923 if (dwError
!= ERROR_SUCCESS
)
1926 /* Set the image path */
1927 if (dwServiceType
& SERVICE_WIN32
)
1929 dwError
= RegSetValueExW(hServiceKey
,
1933 (LPBYTE
)lpBinaryPathName
,
1934 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1935 if (dwError
!= ERROR_SUCCESS
)
1938 else if (dwServiceType
& SERVICE_DRIVER
)
1940 dwError
= RegSetValueExW(hServiceKey
,
1944 (LPBYTE
)lpImagePath
,
1945 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1946 if (dwError
!= ERROR_SUCCESS
)
1950 /* Set the group name */
1951 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1953 dwError
= RegSetValueExW(hServiceKey
,
1957 (LPBYTE
)lpLoadOrderGroup
,
1958 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1959 if (dwError
!= ERROR_SUCCESS
)
1963 if (lpdwTagId
!= NULL
)
1965 dwError
= RegSetValueExW(hServiceKey
,
1969 (LPBYTE
)&lpService
->dwTag
,
1971 if (dwError
!= ERROR_SUCCESS
)
1975 /* Write dependencies */
1976 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1978 dwError
= ScmWriteDependencies(hServiceKey
,
1979 (LPWSTR
)lpDependencies
,
1981 if (dwError
!= ERROR_SUCCESS
)
1985 /* Write service start name */
1986 if (dwServiceType
& SERVICE_WIN32
)
1988 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
1989 dwError
= RegSetValueExW(hServiceKey
,
1993 (LPBYTE
)lpObjectName
,
1994 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
1995 if (dwError
!= ERROR_SUCCESS
)
1999 if (lpPassword
!= NULL
)
2001 /* FIXME: Write password */
2004 dwError
= ScmCreateServiceHandle(lpService
,
2006 if (dwError
!= ERROR_SUCCESS
)
2009 dwError
= ScmCheckAccess(hServiceHandle
,
2011 if (dwError
!= ERROR_SUCCESS
)
2014 lpService
->dwRefCount
= 1;
2015 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2018 if (hServiceKey
!= NULL
)
2019 RegCloseKey(hServiceKey
);
2021 if (dwError
== ERROR_SUCCESS
)
2023 DPRINT("hService %p\n", hServiceHandle
);
2024 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2026 if (lpdwTagId
!= NULL
)
2027 *lpdwTagId
= lpService
->dwTag
;
2031 /* Release the display name buffer */
2032 if (lpService
->lpServiceName
!= NULL
)
2033 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2037 /* Remove the service handle */
2038 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2041 if (lpService
!= NULL
)
2043 /* FIXME: remove the service entry */
2047 if (lpImagePath
!= NULL
)
2048 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2050 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2057 DWORD
REnumDependentServicesW(
2058 SC_RPC_HANDLE hService
,
2059 DWORD dwServiceState
,
2062 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2063 LPBOUNDED_DWORD_256K lpServicesReturned
)
2065 DWORD dwError
= ERROR_SUCCESS
;
2066 DWORD dwServicesReturned
= 0;
2067 DWORD dwServiceCount
;
2068 HKEY hServicesKey
= NULL
;
2069 LPSC_RPC_HANDLE hSCObject
;
2070 PSERVICE_HANDLE hSvc
;
2071 PSERVICE lpService
= NULL
;
2072 PSERVICE
*lpServicesArray
= NULL
;
2073 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2076 *pcbBytesNeeded
= 0;
2077 *lpServicesReturned
= 0;
2079 DPRINT("REnumDependentServicesW() called\n");
2081 hSCObject
= &hService
;
2082 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
2083 lpService
= hSvc
->ServiceEntry
;
2085 /* Check access rights */
2086 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2087 SC_MANAGER_ENUMERATE_SERVICE
))
2089 DPRINT1("Insufficient access rights! 0x%lx\n",
2090 hSvc
->Handle
.DesiredAccess
);
2091 return ERROR_ACCESS_DENIED
;
2094 /* Open the Services Reg key */
2095 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2096 L
"System\\CurrentControlSet\\Services",
2100 if (dwError
!= ERROR_SUCCESS
)
2103 /* First determine the bytes needed and get the number of dependent services */
2104 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2109 &dwServicesReturned
);
2110 if (dwError
!= ERROR_SUCCESS
)
2113 /* If buffer size is less than the bytes needed or pointer is null */
2114 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2116 dwError
= ERROR_MORE_DATA
;
2120 /* Allocate memory for array of service pointers */
2121 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2123 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2124 if (!lpServicesArray
)
2126 DPRINT1("Could not allocate a buffer!!\n");
2127 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2131 dwServicesReturned
= 0;
2132 *pcbBytesNeeded
= 0;
2134 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2139 &dwServicesReturned
);
2140 if (dwError
!= ERROR_SUCCESS
)
2145 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2146 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2148 /* Copy EnumDepenedentService to Buffer */
2149 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2151 lpService
= lpServicesArray
[dwServiceCount
];
2153 /* Copy status info */
2154 memcpy(&lpServicesPtr
->ServiceStatus
,
2156 sizeof(SERVICE_STATUS
));
2158 /* Copy display name */
2159 wcscpy(lpStr
, lpService
->lpDisplayName
);
2160 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2161 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2163 /* Copy service name */
2164 wcscpy(lpStr
, lpService
->lpServiceName
);
2165 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2166 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2171 *lpServicesReturned
= dwServicesReturned
;
2174 if (lpServicesArray
!= NULL
)
2175 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2177 RegCloseKey(hServicesKey
);
2179 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2186 DWORD
REnumServicesStatusW(
2187 SC_RPC_HANDLE hSCManager
,
2188 DWORD dwServiceType
,
2189 DWORD dwServiceState
,
2192 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2193 LPBOUNDED_DWORD_256K lpServicesReturned
,
2194 LPBOUNDED_DWORD_256K lpResumeHandle
)
2196 PMANAGER_HANDLE hManager
;
2198 DWORD dwError
= ERROR_SUCCESS
;
2199 PLIST_ENTRY ServiceEntry
;
2200 PSERVICE CurrentService
;
2202 DWORD dwRequiredSize
;
2203 DWORD dwServiceCount
;
2205 DWORD dwLastResumeCount
= 0;
2206 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2209 DPRINT("REnumServicesStatusW() called\n");
2212 return ERROR_SHUTDOWN_IN_PROGRESS
;
2214 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2215 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2217 DPRINT1("Invalid manager handle!\n");
2218 return ERROR_INVALID_HANDLE
;
2221 *pcbBytesNeeded
= 0;
2222 *lpServicesReturned
= 0;
2224 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2226 DPRINT("Not a valid Service Type!\n");
2227 return ERROR_INVALID_PARAMETER
;
2230 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2232 DPRINT("Not a valid Service State!\n");
2233 return ERROR_INVALID_PARAMETER
;
2236 /* Check access rights */
2237 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2238 SC_MANAGER_ENUMERATE_SERVICE
))
2240 DPRINT1("Insufficient access rights! 0x%lx\n",
2241 hManager
->Handle
.DesiredAccess
);
2242 return ERROR_ACCESS_DENIED
;
2246 dwLastResumeCount
= *lpResumeHandle
;
2248 /* FIXME: Lock the service list shared */
2250 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2251 if (lpService
== NULL
)
2253 dwError
= ERROR_SUCCESS
;
2260 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2261 ServiceEntry
!= &ServiceListHead
;
2262 ServiceEntry
= ServiceEntry
->Flink
)
2264 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2268 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2271 dwState
= SERVICE_ACTIVE
;
2272 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2273 dwState
= SERVICE_INACTIVE
;
2275 if ((dwState
& dwServiceState
) == 0)
2278 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2279 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2280 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2282 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2284 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2288 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2289 dwRequiredSize
+= dwSize
;
2291 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2294 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2295 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2298 ServiceEntry
!= &ServiceListHead
;
2299 ServiceEntry
= ServiceEntry
->Flink
)
2301 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2305 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2308 dwState
= SERVICE_ACTIVE
;
2309 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2310 dwState
= SERVICE_INACTIVE
;
2312 if ((dwState
& dwServiceState
) == 0)
2315 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2316 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2317 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2319 dwError
= ERROR_MORE_DATA
;
2322 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2325 *lpResumeHandle
= dwLastResumeCount
;
2327 *lpServicesReturned
= dwServiceCount
;
2328 *pcbBytesNeeded
= dwRequiredSize
;
2330 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2331 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2332 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2335 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2336 ServiceEntry
!= &ServiceListHead
;
2337 ServiceEntry
= ServiceEntry
->Flink
)
2339 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2343 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2346 dwState
= SERVICE_ACTIVE
;
2347 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2348 dwState
= SERVICE_INACTIVE
;
2350 if ((dwState
& dwServiceState
) == 0)
2353 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2354 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2355 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2357 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2360 /* Copy the service name */
2361 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2362 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2363 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2365 /* Copy the display name */
2366 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2367 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2368 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2370 /* Copy the status information */
2371 memcpy(&lpStatusPtr
->ServiceStatus
,
2372 &CurrentService
->Status
,
2373 sizeof(SERVICE_STATUS
));
2376 dwRequiredSize
+= dwSize
;
2381 *pcbBytesNeeded
= 0;
2382 if (lpResumeHandle
) *lpResumeHandle
= 0;
2386 /* FIXME: Unlock the service list */
2388 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2395 DWORD
ROpenSCManagerW(
2396 LPWSTR lpMachineName
,
2397 LPWSTR lpDatabaseName
,
2398 DWORD dwDesiredAccess
,
2399 LPSC_RPC_HANDLE lpScHandle
)
2404 DPRINT("ROpenSCManagerW() called\n");
2405 DPRINT("lpMachineName = %p\n", lpMachineName
);
2406 DPRINT("lpMachineName: %S\n", lpMachineName
);
2407 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2408 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2409 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2412 return ERROR_SHUTDOWN_IN_PROGRESS
;
2415 return ERROR_INVALID_PARAMETER
;
2417 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2419 if (dwError
!= ERROR_SUCCESS
)
2421 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2425 /* Check the desired access */
2426 dwError
= ScmCheckAccess(hHandle
,
2427 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2428 if (dwError
!= ERROR_SUCCESS
)
2430 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2431 HeapFree(GetProcessHeap(), 0, hHandle
);
2435 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2436 DPRINT("*hScm = %p\n", *lpScHandle
);
2438 DPRINT("ROpenSCManagerW() done\n");
2440 return ERROR_SUCCESS
;
2445 DWORD
ROpenServiceW(
2446 SC_RPC_HANDLE hSCManager
,
2447 LPWSTR lpServiceName
,
2448 DWORD dwDesiredAccess
,
2449 LPSC_RPC_HANDLE lpServiceHandle
)
2452 PMANAGER_HANDLE hManager
;
2456 DPRINT("ROpenServiceW() called\n");
2457 DPRINT("hSCManager = %p\n", hSCManager
);
2458 DPRINT("lpServiceName = %p\n", lpServiceName
);
2459 DPRINT("lpServiceName: %S\n", lpServiceName
);
2460 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2463 return ERROR_SHUTDOWN_IN_PROGRESS
;
2465 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2466 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2468 DPRINT1("Invalid manager handle!\n");
2469 return ERROR_INVALID_HANDLE
;
2472 if (!lpServiceHandle
)
2473 return ERROR_INVALID_PARAMETER
;
2476 return ERROR_INVALID_ADDRESS
;
2478 /* FIXME: Lock the service list */
2480 /* Get service database entry */
2481 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2482 if (lpService
== NULL
)
2484 DPRINT("Could not find a service!\n");
2485 return ERROR_SERVICE_DOES_NOT_EXIST
;
2488 /* Create a service handle */
2489 dwError
= ScmCreateServiceHandle(lpService
,
2491 if (dwError
!= ERROR_SUCCESS
)
2493 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2497 /* Check the desired access */
2498 dwError
= ScmCheckAccess(hHandle
,
2500 if (dwError
!= ERROR_SUCCESS
)
2502 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2503 HeapFree(GetProcessHeap(), 0, hHandle
);
2507 lpService
->dwRefCount
++;
2508 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2510 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2511 DPRINT("*hService = %p\n", *lpServiceHandle
);
2513 DPRINT("ROpenServiceW() done\n");
2515 return ERROR_SUCCESS
;
2520 DWORD
RQueryServiceConfigW(
2521 SC_RPC_HANDLE hService
,
2522 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2524 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2526 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2527 DWORD dwError
= ERROR_SUCCESS
;
2528 PSERVICE_HANDLE hSvc
;
2529 PSERVICE lpService
= NULL
;
2530 HKEY hServiceKey
= NULL
;
2531 LPWSTR lpImagePath
= NULL
;
2532 LPWSTR lpServiceStartName
= NULL
;
2533 LPWSTR lpDependencies
= NULL
;
2534 DWORD dwDependenciesLength
= 0;
2535 DWORD dwRequiredSize
;
2536 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2537 WCHAR lpEmptyString
[] = {0,0};
2540 DPRINT("RQueryServiceConfigW() called\n");
2543 return ERROR_SHUTDOWN_IN_PROGRESS
;
2545 hSvc
= (PSERVICE_HANDLE
)hService
;
2546 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2548 DPRINT1("Invalid handle tag!\n");
2549 return ERROR_INVALID_HANDLE
;
2552 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2553 SERVICE_QUERY_CONFIG
))
2555 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2556 return ERROR_ACCESS_DENIED
;
2559 lpService
= hSvc
->ServiceEntry
;
2560 if (lpService
== NULL
)
2562 DPRINT1("lpService == NULL!\n");
2563 return ERROR_INVALID_HANDLE
;
2566 /* FIXME: Lock the service database shared */
2568 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2571 if (dwError
!= ERROR_SUCCESS
)
2574 /* Read the image path */
2575 dwError
= ScmReadString(hServiceKey
,
2578 if (dwError
!= ERROR_SUCCESS
)
2581 /* Read the service start name */
2582 ScmReadString(hServiceKey
,
2584 &lpServiceStartName
);
2586 /* Read the dependencies */
2587 ScmReadDependencies(hServiceKey
,
2589 &dwDependenciesLength
);
2591 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2593 if (lpImagePath
!= NULL
)
2594 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2596 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2598 if (lpService
->lpGroup
!= NULL
)
2599 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2601 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2603 if (lpDependencies
!= NULL
)
2604 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2606 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2608 if (lpServiceStartName
!= NULL
)
2609 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2611 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2613 if (lpService
->lpDisplayName
!= NULL
)
2614 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2616 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2618 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2620 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2624 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2625 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2626 lpConfig
->dwStartType
= lpService
->dwStartType
;
2627 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2628 lpConfig
->dwTagId
= lpService
->dwTag
;
2630 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2632 /* Append the image path */
2633 if (lpImagePath
!= NULL
)
2635 wcscpy(lpStr
, lpImagePath
);
2639 wcscpy(lpStr
, lpEmptyString
);
2642 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2643 lpStr
+= (wcslen(lpStr
) + 1);
2645 /* Append the group name */
2646 if (lpService
->lpGroup
!= NULL
)
2648 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2652 wcscpy(lpStr
, lpEmptyString
);
2655 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2656 lpStr
+= (wcslen(lpStr
) + 1);
2658 /* Append Dependencies */
2659 if (lpDependencies
!= NULL
)
2663 dwDependenciesLength
* sizeof(WCHAR
));
2667 wcscpy(lpStr
, lpEmptyString
);
2670 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2671 if (lpDependencies
!= NULL
)
2672 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2674 lpStr
+= (wcslen(lpStr
) + 1);
2676 /* Append the service start name */
2677 if (lpServiceStartName
!= NULL
)
2679 wcscpy(lpStr
, lpServiceStartName
);
2683 wcscpy(lpStr
, lpEmptyString
);
2686 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2687 lpStr
+= (wcslen(lpStr
) + 1);
2689 /* Append the display name */
2690 if (lpService
->lpDisplayName
!= NULL
)
2692 wcscpy(lpStr
, lpService
->lpDisplayName
);
2696 wcscpy(lpStr
, lpEmptyString
);
2699 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2702 if (pcbBytesNeeded
!= NULL
)
2703 *pcbBytesNeeded
= dwRequiredSize
;
2706 if (lpImagePath
!= NULL
)
2707 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2709 if (lpServiceStartName
!= NULL
)
2710 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2712 if (lpDependencies
!= NULL
)
2713 HeapFree(GetProcessHeap(), 0, lpDependencies
);
2715 if (hServiceKey
!= NULL
)
2716 RegCloseKey(hServiceKey
);
2718 /* FIXME: Unlock the service database */
2720 DPRINT("RQueryServiceConfigW() done\n");
2727 DWORD
RQueryServiceLockStatusW(
2728 SC_RPC_HANDLE hSCManager
,
2729 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2731 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2734 return ERROR_CALL_NOT_IMPLEMENTED
;
2739 DWORD
RStartServiceW(
2740 SC_RPC_HANDLE hService
,
2742 LPSTRING_PTRSW argv
)
2744 DWORD dwError
= ERROR_SUCCESS
;
2745 PSERVICE_HANDLE hSvc
;
2746 PSERVICE lpService
= NULL
;
2748 DPRINT("RStartServiceW() called\n");
2751 return ERROR_SHUTDOWN_IN_PROGRESS
;
2753 hSvc
= (PSERVICE_HANDLE
)hService
;
2754 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2756 DPRINT1("Invalid handle tag!\n");
2757 return ERROR_INVALID_HANDLE
;
2760 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2763 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2764 return ERROR_ACCESS_DENIED
;
2767 lpService
= hSvc
->ServiceEntry
;
2768 if (lpService
== NULL
)
2770 DPRINT1("lpService == NULL!\n");
2771 return ERROR_INVALID_HANDLE
;
2774 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2775 return ERROR_SERVICE_DISABLED
;
2777 if (lpService
->bDeleted
)
2778 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2785 /* Start the service */
2786 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2793 DWORD
RGetServiceDisplayNameW(
2794 SC_RPC_HANDLE hSCManager
,
2795 LPCWSTR lpServiceName
,
2796 LPWSTR lpDisplayName
,
2799 // PMANAGER_HANDLE hManager;
2804 DPRINT("RGetServiceDisplayNameW() called\n");
2805 DPRINT("hSCManager = %p\n", hSCManager
);
2806 DPRINT("lpServiceName: %S\n", lpServiceName
);
2807 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2808 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2810 // hManager = (PMANAGER_HANDLE)hSCManager;
2811 // if (hManager->Handle.Tag != MANAGER_TAG)
2813 // DPRINT1("Invalid manager handle!\n");
2814 // return ERROR_INVALID_HANDLE;
2817 /* Get service database entry */
2818 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2819 if (lpService
== NULL
)
2821 DPRINT1("Could not find a service!\n");
2823 /* If the service could not be found and lpcchBuffer is less than 2, windows
2824 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2825 if (*lpcchBuffer
< 2)
2828 if (lpDisplayName
!= NULL
)
2830 *lpDisplayName
= '\0';
2834 return ERROR_SERVICE_DOES_NOT_EXIST
;
2837 if (!lpService
->lpDisplayName
)
2839 dwLength
= wcslen(lpService
->lpServiceName
);
2841 if (lpDisplayName
!= NULL
&&
2842 *lpcchBuffer
> dwLength
)
2844 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2849 dwLength
= wcslen(lpService
->lpDisplayName
);
2851 if (lpDisplayName
!= NULL
&&
2852 *lpcchBuffer
> dwLength
)
2854 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2858 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2860 *lpcchBuffer
= dwLength
;
2867 DWORD
RGetServiceKeyNameW(
2868 SC_RPC_HANDLE hSCManager
,
2869 LPCWSTR lpDisplayName
,
2870 LPWSTR lpServiceName
,
2873 // PMANAGER_HANDLE hManager;
2878 DPRINT("RGetServiceKeyNameW() called\n");
2879 DPRINT("hSCManager = %p\n", hSCManager
);
2880 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2881 DPRINT("lpServiceName: %p\n", lpServiceName
);
2882 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2884 // hManager = (PMANAGER_HANDLE)hSCManager;
2885 // if (hManager->Handle.Tag != MANAGER_TAG)
2887 // DPRINT1("Invalid manager handle!\n");
2888 // return ERROR_INVALID_HANDLE;
2891 /* Get service database entry */
2892 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2893 if (lpService
== NULL
)
2895 DPRINT1("Could not find a service!\n");
2897 /* If the service could not be found and lpcchBuffer is less than 2, windows
2898 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2899 if (*lpcchBuffer
< 2)
2902 if (lpServiceName
!= NULL
)
2904 *lpServiceName
= '\0';
2908 return ERROR_SERVICE_DOES_NOT_EXIST
;
2911 dwLength
= wcslen(lpService
->lpServiceName
);
2913 if (lpServiceName
!= NULL
&&
2914 *lpcchBuffer
> dwLength
)
2916 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2917 *lpcchBuffer
= dwLength
;
2918 return ERROR_SUCCESS
;
2921 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2923 *lpcchBuffer
= dwLength
;
2930 DWORD
RI_ScSetServiceBitsA(
2931 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
2932 DWORD dwServiceBits
,
2934 int bUpdateImmediately
,
2938 return ERROR_CALL_NOT_IMPLEMENTED
;
2943 DWORD
RChangeServiceConfigA(
2944 SC_RPC_HANDLE hService
,
2945 DWORD dwServiceType
,
2947 DWORD dwErrorControl
,
2948 LPSTR lpBinaryPathName
,
2949 LPSTR lpLoadOrderGroup
,
2951 LPSTR lpDependencies
,
2953 LPSTR lpServiceStartName
,
2956 LPSTR lpDisplayName
)
2958 DWORD dwError
= ERROR_SUCCESS
;
2959 PSERVICE_HANDLE hSvc
;
2960 PSERVICE lpService
= NULL
;
2961 HKEY hServiceKey
= NULL
;
2962 LPWSTR lpDisplayNameW
= NULL
;
2963 // LPWSTR lpBinaryPathNameW = NULL;
2964 LPWSTR lpLoadOrderGroupW
= NULL
;
2965 LPWSTR lpDependenciesW
= NULL
;
2966 // LPWSTR lpPasswordW = NULL;
2968 DPRINT("RChangeServiceConfigA() called\n");
2969 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2970 DPRINT("dwStartType = %lu\n", dwStartType
);
2971 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2972 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2973 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2974 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2977 return ERROR_SHUTDOWN_IN_PROGRESS
;
2979 hSvc
= (PSERVICE_HANDLE
)hService
;
2980 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2982 DPRINT1("Invalid handle tag!\n");
2983 return ERROR_INVALID_HANDLE
;
2986 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2987 SERVICE_CHANGE_CONFIG
))
2989 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2990 return ERROR_ACCESS_DENIED
;
2993 lpService
= hSvc
->ServiceEntry
;
2994 if (lpService
== NULL
)
2996 DPRINT1("lpService == NULL!\n");
2997 return ERROR_INVALID_HANDLE
;
3000 /* FIXME: Lock database exclusively */
3002 if (lpService
->bDeleted
)
3004 /* FIXME: Unlock database */
3005 DPRINT1("The service has already been marked for delete!\n");
3006 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3009 /* Open the service key */
3010 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3013 if (dwError
!= ERROR_SUCCESS
)
3016 /* Write service data to the registry */
3018 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3020 /* Set the display name */
3021 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3023 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3024 if (lpDisplayNameW
== NULL
)
3026 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3030 MultiByteToWideChar(CP_ACP
,
3035 strlen(lpDisplayName
) + 1);
3037 RegSetValueExW(hServiceKey
,
3041 (LPBYTE
)lpDisplayNameW
,
3042 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3044 /* Update lpService->lpDisplayName */
3045 if (lpService
->lpDisplayName
)
3046 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3048 lpService
->lpDisplayName
= lpDisplayNameW
;
3051 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3053 /* Set the service type */
3054 dwError
= RegSetValueExW(hServiceKey
,
3058 (LPBYTE
)&dwServiceType
,
3060 if (dwError
!= ERROR_SUCCESS
)
3063 lpService
->Status
.dwServiceType
= dwServiceType
;
3066 if (dwStartType
!= SERVICE_NO_CHANGE
)
3068 /* Set the start value */
3069 dwError
= RegSetValueExW(hServiceKey
,
3073 (LPBYTE
)&dwStartType
,
3075 if (dwError
!= ERROR_SUCCESS
)
3078 lpService
->dwStartType
= dwStartType
;
3081 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3083 /* Set the error control value */
3084 dwError
= RegSetValueExW(hServiceKey
,
3088 (LPBYTE
)&dwErrorControl
,
3090 if (dwError
!= ERROR_SUCCESS
)
3093 lpService
->dwErrorControl
= dwErrorControl
;
3097 /* FIXME: set the new ImagePath value */
3099 /* Set the image path */
3100 if (dwServiceType
& SERVICE_WIN32
)
3102 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3104 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3105 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, strlen(lpBinaryPathName
)+1);
3106 dwError
= RegSetValueExW(hServiceKey
,
3110 (LPBYTE
)lpBinaryPathNameW
,
3111 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3112 if (dwError
!= ERROR_SUCCESS
)
3116 else if (dwServiceType
& SERVICE_DRIVER
)
3118 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3120 dwError
= RegSetValueExW(hServiceKey
,
3124 (LPBYTE
)lpImagePath
,
3125 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3126 if (dwError
!= ERROR_SUCCESS
)
3132 /* Set the group name */
3133 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3135 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3137 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3138 if (lpLoadOrderGroupW
== NULL
)
3140 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3144 MultiByteToWideChar(CP_ACP
,
3149 strlen(lpLoadOrderGroup
) + 1);
3151 dwError
= RegSetValueExW(hServiceKey
,
3155 (LPBYTE
)lpLoadOrderGroupW
,
3156 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3157 if (dwError
!= ERROR_SUCCESS
)
3159 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3163 dwError
= ScmSetServiceGroup(lpService
,
3166 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3168 if (dwError
!= ERROR_SUCCESS
)
3172 if (lpdwTagId
!= NULL
)
3174 dwError
= ScmAssignNewTag(lpService
);
3175 if (dwError
!= ERROR_SUCCESS
)
3178 dwError
= RegSetValueExW(hServiceKey
,
3182 (LPBYTE
)&lpService
->dwTag
,
3184 if (dwError
!= ERROR_SUCCESS
)
3187 *lpdwTagId
= lpService
->dwTag
;
3190 /* Write dependencies */
3191 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3193 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3195 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3196 if (lpDependenciesW
== NULL
)
3198 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3202 MultiByteToWideChar(CP_ACP
,
3207 strlen(lpDependencies
) + 1);
3209 dwError
= ScmWriteDependencies(hServiceKey
,
3210 (LPWSTR
)lpDependenciesW
,
3213 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3216 if (lpPassword
!= NULL
)
3218 /* FIXME: Write password */
3221 /* FIXME: Unlock database */
3224 if (hServiceKey
!= NULL
)
3225 RegCloseKey(hServiceKey
);
3227 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3234 DWORD
RCreateServiceA(
3235 SC_RPC_HANDLE hSCManager
,
3236 LPSTR lpServiceName
,
3237 LPSTR lpDisplayName
,
3238 DWORD dwDesiredAccess
,
3239 DWORD dwServiceType
,
3241 DWORD dwErrorControl
,
3242 LPSTR lpBinaryPathName
,
3243 LPSTR lpLoadOrderGroup
,
3245 LPBYTE lpDependencies
,
3247 LPSTR lpServiceStartName
,
3250 LPSC_RPC_HANDLE lpServiceHandle
)
3252 DWORD dwError
= ERROR_SUCCESS
;
3253 LPWSTR lpServiceNameW
= NULL
;
3254 LPWSTR lpDisplayNameW
= NULL
;
3255 LPWSTR lpBinaryPathNameW
= NULL
;
3256 LPWSTR lpLoadOrderGroupW
= NULL
;
3257 LPWSTR lpDependenciesW
= NULL
;
3258 LPWSTR lpServiceStartNameW
= NULL
;
3259 DWORD dwDependenciesLength
= 0;
3266 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3267 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3268 if (!lpServiceNameW
)
3270 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3273 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3278 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3279 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3280 if (!lpDisplayNameW
)
3282 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3285 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3288 if (lpBinaryPathName
)
3290 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3291 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3292 if (!lpBinaryPathNameW
)
3294 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3297 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3300 if (lpLoadOrderGroup
)
3302 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3303 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3304 if (!lpLoadOrderGroupW
)
3306 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3309 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3314 lpStr
= (LPSTR
)lpDependencies
;
3317 dwLength
= strlen(lpStr
) + 1;
3318 dwDependenciesLength
+= dwLength
;
3319 lpStr
= lpStr
+ dwLength
;
3321 dwDependenciesLength
++;
3323 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3324 if (!lpDependenciesW
)
3326 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3329 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3332 if (lpServiceStartName
)
3334 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3335 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3336 if (!lpServiceStartNameW
)
3338 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3341 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3344 dwError
= RCreateServiceW(hSCManager
,
3354 (LPBYTE
)lpDependenciesW
,
3355 dwDependenciesLength
,
3356 lpServiceStartNameW
,
3362 if (lpServiceNameW
!=NULL
)
3363 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3365 if (lpDisplayNameW
!= NULL
)
3366 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3368 if (lpBinaryPathNameW
!= NULL
)
3369 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3371 if (lpLoadOrderGroupW
!= NULL
)
3372 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3374 if (lpDependenciesW
!= NULL
)
3375 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3377 if (lpServiceStartNameW
!= NULL
)
3378 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3385 DWORD
REnumDependentServicesA(
3386 SC_RPC_HANDLE hService
,
3387 DWORD dwServiceState
,
3390 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3391 LPBOUNDED_DWORD_256K lpServicesReturned
)
3393 DWORD dwError
= ERROR_SUCCESS
;
3394 DWORD dwServicesReturned
= 0;
3395 DWORD dwServiceCount
;
3396 HKEY hServicesKey
= NULL
;
3397 LPSC_RPC_HANDLE hSCObject
;
3398 PSERVICE_HANDLE hSvc
;
3399 PSERVICE lpService
= NULL
;
3400 PSERVICE
*lpServicesArray
= NULL
;
3401 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3404 *pcbBytesNeeded
= 0;
3405 *lpServicesReturned
= 0;
3407 DPRINT("REnumDependentServicesA() called\n");
3409 hSCObject
= &hService
;
3410 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3411 lpService
= hSvc
->ServiceEntry
;
3413 /* Check access rights */
3414 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3415 SC_MANAGER_ENUMERATE_SERVICE
))
3417 DPRINT1("Insufficient access rights! 0x%lx\n",
3418 hSvc
->Handle
.DesiredAccess
);
3419 return ERROR_ACCESS_DENIED
;
3422 /* Open the Services Reg key */
3423 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3424 L
"System\\CurrentControlSet\\Services",
3429 if (dwError
!= ERROR_SUCCESS
)
3432 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3433 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3434 are the same for both. Verified in WINXP. */
3436 /* First determine the bytes needed and get the number of dependent services*/
3437 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3442 &dwServicesReturned
);
3443 if (dwError
!= ERROR_SUCCESS
)
3446 /* If buffer size is less than the bytes needed or pointer is null*/
3447 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3449 dwError
= ERROR_MORE_DATA
;
3453 /* Allocate memory for array of service pointers */
3454 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3456 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3457 if (!lpServicesArray
)
3459 DPRINT1("Could not allocate a buffer!!\n");
3460 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3464 dwServicesReturned
= 0;
3465 *pcbBytesNeeded
= 0;
3467 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3472 &dwServicesReturned
);
3473 if (dwError
!= ERROR_SUCCESS
)
3478 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3479 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3481 /* Copy EnumDepenedentService to Buffer */
3482 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3484 lpService
= lpServicesArray
[dwServiceCount
];
3486 /* Copy the status info */
3487 memcpy(&lpServicesPtr
->ServiceStatus
,
3489 sizeof(SERVICE_STATUS
));
3491 /* Copy display name */
3492 WideCharToMultiByte(CP_ACP
,
3494 lpService
->lpDisplayName
,
3497 wcslen(lpService
->lpDisplayName
),
3500 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3501 lpStr
+= strlen(lpStr
) + 1;
3503 /* Copy service name */
3504 WideCharToMultiByte(CP_ACP
,
3506 lpService
->lpServiceName
,
3509 wcslen(lpService
->lpServiceName
),
3512 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3513 lpStr
+= strlen(lpStr
) + 1;
3518 *lpServicesReturned
= dwServicesReturned
;
3521 if (lpServicesArray
)
3522 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3524 RegCloseKey(hServicesKey
);
3526 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3533 DWORD
REnumServicesStatusA(
3534 SC_RPC_HANDLE hSCManager
,
3535 DWORD dwServiceType
,
3536 DWORD dwServiceState
,
3539 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3540 LPBOUNDED_DWORD_256K lpServicesReturned
,
3541 LPBOUNDED_DWORD_256K lpResumeHandle
)
3543 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3544 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3545 LPWSTR lpStringPtrW
;
3548 DWORD dwServiceCount
;
3550 DPRINT("REnumServicesStatusA() called\n");
3552 if ((dwBufSize
> 0) && (lpBuffer
))
3554 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3557 DPRINT1("Failed to allocate buffer!\n");
3558 return ERROR_NOT_ENOUGH_MEMORY
;
3562 dwError
= REnumServicesStatusW(hSCManager
,
3565 (LPBYTE
)lpStatusPtrW
,
3571 /* if no services were returned then we are Done */
3572 if (*lpServicesReturned
== 0)
3575 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3576 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3577 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3578 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3579 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3581 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3583 /* Copy the service name */
3584 WideCharToMultiByte(CP_ACP
,
3589 wcslen(lpStringPtrW
),
3593 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3594 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3595 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3597 /* Copy the display name */
3598 WideCharToMultiByte(CP_ACP
,
3603 wcslen(lpStringPtrW
),
3607 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3608 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3609 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3611 /* Copy the status information */
3612 memcpy(&lpStatusPtrA
->ServiceStatus
,
3613 &lpStatusPtrW
->ServiceStatus
,
3614 sizeof(SERVICE_STATUS
));
3621 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3623 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3630 DWORD
ROpenSCManagerA(
3631 LPSTR lpMachineName
,
3632 LPSTR lpDatabaseName
,
3633 DWORD dwDesiredAccess
,
3634 LPSC_RPC_HANDLE lpScHandle
)
3636 UNICODE_STRING MachineName
;
3637 UNICODE_STRING DatabaseName
;
3640 DPRINT("ROpenSCManagerA() called\n");
3643 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3647 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3650 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3651 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3656 RtlFreeUnicodeString(&MachineName
);
3659 RtlFreeUnicodeString(&DatabaseName
);
3666 DWORD
ROpenServiceA(
3667 SC_RPC_HANDLE hSCManager
,
3668 LPSTR lpServiceName
,
3669 DWORD dwDesiredAccess
,
3670 LPSC_RPC_HANDLE lpServiceHandle
)
3672 UNICODE_STRING ServiceName
;
3675 DPRINT("ROpenServiceA() called\n");
3678 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3681 dwError
= ROpenServiceW(hSCManager
,
3682 lpServiceName
? ServiceName
.Buffer
: NULL
,
3687 RtlFreeUnicodeString(&ServiceName
);
3694 DWORD
RQueryServiceConfigA(
3695 SC_RPC_HANDLE hService
,
3696 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3698 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3700 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3701 DWORD dwError
= ERROR_SUCCESS
;
3702 PSERVICE_HANDLE hSvc
;
3703 PSERVICE lpService
= NULL
;
3704 HKEY hServiceKey
= NULL
;
3705 LPWSTR lpImagePath
= NULL
;
3706 LPWSTR lpServiceStartName
= NULL
;
3707 LPWSTR lpDependencies
= NULL
;
3708 DWORD dwDependenciesLength
= 0;
3709 DWORD dwRequiredSize
;
3710 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3711 CHAR lpEmptyString
[]={0,0};
3714 DPRINT("RQueryServiceConfigA() called\n");
3717 return ERROR_SHUTDOWN_IN_PROGRESS
;
3719 hSvc
= (PSERVICE_HANDLE
)hService
;
3720 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3722 DPRINT1("Invalid handle tag!\n");
3723 return ERROR_INVALID_HANDLE
;
3726 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3727 SERVICE_QUERY_CONFIG
))
3729 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3730 return ERROR_ACCESS_DENIED
;
3733 lpService
= hSvc
->ServiceEntry
;
3734 if (lpService
== NULL
)
3736 DPRINT1("lpService == NULL!\n");
3737 return ERROR_INVALID_HANDLE
;
3740 /* FIXME: Lock the service database shared */
3742 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3745 if (dwError
!= ERROR_SUCCESS
)
3748 /* Read the image path */
3749 dwError
= ScmReadString(hServiceKey
,
3752 if (dwError
!= ERROR_SUCCESS
)
3755 /* Read the service start name */
3756 ScmReadString(hServiceKey
,
3758 &lpServiceStartName
);
3760 /* Read the dependencies */
3761 ScmReadDependencies(hServiceKey
,
3763 &dwDependenciesLength
);
3765 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3767 if (lpImagePath
!= NULL
)
3768 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3770 dwRequiredSize
+= 2;
3772 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3773 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3775 dwRequiredSize
+= 2;
3777 /* Add Dependencies length */
3778 if (lpDependencies
!= NULL
)
3779 dwRequiredSize
+= dwDependenciesLength
;
3781 dwRequiredSize
+= 2;
3783 if (lpServiceStartName
!= NULL
)
3784 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3786 dwRequiredSize
+= 2;
3788 if (lpService
->lpDisplayName
!= NULL
)
3789 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3791 dwRequiredSize
+= 2;
3793 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3795 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3799 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3800 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3801 lpConfig
->dwStartType
= lpService
->dwStartType
;
3802 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3803 lpConfig
->dwTagId
= lpService
->dwTag
;
3805 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3807 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3812 WideCharToMultiByte(CP_ACP
,
3817 wcslen(lpImagePath
) + 1,
3823 strcpy(lpStr
, lpEmptyString
);
3826 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3827 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3829 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
3831 WideCharToMultiByte(CP_ACP
,
3833 lpService
->lpGroup
->lpGroupName
,
3836 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
3842 strcpy(lpStr
, lpEmptyString
);
3845 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3846 lpStr
+= (strlen(lpStr
) + 1);
3848 /* Append Dependencies */
3851 WideCharToMultiByte(CP_ACP
,
3854 dwDependenciesLength
,
3856 dwDependenciesLength
,
3862 strcpy(lpStr
, lpEmptyString
);
3865 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3867 lpStr
+= dwDependenciesLength
;
3869 lpStr
+= (strlen(lpStr
) + 1);
3871 if (lpServiceStartName
)
3873 WideCharToMultiByte(CP_ACP
,
3878 wcslen(lpServiceStartName
) + 1,
3884 strcpy(lpStr
, lpEmptyString
);
3887 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3888 lpStr
+= (strlen(lpStr
) + 1);
3890 if (lpService
->lpDisplayName
)
3892 WideCharToMultiByte(CP_ACP
,
3894 lpService
->lpDisplayName
,
3897 wcslen(lpService
->lpDisplayName
) + 1,
3903 strcpy(lpStr
, lpEmptyString
);
3906 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3909 if (pcbBytesNeeded
!= NULL
)
3910 *pcbBytesNeeded
= dwRequiredSize
;
3913 if (lpImagePath
!= NULL
)
3914 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3916 if (lpServiceStartName
!= NULL
)
3917 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3919 if (lpDependencies
!= NULL
)
3920 HeapFree(GetProcessHeap(), 0, lpDependencies
);
3922 if (hServiceKey
!= NULL
)
3923 RegCloseKey(hServiceKey
);
3925 /* FIXME: Unlock the service database */
3927 DPRINT("RQueryServiceConfigA() done\n");
3934 DWORD
RQueryServiceLockStatusA(
3935 SC_RPC_HANDLE hSCManager
,
3936 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
3938 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3941 return ERROR_CALL_NOT_IMPLEMENTED
;
3946 DWORD
RStartServiceA(
3947 SC_RPC_HANDLE hService
,
3949 LPSTRING_PTRSA argv
)
3951 DWORD dwError
= ERROR_SUCCESS
;
3952 PSERVICE_HANDLE hSvc
;
3953 PSERVICE lpService
= NULL
;
3955 DPRINT1("RStartServiceA() called\n");
3958 return ERROR_SHUTDOWN_IN_PROGRESS
;
3960 hSvc
= (PSERVICE_HANDLE
)hService
;
3961 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3963 DPRINT1("Invalid handle tag!\n");
3964 return ERROR_INVALID_HANDLE
;
3967 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3970 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3971 return ERROR_ACCESS_DENIED
;
3974 lpService
= hSvc
->ServiceEntry
;
3975 if (lpService
== NULL
)
3977 DPRINT1("lpService == NULL!\n");
3978 return ERROR_INVALID_HANDLE
;
3981 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3982 return ERROR_SERVICE_DISABLED
;
3984 if (lpService
->bDeleted
)
3985 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3987 /* FIXME: Convert argument vector to Unicode */
3989 /* Start the service */
3990 dwError
= ScmStartService(lpService
, 0, NULL
);
3992 /* FIXME: Free argument vector */
3999 DWORD
RGetServiceDisplayNameA(
4000 SC_RPC_HANDLE hSCManager
,
4001 LPCSTR lpServiceName
,
4002 LPSTR lpDisplayName
,
4003 LPBOUNDED_DWORD_4K lpcchBuffer
)
4005 // PMANAGER_HANDLE hManager;
4006 PSERVICE lpService
= NULL
;
4009 LPWSTR lpServiceNameW
;
4011 DPRINT("RGetServiceDisplayNameA() called\n");
4012 DPRINT("hSCManager = %p\n", hSCManager
);
4013 DPRINT("lpServiceName: %s\n", lpServiceName
);
4014 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4015 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4017 // hManager = (PMANAGER_HANDLE)hSCManager;
4018 // if (hManager->Handle.Tag != MANAGER_TAG)
4020 // DPRINT1("Invalid manager handle!\n");
4021 // return ERROR_INVALID_HANDLE;
4024 if (lpServiceName
!= NULL
)
4026 dwLength
= strlen(lpServiceName
) + 1;
4027 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4029 dwLength
* sizeof(WCHAR
));
4030 if (!lpServiceNameW
)
4031 return ERROR_NOT_ENOUGH_MEMORY
;
4033 MultiByteToWideChar(CP_ACP
,
4040 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4042 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4045 if (lpService
== NULL
)
4047 DPRINT1("Could not find a service!\n");
4049 /* If the service could not be found and lpcchBuffer is 0, windows
4050 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4051 if (*lpcchBuffer
== 0)
4054 if (lpDisplayName
!= NULL
)
4056 *lpDisplayName
= '\0';
4059 return ERROR_SERVICE_DOES_NOT_EXIST
;
4062 if (!lpService
->lpDisplayName
)
4064 dwLength
= wcslen(lpService
->lpServiceName
);
4065 if (lpDisplayName
!= NULL
&&
4066 *lpcchBuffer
> dwLength
)
4068 WideCharToMultiByte(CP_ACP
,
4070 lpService
->lpServiceName
,
4071 wcslen(lpService
->lpServiceName
),
4076 return ERROR_SUCCESS
;
4081 dwLength
= wcslen(lpService
->lpDisplayName
);
4082 if (lpDisplayName
!= NULL
&&
4083 *lpcchBuffer
> dwLength
)
4085 WideCharToMultiByte(CP_ACP
,
4087 lpService
->lpDisplayName
,
4088 wcslen(lpService
->lpDisplayName
),
4093 return ERROR_SUCCESS
;
4097 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4099 *lpcchBuffer
= dwLength
* 2;
4106 DWORD
RGetServiceKeyNameA(
4107 SC_RPC_HANDLE hSCManager
,
4108 LPCSTR lpDisplayName
,
4109 LPSTR lpServiceName
,
4110 LPBOUNDED_DWORD_4K lpcchBuffer
)
4115 LPWSTR lpDisplayNameW
;
4117 DPRINT("RGetServiceKeyNameA() called\n");
4118 DPRINT("hSCManager = %p\n", hSCManager
);
4119 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4120 DPRINT("lpServiceName: %p\n", lpServiceName
);
4121 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4123 dwLength
= strlen(lpDisplayName
) + 1;
4124 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4126 dwLength
* sizeof(WCHAR
));
4127 if (!lpDisplayNameW
)
4128 return ERROR_NOT_ENOUGH_MEMORY
;
4130 MultiByteToWideChar(CP_ACP
,
4137 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4139 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4141 if (lpService
== NULL
)
4143 DPRINT1("Could not find the service!\n");
4145 /* If the service could not be found and lpcchBuffer is 0,
4146 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4147 if (*lpcchBuffer
== 0)
4150 if (lpServiceName
!= NULL
)
4152 *lpServiceName
= '\0';
4156 return ERROR_SERVICE_DOES_NOT_EXIST
;
4159 dwLength
= wcslen(lpService
->lpServiceName
);
4160 if (lpServiceName
!= NULL
&&
4161 *lpcchBuffer
> dwLength
)
4163 WideCharToMultiByte(CP_ACP
,
4165 lpService
->lpServiceName
,
4166 wcslen(lpService
->lpServiceName
),
4171 return ERROR_SUCCESS
;
4174 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4176 *lpcchBuffer
= dwLength
* 2;
4183 DWORD
RI_ScGetCurrentGroupStateW(
4184 SC_RPC_HANDLE hSCManager
,
4185 LPWSTR lpLoadOrderGroup
,
4189 return ERROR_CALL_NOT_IMPLEMENTED
;
4194 DWORD
REnumServiceGroupW(
4195 SC_RPC_HANDLE hSCManager
,
4196 DWORD dwServiceType
,
4197 DWORD dwServiceState
,
4200 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4201 LPBOUNDED_DWORD_256K lpServicesReturned
,
4202 LPBOUNDED_DWORD_256K lpResumeIndex
,
4203 LPCWSTR pszGroupName
)
4206 return ERROR_CALL_NOT_IMPLEMENTED
;
4211 // WARNING: This function is untested
4214 DWORD
RChangeServiceConfig2A(
4215 SC_RPC_HANDLE hService
,
4216 SC_RPC_CONFIG_INFOA Info
)
4218 SC_RPC_CONFIG_INFOW InfoW
;
4219 DWORD dwRet
, dwLength
;
4222 DPRINT("RChangeServiceConfig2A() called\n");
4223 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4225 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4227 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4229 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4230 LPSERVICE_DESCRIPTIONA lpServiceDescriptonA
;
4232 lpServiceDescriptonA
= Info
.psd
;
4234 ///if (lpServiceDescriptonA &&
4235 ///lpServiceDescriptonA->lpDescription)
4237 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4239 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4241 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4242 if (!lpServiceDescriptonW
)
4244 return ERROR_NOT_ENOUGH_MEMORY
;
4247 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4249 MultiByteToWideChar(CP_ACP
,
4253 lpServiceDescriptonW
->lpDescription
,
4256 ptr
= lpServiceDescriptonW
;
4257 InfoW
.psd
= lpServiceDescriptonW
;
4260 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4262 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4263 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4264 DWORD dwRebootLen
= 0;
4265 DWORD dwCommandLen
= 0;
4267 lpServiceFailureActionsA
= Info
.psfa
;
4269 if (lpServiceFailureActionsA
)
4271 if (lpServiceFailureActionsA
->lpRebootMsg
)
4273 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4275 if (lpServiceFailureActionsA
->lpCommand
)
4277 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4279 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4281 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4284 if (!lpServiceFailureActionsW
)
4286 return ERROR_NOT_ENOUGH_MEMORY
;
4289 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4290 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4291 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4293 if (lpServiceFailureActionsA
->lpRebootMsg
)
4295 MultiByteToWideChar(CP_ACP
,
4297 lpServiceFailureActionsA
->lpRebootMsg
,
4299 lpServiceFailureActionsW
->lpRebootMsg
,
4303 if (lpServiceFailureActionsA
->lpCommand
)
4305 MultiByteToWideChar(CP_ACP
,
4307 lpServiceFailureActionsA
->lpCommand
,
4309 lpServiceFailureActionsW
->lpCommand
,
4313 ptr
= lpServiceFailureActionsW
;
4317 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4319 HeapFree(GetProcessHeap(), 0, ptr
);
4326 DWORD
RChangeServiceConfig2W(
4327 SC_RPC_HANDLE hService
,
4328 SC_RPC_CONFIG_INFOW Info
)
4330 DWORD dwError
= ERROR_SUCCESS
;
4331 PSERVICE_HANDLE hSvc
;
4332 PSERVICE lpService
= NULL
;
4333 HKEY hServiceKey
= NULL
;
4335 DPRINT("RChangeServiceConfig2W() called\n");
4336 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4339 return ERROR_SHUTDOWN_IN_PROGRESS
;
4341 hSvc
= (PSERVICE_HANDLE
)hService
;
4342 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4344 DPRINT1("Invalid handle tag!\n");
4345 return ERROR_INVALID_HANDLE
;
4348 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4349 SERVICE_CHANGE_CONFIG
))
4351 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4352 return ERROR_ACCESS_DENIED
;
4355 lpService
= hSvc
->ServiceEntry
;
4356 if (lpService
== NULL
)
4358 DPRINT1("lpService == NULL!\n");
4359 return ERROR_INVALID_HANDLE
;
4362 /* FIXME: Lock database exclusively */
4364 if (lpService
->bDeleted
)
4366 /* FIXME: Unlock database */
4367 DPRINT1("The service has already been marked for delete!\n");
4368 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4371 /* Open the service key */
4372 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4375 if (dwError
!= ERROR_SUCCESS
)
4378 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4380 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4382 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4383 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4385 if (lpServiceDescription
!= NULL
&&
4386 lpServiceDescription
->lpDescription
!= NULL
)
4388 DPRINT1("Setting value %S\n", lpServiceDescription
->lpDescription
);
4389 RegSetValueExW(hServiceKey
,
4393 (LPBYTE
)lpServiceDescription
->lpDescription
,
4394 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4396 if (dwError
!= ERROR_SUCCESS
)
4400 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4403 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4408 /* FIXME: Unlock database */
4409 if (hServiceKey
!= NULL
)
4410 RegCloseKey(hServiceKey
);
4412 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4419 DWORD
RQueryServiceConfig2A(
4420 SC_RPC_HANDLE hService
,
4424 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4426 DWORD dwError
= ERROR_SUCCESS
;
4427 PSERVICE_HANDLE hSvc
;
4428 PSERVICE lpService
= NULL
;
4429 HKEY hServiceKey
= NULL
;
4430 LPWSTR lpDescriptionW
= NULL
;
4431 LPSTR lpDescription
= NULL
;
4433 DPRINT1("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4434 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4437 return ERROR_INVALID_ADDRESS
;
4440 return ERROR_SHUTDOWN_IN_PROGRESS
;
4442 hSvc
= (PSERVICE_HANDLE
)hService
;
4443 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4445 DPRINT1("Invalid handle tag!\n");
4446 return ERROR_INVALID_HANDLE
;
4449 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4450 SERVICE_QUERY_CONFIG
))
4452 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4453 return ERROR_ACCESS_DENIED
;
4456 lpService
= hSvc
->ServiceEntry
;
4457 if (lpService
== NULL
)
4459 DPRINT1("lpService == NULL!\n");
4460 return ERROR_INVALID_HANDLE
;
4463 /* FIXME: Lock the service database shared */
4465 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4468 if (dwError
!= ERROR_SUCCESS
)
4471 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4473 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4476 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4478 dwError
= ScmReadString(hServiceKey
,
4481 if (dwError
== ERROR_SUCCESS
)
4483 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4486 if (cbBufSize
>= *pcbBytesNeeded
)
4489 if (dwError
== ERROR_SUCCESS
)
4491 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4493 WideCharToMultiByte(CP_ACP
,
4498 wcslen(lpDescriptionW
),
4501 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4505 lpServiceDescription
->lpDescription
= NULL
;
4511 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4515 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4518 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4523 if (lpDescription
!= NULL
)
4524 HeapFree(GetProcessHeap(), 0, lpDescription
);
4526 if (hServiceKey
!= NULL
)
4527 RegCloseKey(hServiceKey
);
4529 /* FIXME: Unlock database */
4531 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4538 DWORD
RQueryServiceConfig2W(
4539 SC_RPC_HANDLE hService
,
4543 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4545 DWORD dwError
= ERROR_SUCCESS
;
4546 PSERVICE_HANDLE hSvc
;
4547 PSERVICE lpService
= NULL
;
4548 HKEY hServiceKey
= NULL
;
4549 DWORD dwRequiredSize
;
4550 LPWSTR lpDescription
= NULL
;
4551 LPWSTR lpFailureCommand
= NULL
;
4552 LPWSTR lpRebootMessage
= NULL
;
4554 DPRINT("RQueryServiceConfig2W() called\n");
4557 return ERROR_INVALID_ADDRESS
;
4560 return ERROR_SHUTDOWN_IN_PROGRESS
;
4562 hSvc
= (PSERVICE_HANDLE
)hService
;
4563 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4565 DPRINT1("Invalid handle tag!\n");
4566 return ERROR_INVALID_HANDLE
;
4569 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4570 SERVICE_QUERY_CONFIG
))
4572 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4573 return ERROR_ACCESS_DENIED
;
4576 lpService
= hSvc
->ServiceEntry
;
4577 if (lpService
== NULL
)
4579 DPRINT1("lpService == NULL!\n");
4580 return ERROR_INVALID_HANDLE
;
4583 /* FIXME: Lock the service database shared */
4585 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4588 if (dwError
!= ERROR_SUCCESS
)
4591 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4593 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4596 dwError
= ScmReadString(hServiceKey
,
4599 if (dwError
!= ERROR_SUCCESS
)
4602 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4604 if (cbBufSize
< dwRequiredSize
)
4606 *pcbBytesNeeded
= dwRequiredSize
;
4607 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4611 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4612 wcscpy(lpStr
, lpDescription
);
4613 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4615 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4618 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
4622 dwError
= ScmReadString(hServiceKey
,
4626 dwError
= ScmReadString(hServiceKey
,
4630 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
4632 if (lpFailureCommand
)
4633 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
4635 if (lpRebootMessage
)
4636 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
4638 if (cbBufSize
< dwRequiredSize
)
4640 *pcbBytesNeeded
= dwRequiredSize
;
4641 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4645 lpFailureActions
->cActions
= 0;
4646 lpFailureActions
->dwResetPeriod
= 0;
4647 lpFailureActions
->lpCommand
= NULL
;
4648 lpFailureActions
->lpRebootMsg
= NULL
;
4649 lpFailureActions
->lpsaActions
= NULL
;
4651 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
4652 if (lpRebootMessage
)
4654 wcscpy(lpStr
, lpRebootMessage
);
4655 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
4656 lpStr
+= wcslen(lpRebootMessage
) + 1;
4659 if (lpFailureCommand
)
4661 wcscpy(lpStr
, lpFailureCommand
);
4662 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
4663 lpStr
+= wcslen(lpRebootMessage
) + 1;
4665 dwError
= STATUS_SUCCESS
;
4670 if (lpDescription
!= NULL
)
4671 HeapFree(GetProcessHeap(), 0, lpDescription
);
4673 if (lpRebootMessage
!= NULL
)
4674 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
4676 if (lpFailureCommand
!= NULL
)
4677 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
4679 if (hServiceKey
!= NULL
)
4680 RegCloseKey(hServiceKey
);
4682 /* FIXME: Unlock database */
4684 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4691 DWORD
RQueryServiceStatusEx(
4692 SC_RPC_HANDLE hService
,
4693 SC_STATUS_TYPE InfoLevel
,
4696 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4698 LPSERVICE_STATUS_PROCESS lpStatus
;
4699 PSERVICE_HANDLE hSvc
;
4702 DPRINT("RQueryServiceStatusEx() called\n");
4705 return ERROR_SHUTDOWN_IN_PROGRESS
;
4707 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4708 return ERROR_INVALID_LEVEL
;
4710 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4712 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4713 return ERROR_INSUFFICIENT_BUFFER
;
4715 hSvc
= (PSERVICE_HANDLE
)hService
;
4716 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4718 DPRINT1("Invalid handle tag!\n");
4719 return ERROR_INVALID_HANDLE
;
4722 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4723 SERVICE_QUERY_STATUS
))
4725 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4726 return ERROR_ACCESS_DENIED
;
4729 lpService
= hSvc
->ServiceEntry
;
4730 if (lpService
== NULL
)
4732 DPRINT1("lpService == NULL!\n");
4733 return ERROR_INVALID_HANDLE
;
4736 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4738 /* Return service status information */
4739 RtlCopyMemory(lpStatus
,
4741 sizeof(SERVICE_STATUS
));
4743 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
4744 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4746 return ERROR_SUCCESS
;
4751 DWORD
REnumServicesStatusExA(
4752 SC_RPC_HANDLE hSCManager
,
4753 SC_ENUM_TYPE InfoLevel
,
4754 DWORD dwServiceType
,
4755 DWORD dwServiceState
,
4758 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4759 LPBOUNDED_DWORD_256K lpServicesReturned
,
4760 LPBOUNDED_DWORD_256K lpResumeIndex
,
4761 LPCSTR pszGroupName
)
4763 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
4764 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
4765 LPWSTR lpStringPtrW
;
4767 LPWSTR pszGroupNameW
= NULL
;
4769 DWORD dwServiceCount
;
4771 DPRINT("REnumServicesStatusExA() called\n");
4775 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
4778 DPRINT1("Failed to allocate buffer!\n");
4779 return ERROR_NOT_ENOUGH_MEMORY
;
4782 MultiByteToWideChar(CP_ACP
,
4787 strlen(pszGroupName
) + 1);
4790 if ((cbBufSize
> 0) && (lpBuffer
))
4792 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
4795 DPRINT1("Failed to allocate buffer!\n");
4796 return ERROR_NOT_ENOUGH_MEMORY
;
4800 dwError
= REnumServicesStatusExW(hSCManager
,
4804 (LPBYTE
)lpStatusPtrW
,
4811 /* if no services were returned then we are Done */
4812 if (*lpServicesReturned
== 0)
4815 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
4816 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
4817 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
4818 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
4819 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4821 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
4823 /* Copy the service name */
4824 WideCharToMultiByte(CP_ACP
,
4829 wcslen(lpStringPtrW
),
4833 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4834 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4835 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4837 /* Copy the display name */
4838 WideCharToMultiByte(CP_ACP
,
4843 wcslen(lpStringPtrW
),
4847 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4848 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4849 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4851 /* Copy the status information */
4852 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
4853 &lpStatusPtrW
->ServiceStatusProcess
,
4854 sizeof(SERVICE_STATUS
));
4856 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
4857 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4863 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
4866 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
4868 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
4875 DWORD
REnumServicesStatusExW(
4876 SC_RPC_HANDLE hSCManager
,
4877 SC_ENUM_TYPE InfoLevel
,
4878 DWORD dwServiceType
,
4879 DWORD dwServiceState
,
4882 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4883 LPBOUNDED_DWORD_256K lpServicesReturned
,
4884 LPBOUNDED_DWORD_256K lpResumeIndex
,
4885 LPCWSTR pszGroupName
)
4887 PMANAGER_HANDLE hManager
;
4889 DWORD dwError
= ERROR_SUCCESS
;
4890 PLIST_ENTRY ServiceEntry
;
4891 PSERVICE CurrentService
;
4893 DWORD dwRequiredSize
;
4894 DWORD dwServiceCount
;
4896 DWORD dwLastResumeCount
= 0;
4897 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
4900 DPRINT("REnumServicesStatusExW() called\n");
4903 return ERROR_SHUTDOWN_IN_PROGRESS
;
4905 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
4906 return ERROR_INVALID_LEVEL
;
4908 hManager
= (PMANAGER_HANDLE
)hSCManager
;
4909 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
4911 DPRINT1("Invalid manager handle!\n");
4912 return ERROR_INVALID_HANDLE
;
4915 *pcbBytesNeeded
= 0;
4916 *lpServicesReturned
= 0;
4918 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
4920 DPRINT1("Not a valid Service Type!\n");
4921 return ERROR_INVALID_PARAMETER
;
4924 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
4926 DPRINT1("Not a valid Service State!\n");
4927 return ERROR_INVALID_PARAMETER
;
4930 /* Check access rights */
4931 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4932 SC_MANAGER_ENUMERATE_SERVICE
))
4934 DPRINT1("Insufficient access rights! 0x%lx\n",
4935 hManager
->Handle
.DesiredAccess
);
4936 return ERROR_ACCESS_DENIED
;
4939 if (lpResumeIndex
) dwLastResumeCount
= *lpResumeIndex
;
4941 /* Lock the service list shared */
4943 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4944 if (lpService
== NULL
)
4946 dwError
= ERROR_SUCCESS
;
4953 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4954 ServiceEntry
!= &ServiceListHead
;
4955 ServiceEntry
= ServiceEntry
->Flink
)
4957 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4961 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4964 dwState
= SERVICE_ACTIVE
;
4965 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4966 dwState
= SERVICE_INACTIVE
;
4968 if ((dwState
& dwServiceState
) == 0)
4973 if (*pszGroupName
== 0)
4975 if (CurrentService
->lpGroup
!= NULL
)
4980 if ((CurrentService
->lpGroup
== NULL
) ||
4981 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4986 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4987 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4988 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4990 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4992 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
4993 dwRequiredSize
+= dwSize
;
4995 dwLastResumeCount
= CurrentService
->dwResumeCount
;
4999 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5005 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5006 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5009 ServiceEntry
!= &ServiceListHead
;
5010 ServiceEntry
= ServiceEntry
->Flink
)
5012 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5016 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5019 dwState
= SERVICE_ACTIVE
;
5020 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5021 dwState
= SERVICE_INACTIVE
;
5023 if ((dwState
& dwServiceState
) == 0)
5028 if (*pszGroupName
== 0)
5030 if (CurrentService
->lpGroup
!= NULL
)
5035 if ((CurrentService
->lpGroup
== NULL
) ||
5036 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5041 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5042 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5043 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5045 dwError
= ERROR_MORE_DATA
;
5048 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5051 *lpResumeIndex
= dwLastResumeCount
;
5053 *lpServicesReturned
= dwServiceCount
;
5054 *pcbBytesNeeded
= dwRequiredSize
;
5056 /* If there was no services that matched */
5057 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5059 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5063 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5064 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5065 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5068 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5069 ServiceEntry
!= &ServiceListHead
;
5070 ServiceEntry
= ServiceEntry
->Flink
)
5072 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5076 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5079 dwState
= SERVICE_ACTIVE
;
5080 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5081 dwState
= SERVICE_INACTIVE
;
5083 if ((dwState
& dwServiceState
) == 0)
5088 if (*pszGroupName
== 0)
5090 if (CurrentService
->lpGroup
!= NULL
)
5095 if ((CurrentService
->lpGroup
== NULL
) ||
5096 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5101 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5102 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5103 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5105 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5107 /* Copy the service name */
5109 CurrentService
->lpServiceName
);
5110 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5111 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5113 /* Copy the display name */
5115 CurrentService
->lpDisplayName
);
5116 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5117 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5119 /* Copy the status information */
5120 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5121 &CurrentService
->Status
,
5122 sizeof(SERVICE_STATUS
));
5123 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
5124 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5127 dwRequiredSize
+= dwSize
;
5137 *pcbBytesNeeded
= 0;
5143 /* Unlock the service list */
5145 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5152 DWORD
RSendTSMessage(
5153 handle_t BindingHandle
) /* FIXME */
5156 return ERROR_CALL_NOT_IMPLEMENTED
;
5161 DWORD
RCreateServiceWOW64A(
5162 handle_t BindingHandle
,
5163 LPSTR lpServiceName
,
5164 LPSTR lpDisplayName
,
5165 DWORD dwDesiredAccess
,
5166 DWORD dwServiceType
,
5168 DWORD dwErrorControl
,
5169 LPSTR lpBinaryPathName
,
5170 LPSTR lpLoadOrderGroup
,
5172 LPBYTE lpDependencies
,
5174 LPSTR lpServiceStartName
,
5177 LPSC_RPC_HANDLE lpServiceHandle
)
5180 return ERROR_CALL_NOT_IMPLEMENTED
;
5185 DWORD
RCreateServiceWOW64W(
5186 handle_t BindingHandle
,
5187 LPWSTR lpServiceName
,
5188 LPWSTR lpDisplayName
,
5189 DWORD dwDesiredAccess
,
5190 DWORD dwServiceType
,
5192 DWORD dwErrorControl
,
5193 LPWSTR lpBinaryPathName
,
5194 LPWSTR lpLoadOrderGroup
,
5196 LPBYTE lpDependencies
,
5198 LPWSTR lpServiceStartName
,
5201 LPSC_RPC_HANDLE lpServiceHandle
)
5204 return ERROR_CALL_NOT_IMPLEMENTED
;
5209 DWORD
RQueryServiceTagInfo(
5210 handle_t BindingHandle
) /* FIXME */
5213 return ERROR_CALL_NOT_IMPLEMENTED
;
5218 DWORD
RNotifyServiceStatusChange(
5219 SC_RPC_HANDLE hService
,
5220 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5221 GUID
*pClientProcessGuid
,
5222 GUID
*pSCMProcessGuid
,
5223 PBOOL pfCreateRemoteQueue
,
5224 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5227 return ERROR_CALL_NOT_IMPLEMENTED
;
5232 DWORD
RGetNotifyResults(
5233 SC_NOTIFY_RPC_HANDLE hNotify
,
5234 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5237 return ERROR_CALL_NOT_IMPLEMENTED
;
5242 DWORD
RCloseNotifyHandle(
5243 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5247 return ERROR_CALL_NOT_IMPLEMENTED
;
5252 DWORD
RControlServiceExA(
5253 SC_RPC_HANDLE hService
,
5258 return ERROR_CALL_NOT_IMPLEMENTED
;
5263 DWORD
RControlServiceExW(
5264 SC_RPC_HANDLE hService
,
5269 return ERROR_CALL_NOT_IMPLEMENTED
;
5274 DWORD
RSendPnPMessage(
5275 handle_t BindingHandle
) /* FIXME */
5278 return ERROR_CALL_NOT_IMPLEMENTED
;
5283 DWORD
RValidatePnPService(
5284 handle_t BindingHandle
) /* FIXME */
5287 return ERROR_CALL_NOT_IMPLEMENTED
;
5292 DWORD
ROpenServiceStatusHandle(
5293 handle_t BindingHandle
) /* FIXME */
5296 return ERROR_CALL_NOT_IMPLEMENTED
;
5302 handle_t BindingHandle
) /* FIXME */
5305 return ERROR_CALL_NOT_IMPLEMENTED
;
5309 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5311 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5315 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5317 HeapFree(GetProcessHeap(), 0, ptr
);
5321 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5326 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5331 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)