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 /* Return service status information */
648 RtlCopyMemory(lpServiceStatus
,
650 sizeof(SERVICE_STATUS
));
657 DWORD
RDeleteService(
658 SC_RPC_HANDLE hService
)
660 PSERVICE_HANDLE hSvc
;
664 DPRINT("RDeleteService() called\n");
667 return ERROR_SHUTDOWN_IN_PROGRESS
;
669 hSvc
= (PSERVICE_HANDLE
)hService
;
670 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
671 return ERROR_INVALID_HANDLE
;
673 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
675 return ERROR_ACCESS_DENIED
;
677 lpService
= hSvc
->ServiceEntry
;
678 if (lpService
== NULL
)
680 DPRINT1("lpService == NULL!\n");
681 return ERROR_INVALID_HANDLE
;
684 /* FIXME: Acquire service database lock exclusively */
686 if (lpService
->bDeleted
)
688 DPRINT1("The service has already been marked for delete!\n");
689 return ERROR_SERVICE_MARKED_FOR_DELETE
;
692 /* Mark service for delete */
693 lpService
->bDeleted
= TRUE
;
695 dwError
= ScmMarkServiceForDelete(lpService
);
697 /* FIXME: Release service database lock */
699 DPRINT("RDeleteService() done\n");
706 DWORD
RLockServiceDatabase(
707 SC_RPC_HANDLE hSCManager
,
708 LPSC_RPC_LOCK lpLock
)
710 PMANAGER_HANDLE hMgr
;
712 DPRINT("RLockServiceDatabase() called\n");
716 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
717 if (!hMgr
|| hMgr
->Handle
.Tag
!= MANAGER_TAG
)
718 return ERROR_INVALID_HANDLE
;
720 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
722 return ERROR_ACCESS_DENIED
;
724 // return ScmLockDatabase(0, hMgr->0xC, hLock);
726 /* FIXME: Lock the database */
727 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
729 return ERROR_SUCCESS
;
734 DWORD
RQueryServiceObjectSecurity(
735 SC_RPC_HANDLE hService
,
736 SECURITY_INFORMATION dwSecurityInformation
,
737 LPBYTE lpSecurityDescriptor
,
739 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
741 PSERVICE_HANDLE hSvc
;
743 ULONG DesiredAccess
= 0;
749 SECURITY_DESCRIPTOR ObjectDescriptor
;
751 DPRINT("RQueryServiceObjectSecurity() called\n");
753 hSvc
= (PSERVICE_HANDLE
)hService
;
754 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
756 DPRINT1("Invalid handle tag!\n");
757 return ERROR_INVALID_HANDLE
;
760 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
761 GROUP_SECURITY_INFORMATION
||
762 OWNER_SECURITY_INFORMATION
))
763 DesiredAccess
|= READ_CONTROL
;
765 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
766 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
768 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
771 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
772 return ERROR_ACCESS_DENIED
;
775 lpService
= hSvc
->ServiceEntry
;
776 if (lpService
== NULL
)
778 DPRINT1("lpService == NULL!\n");
779 return ERROR_INVALID_HANDLE
;
782 /* FIXME: Lock the service list */
785 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
787 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
788 dwSecurityInformation
,
789 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
793 /* FIXME: Unlock the service list */
795 if (NT_SUCCESS(Status
))
797 *pcbBytesNeeded
= dwBytesNeeded
;
798 dwError
= STATUS_SUCCESS
;
800 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
802 *pcbBytesNeeded
= dwBytesNeeded
;
803 dwError
= ERROR_INSUFFICIENT_BUFFER
;
805 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
807 dwError
= ERROR_GEN_FAILURE
;
811 dwError
= RtlNtStatusToDosError(Status
);
819 DWORD
RSetServiceObjectSecurity(
820 SC_RPC_HANDLE hService
,
821 DWORD dwSecurityInformation
,
822 LPBYTE lpSecurityDescriptor
,
823 DWORD dwSecuityDescriptorSize
)
825 PSERVICE_HANDLE hSvc
;
827 ULONG DesiredAccess
= 0;
828 /* HANDLE hToken = NULL; */
830 /* NTSTATUS Status; */
833 DPRINT1("RSetServiceObjectSecurity() called\n");
835 hSvc
= (PSERVICE_HANDLE
)hService
;
836 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
838 DPRINT1("Invalid handle tag!\n");
839 return ERROR_INVALID_HANDLE
;
842 if (dwSecurityInformation
== 0 ||
843 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
844 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
845 return ERROR_INVALID_PARAMETER
;
847 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
848 return ERROR_INVALID_PARAMETER
;
850 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
851 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
853 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
854 DesiredAccess
|= WRITE_DAC
;
856 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
857 DesiredAccess
|= WRITE_OWNER
;
859 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
860 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
861 return ERROR_INVALID_PARAMETER
;
863 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
864 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
865 return ERROR_INVALID_PARAMETER
;
867 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
870 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
871 return ERROR_ACCESS_DENIED
;
874 lpService
= hSvc
->ServiceEntry
;
875 if (lpService
== NULL
)
877 DPRINT1("lpService == NULL!\n");
878 return ERROR_INVALID_HANDLE
;
881 if (lpService
->bDeleted
)
882 return ERROR_SERVICE_MARKED_FOR_DELETE
;
885 RpcImpersonateClient(NULL
);
887 Status
= NtOpenThreadToken(NtCurrentThread(),
891 if (!NT_SUCCESS(Status
))
892 return RtlNtStatusToDosError(Status
);
896 /* FIXME: Lock service database */
898 Status
= RtlSetSecurityObject(dwSecurityInformation
,
899 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
900 &lpService
->lpSecurityDescriptor
,
903 if (!NT_SUCCESS(Status
))
905 dwError
= RtlNtStatusToDosError(Status
);
910 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
911 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
913 if (dwError
!= ERROR_SUCCESS
)
917 dwError
= ERROR_SUCCESS
;
918 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
919 // lpService->lpSecurityDescriptor);
921 RegFlushKey(hServiceKey
);
922 RegCloseKey(hServiceKey
);
931 /* FIXME: Unlock service database */
933 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
940 DWORD
RQueryServiceStatus(
941 SC_RPC_HANDLE hService
,
942 LPSERVICE_STATUS lpServiceStatus
)
944 PSERVICE_HANDLE hSvc
;
947 DPRINT("RQueryServiceStatus() called\n");
950 return ERROR_SHUTDOWN_IN_PROGRESS
;
952 hSvc
= (PSERVICE_HANDLE
)hService
;
953 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
955 DPRINT1("Invalid handle tag!\n");
956 return ERROR_INVALID_HANDLE
;
959 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
960 SERVICE_QUERY_STATUS
))
962 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
963 return ERROR_ACCESS_DENIED
;
966 lpService
= hSvc
->ServiceEntry
;
967 if (lpService
== NULL
)
969 DPRINT1("lpService == NULL!\n");
970 return ERROR_INVALID_HANDLE
;
973 /* Return service status information */
974 RtlCopyMemory(lpServiceStatus
,
976 sizeof(SERVICE_STATUS
));
978 return ERROR_SUCCESS
;
983 ScmIsValidServiceState(DWORD dwCurrentState
)
985 switch (dwCurrentState
)
987 case SERVICE_STOPPED
:
988 case SERVICE_START_PENDING
:
989 case SERVICE_STOP_PENDING
:
990 case SERVICE_RUNNING
:
991 case SERVICE_CONTINUE_PENDING
:
992 case SERVICE_PAUSE_PENDING
:
1003 DWORD
RSetServiceStatus(
1004 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1005 LPSERVICE_STATUS lpServiceStatus
)
1009 DPRINT("RSetServiceStatus() called\n");
1010 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1011 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1012 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1013 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1014 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1015 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1016 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1017 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1019 if (hServiceStatus
== 0)
1021 DPRINT1("hServiceStatus == NULL!\n");
1022 return ERROR_INVALID_HANDLE
;
1025 lpService
= ScmGetServiceEntryByClientHandle((HANDLE
)hServiceStatus
);
1026 if (lpService
== NULL
)
1028 DPRINT1("lpService == NULL!\n");
1029 return ERROR_INVALID_HANDLE
;
1032 /* Check current state */
1033 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1035 DPRINT1("Invalid service state!\n");
1036 return ERROR_INVALID_DATA
;
1039 /* Check service type */
1040 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1041 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1043 DPRINT1("Invalid service type!\n");
1044 return ERROR_INVALID_DATA
;
1047 /* Check accepted controls */
1048 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1050 DPRINT1("Invalid controls accepted!\n");
1051 return ERROR_INVALID_DATA
;
1055 RtlCopyMemory(&lpService
->Status
,
1057 sizeof(SERVICE_STATUS
));
1059 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1060 DPRINT("RSetServiceStatus() done\n");
1062 return ERROR_SUCCESS
;
1067 DWORD
RUnlockServiceDatabase(
1071 return ERROR_SUCCESS
;
1076 DWORD
RNotifyBootConfigStatus(
1077 SVCCTL_HANDLEW lpMachineName
,
1078 DWORD BootAcceptable
)
1081 return ERROR_CALL_NOT_IMPLEMENTED
;
1086 DWORD
RI_ScSetServiceBitsW(
1087 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1088 DWORD dwServiceBits
,
1090 int bUpdateImmediately
,
1094 return ERROR_CALL_NOT_IMPLEMENTED
;
1099 DWORD
RChangeServiceConfigW(
1100 SC_RPC_HANDLE hService
,
1101 DWORD dwServiceType
,
1103 DWORD dwErrorControl
,
1104 LPWSTR lpBinaryPathName
,
1105 LPWSTR lpLoadOrderGroup
,
1107 LPBYTE lpDependencies
,
1109 LPWSTR lpServiceStartName
,
1112 LPWSTR lpDisplayName
)
1114 DWORD dwError
= ERROR_SUCCESS
;
1115 PSERVICE_HANDLE hSvc
;
1116 PSERVICE lpService
= NULL
;
1117 HKEY hServiceKey
= NULL
;
1118 LPWSTR lpDisplayNameW
= NULL
;
1120 DPRINT("RChangeServiceConfigW() called\n");
1121 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1122 DPRINT("dwStartType = %lu\n", dwStartType
);
1123 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1124 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1125 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1126 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1129 return ERROR_SHUTDOWN_IN_PROGRESS
;
1131 hSvc
= (PSERVICE_HANDLE
)hService
;
1132 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1134 DPRINT1("Invalid handle tag!\n");
1135 return ERROR_INVALID_HANDLE
;
1138 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1139 SERVICE_CHANGE_CONFIG
))
1141 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1142 return ERROR_ACCESS_DENIED
;
1145 lpService
= hSvc
->ServiceEntry
;
1146 if (lpService
== NULL
)
1148 DPRINT1("lpService == NULL!\n");
1149 return ERROR_INVALID_HANDLE
;
1152 /* FIXME: Lock database exclusively */
1154 if (lpService
->bDeleted
)
1156 /* FIXME: Unlock database */
1157 DPRINT1("The service has already been marked for delete!\n");
1158 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1161 /* Open the service key */
1162 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1165 if (dwError
!= ERROR_SUCCESS
)
1168 /* Write service data to the registry */
1169 /* Set the display name */
1170 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1172 RegSetValueExW(hServiceKey
,
1176 (LPBYTE
)lpDisplayName
,
1177 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1179 /* Update the display name */
1180 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1182 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1183 if (lpDisplayNameW
== NULL
)
1185 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1189 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1190 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1192 lpService
->lpDisplayName
= lpDisplayNameW
;
1195 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1197 /* Set the service type */
1198 dwError
= RegSetValueExW(hServiceKey
,
1202 (LPBYTE
)&dwServiceType
,
1204 if (dwError
!= ERROR_SUCCESS
)
1207 lpService
->Status
.dwServiceType
= dwServiceType
;
1210 if (dwStartType
!= SERVICE_NO_CHANGE
)
1212 /* Set the start value */
1213 dwError
= RegSetValueExW(hServiceKey
,
1217 (LPBYTE
)&dwStartType
,
1219 if (dwError
!= ERROR_SUCCESS
)
1222 lpService
->dwStartType
= dwStartType
;
1225 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1227 /* Set the error control value */
1228 dwError
= RegSetValueExW(hServiceKey
,
1232 (LPBYTE
)&dwErrorControl
,
1234 if (dwError
!= ERROR_SUCCESS
)
1237 lpService
->dwErrorControl
= dwErrorControl
;
1241 /* FIXME: set the new ImagePath value */
1243 /* Set the image path */
1244 if (dwServiceType
& SERVICE_WIN32
)
1246 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1248 dwError
= RegSetValueExW(hServiceKey
,
1252 (LPBYTE
)lpBinaryPathName
,
1253 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1254 if (dwError
!= ERROR_SUCCESS
)
1258 else if (dwServiceType
& SERVICE_DRIVER
)
1260 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1262 dwError
= RegSetValueExW(hServiceKey
,
1266 (LPBYTE
)lpImagePath
,
1267 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1268 if (dwError
!= ERROR_SUCCESS
)
1274 /* Set the group name */
1275 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1277 dwError
= RegSetValueExW(hServiceKey
,
1281 (LPBYTE
)lpLoadOrderGroup
,
1282 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1283 if (dwError
!= ERROR_SUCCESS
)
1285 /* FIXME: Update lpService->lpServiceGroup */
1288 if (lpdwTagId
!= NULL
)
1290 dwError
= ScmAssignNewTag(lpService
);
1291 if (dwError
!= ERROR_SUCCESS
)
1294 dwError
= RegSetValueExW(hServiceKey
,
1298 (LPBYTE
)&lpService
->dwTag
,
1300 if (dwError
!= ERROR_SUCCESS
)
1303 *lpdwTagId
= lpService
->dwTag
;
1306 /* Write dependencies */
1307 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1309 dwError
= ScmWriteDependencies(hServiceKey
,
1310 (LPWSTR
)lpDependencies
,
1312 if (dwError
!= ERROR_SUCCESS
)
1316 if (lpPassword
!= NULL
)
1318 /* FIXME: Write password */
1321 /* FIXME: Unlock database */
1324 if (hServiceKey
!= NULL
)
1325 RegCloseKey(hServiceKey
);
1327 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1333 /* Create a path suitable for the bootloader out of the full path */
1335 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1337 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1340 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1341 OBJECT_ATTRIBUTES ObjectAttributes
;
1343 HANDLE SymbolicLinkHandle
;
1345 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1347 ServiceNameLen
= wcslen(CanonName
);
1349 /* First check, if it's already good */
1350 if (ServiceNameLen
> 12 &&
1351 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1353 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1354 if (*RelativeName
== NULL
)
1356 DPRINT1("Error allocating memory for boot driver name!\n");
1357 return ERROR_NOT_ENOUGH_MEMORY
;
1361 wcscpy(*RelativeName
, CanonName
);
1363 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1364 return ERROR_SUCCESS
;
1367 /* If it has %SystemRoot% prefix, substitute it to \System*/
1368 if (ServiceNameLen
> 13 &&
1369 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1371 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1372 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1374 if (*RelativeName
== NULL
)
1376 DPRINT1("Error allocating memory for boot driver name!\n");
1377 return ERROR_NOT_ENOUGH_MEMORY
;
1381 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1382 wcscat(*RelativeName
, CanonName
+ 13);
1384 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1385 return ERROR_SUCCESS
;
1388 /* Get buffer size needed for expanding env strings */
1389 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1391 if (BufferSize
<= 1)
1393 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1394 return ERROR_INVALID_ENVIRONMENT
;
1397 /* Allocate memory, since the size is known now */
1398 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1401 DPRINT1("Error allocating memory for boot driver name!\n");
1402 return ERROR_NOT_ENOUGH_MEMORY
;
1406 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1409 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1410 LocalFree(Expanded
);
1411 return ERROR_NOT_ENOUGH_MEMORY
;
1414 /* Convert to NY-style path */
1415 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1417 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1418 return ERROR_INVALID_ENVIRONMENT
;
1421 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1423 /* No need to keep the dos-path anymore */
1424 LocalFree(Expanded
);
1426 /* Copy it to the allocated place */
1427 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1430 DPRINT1("Error allocating memory for boot driver name!\n");
1431 return ERROR_NOT_ENOUGH_MEMORY
;
1434 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1435 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1436 Expanded
[ExpandedLen
] = 0;
1438 if (ServiceNameLen
> ExpandedLen
&&
1439 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1441 /* Only \SystemRoot\ is missing */
1442 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1443 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1444 if (*RelativeName
== NULL
)
1446 DPRINT1("Error allocating memory for boot driver name!\n");
1447 LocalFree(Expanded
);
1448 return ERROR_NOT_ENOUGH_MEMORY
;
1451 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1452 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1454 RtlFreeUnicodeString(&NtPathName
);
1455 return ERROR_SUCCESS
;
1458 /* The most complex case starts here */
1459 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1460 InitializeObjectAttributes(&ObjectAttributes
,
1462 OBJ_CASE_INSENSITIVE
,
1466 /* Open this symlink */
1467 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1469 if (NT_SUCCESS(Status
))
1471 LinkTarget
.Length
= 0;
1472 LinkTarget
.MaximumLength
= 0;
1474 DPRINT("Opened symbolic link object\n");
1476 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1477 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1479 /* Check if required buffer size is sane */
1480 if (BufferSize
> 0xFFFD)
1482 DPRINT1("Too large buffer required\n");
1485 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1486 LocalFree(Expanded
);
1487 return ERROR_NOT_ENOUGH_MEMORY
;
1490 /* Alloc the string */
1491 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1492 if (!LinkTarget
.Buffer
)
1494 DPRINT1("Unable to alloc buffer\n");
1495 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1496 LocalFree(Expanded
);
1497 return ERROR_NOT_ENOUGH_MEMORY
;
1500 /* Do a real query now */
1501 LinkTarget
.Length
= BufferSize
;
1502 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1504 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1505 if (NT_SUCCESS(Status
))
1507 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1509 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1510 if ((ServiceNameLen
> ExpandedLen
) &&
1511 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1513 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1514 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1516 if (*RelativeName
== NULL
)
1518 DPRINT1("Unable to alloc buffer\n");
1519 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1520 LocalFree(Expanded
);
1521 RtlFreeUnicodeString(&NtPathName
);
1522 return ERROR_NOT_ENOUGH_MEMORY
;
1525 /* Copy it over, substituting the first part
1527 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1528 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1531 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1532 LocalFree(Expanded
);
1533 RtlFreeUnicodeString(&NtPathName
);
1535 /* Return success */
1536 return ERROR_SUCCESS
;
1540 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1541 LocalFree(Expanded
);
1542 RtlFreeUnicodeString(&NtPathName
);
1543 return ERROR_INVALID_PARAMETER
;
1548 DPRINT1("Error, Status = %08X\n", Status
);
1549 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1550 LocalFree(Expanded
);
1551 RtlFreeUnicodeString(&NtPathName
);
1552 return ERROR_INVALID_PARAMETER
;
1557 DPRINT1("Error, Status = %08X\n", Status
);
1558 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1559 LocalFree(Expanded
);
1560 RtlFreeUnicodeString(&NtPathName
);
1561 return ERROR_INVALID_PARAMETER
;
1566 DPRINT1("Error, Status = %08X\n", Status
);
1567 LocalFree(Expanded
);
1568 return ERROR_INVALID_PARAMETER
;
1572 *RelativeName
= NULL
;
1573 return ERROR_INVALID_PARAMETER
;
1577 ScmCanonDriverImagePath(DWORD dwStartType
,
1578 const wchar_t *lpServiceName
,
1579 wchar_t **lpCanonName
)
1581 DWORD ServiceNameLen
, Result
;
1582 UNICODE_STRING NtServiceName
;
1583 WCHAR
*RelativeName
;
1584 const WCHAR
*SourceName
= lpServiceName
;
1586 /* Calculate the length of the service's name */
1587 ServiceNameLen
= wcslen(lpServiceName
);
1589 /* 12 is wcslen(L"\\SystemRoot\\") */
1590 if (ServiceNameLen
> 12 &&
1591 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1593 /* SystemRoot prefix is already included */
1595 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1597 if (*lpCanonName
== NULL
)
1599 DPRINT1("Error allocating memory for canonized service name!\n");
1600 return ERROR_NOT_ENOUGH_MEMORY
;
1603 /* If it's a boot-time driver, it must be systemroot relative */
1604 if (dwStartType
== SERVICE_BOOT_START
)
1608 wcscpy(*lpCanonName
, SourceName
);
1610 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1614 /* Check if it has %SystemRoot% (len=13) */
1615 if (ServiceNameLen
> 13 &&
1616 !_wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1618 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1619 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1621 if (*lpCanonName
== NULL
)
1623 DPRINT1("Error allocating memory for canonized service name!\n");
1624 return ERROR_NOT_ENOUGH_MEMORY
;
1627 /* If it's a boot-time driver, it must be systemroot relative */
1628 if (dwStartType
== SERVICE_BOOT_START
)
1629 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1631 wcscat(*lpCanonName
, lpServiceName
+ 13);
1633 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1637 /* Check if it's a relative path name */
1638 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1640 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1642 if (*lpCanonName
== NULL
)
1644 DPRINT1("Error allocating memory for canonized service name!\n");
1645 return ERROR_NOT_ENOUGH_MEMORY
;
1648 /* Just copy it over without changing */
1649 wcscpy(*lpCanonName
, lpServiceName
);
1654 /* It seems to be a DOS path, convert it */
1655 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1657 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1658 return ERROR_INVALID_PARAMETER
;
1661 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1663 if (*lpCanonName
== NULL
)
1665 DPRINT1("Error allocating memory for canonized service name!\n");
1666 RtlFreeUnicodeString(&NtServiceName
);
1667 return ERROR_NOT_ENOUGH_MEMORY
;
1670 /* Copy the string */
1671 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1673 /* The unicode string is not needed anymore */
1674 RtlFreeUnicodeString(&NtServiceName
);
1676 if (dwStartType
!= SERVICE_BOOT_START
)
1678 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1682 /* The service is boot-started, so must be relative */
1683 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1686 /* There is a problem, free name and return */
1687 LocalFree(*lpCanonName
);
1688 DPRINT1("Error converting named!\n");
1692 ASSERT(RelativeName
);
1694 /* Copy that string */
1695 wcscpy(*lpCanonName
, RelativeName
+ 12);
1697 /* Free the allocated buffer */
1698 LocalFree(RelativeName
);
1700 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1708 DWORD
RCreateServiceW(
1709 SC_RPC_HANDLE hSCManager
,
1710 LPCWSTR lpServiceName
,
1711 LPCWSTR lpDisplayName
,
1712 DWORD dwDesiredAccess
,
1713 DWORD dwServiceType
,
1715 DWORD dwErrorControl
,
1716 LPCWSTR lpBinaryPathName
,
1717 LPCWSTR lpLoadOrderGroup
,
1719 LPBYTE lpDependencies
,
1721 LPCWSTR lpServiceStartName
,
1724 LPSC_RPC_HANDLE lpServiceHandle
)
1726 PMANAGER_HANDLE hManager
;
1727 DWORD dwError
= ERROR_SUCCESS
;
1728 PSERVICE lpService
= NULL
;
1729 SC_HANDLE hServiceHandle
= NULL
;
1730 LPWSTR lpImagePath
= NULL
;
1731 HKEY hServiceKey
= NULL
;
1733 DPRINT("RCreateServiceW() called\n");
1734 DPRINT("lpServiceName = %S\n", lpServiceName
);
1735 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1736 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1737 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1738 DPRINT("dwStartType = %lu\n", dwStartType
);
1739 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1740 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1741 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1744 return ERROR_SHUTDOWN_IN_PROGRESS
;
1746 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1747 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1749 DPRINT1("Invalid manager handle!\n");
1750 return ERROR_INVALID_HANDLE
;
1753 /* Check access rights */
1754 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1755 SC_MANAGER_CREATE_SERVICE
))
1757 DPRINT1("Insufficient access rights! 0x%lx\n",
1758 hManager
->Handle
.DesiredAccess
);
1759 return ERROR_ACCESS_DENIED
;
1762 if (wcslen(lpServiceName
) == 0)
1764 return ERROR_INVALID_NAME
;
1767 if (wcslen(lpBinaryPathName
) == 0)
1769 return ERROR_INVALID_PARAMETER
;
1772 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1773 (lpServiceStartName
))
1775 return ERROR_INVALID_PARAMETER
;
1778 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1779 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1780 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1782 return ERROR_INVALID_PARAMETER
;
1785 if (dwStartType
> SERVICE_DISABLED
)
1787 return ERROR_INVALID_PARAMETER
;
1790 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1793 /* check if it is marked for deletion */
1794 if (lpService
->bDeleted
)
1795 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1796 /* Return Error exist */
1797 return ERROR_SERVICE_EXISTS
;
1800 if (lpDisplayName
!= NULL
&&
1801 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1802 return ERROR_DUPLICATE_SERVICE_NAME
;
1804 if (dwServiceType
& SERVICE_DRIVER
)
1806 dwError
= ScmCanonDriverImagePath(dwStartType
,
1809 if (dwError
!= ERROR_SUCCESS
)
1814 if (dwStartType
== SERVICE_BOOT_START
||
1815 dwStartType
== SERVICE_SYSTEM_START
)
1817 return ERROR_INVALID_PARAMETER
;
1821 /* Allocate a new service entry */
1822 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1824 if (dwError
!= ERROR_SUCCESS
)
1827 /* Fill the new service entry */
1828 lpService
->Status
.dwServiceType
= dwServiceType
;
1829 lpService
->dwStartType
= dwStartType
;
1830 lpService
->dwErrorControl
= dwErrorControl
;
1832 /* Fill the display name */
1833 if (lpDisplayName
!= NULL
&&
1834 *lpDisplayName
!= 0 &&
1835 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1837 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1838 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1839 if (lpService
->lpDisplayName
== NULL
)
1841 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1844 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1847 /* Assign the service to a group */
1848 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1850 dwError
= ScmSetServiceGroup(lpService
,
1852 if (dwError
!= ERROR_SUCCESS
)
1856 /* Assign a new tag */
1857 if (lpdwTagId
!= NULL
)
1859 dwError
= ScmAssignNewTag(lpService
);
1860 if (dwError
!= ERROR_SUCCESS
)
1864 /* Write service data to the registry */
1865 /* Create the service key */
1866 dwError
= ScmCreateServiceKey(lpServiceName
,
1869 if (dwError
!= ERROR_SUCCESS
)
1872 /* Set the display name */
1873 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1875 RegSetValueExW(hServiceKey
,
1879 (LPBYTE
)lpDisplayName
,
1880 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1883 /* Set the service type */
1884 dwError
= RegSetValueExW(hServiceKey
,
1888 (LPBYTE
)&dwServiceType
,
1890 if (dwError
!= ERROR_SUCCESS
)
1893 /* Set the start value */
1894 dwError
= RegSetValueExW(hServiceKey
,
1898 (LPBYTE
)&dwStartType
,
1900 if (dwError
!= ERROR_SUCCESS
)
1903 /* Set the error control value */
1904 dwError
= RegSetValueExW(hServiceKey
,
1908 (LPBYTE
)&dwErrorControl
,
1910 if (dwError
!= ERROR_SUCCESS
)
1913 /* Set the image path */
1914 if (dwServiceType
& SERVICE_WIN32
)
1916 dwError
= RegSetValueExW(hServiceKey
,
1920 (LPBYTE
)lpBinaryPathName
,
1921 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1922 if (dwError
!= ERROR_SUCCESS
)
1925 else if (dwServiceType
& SERVICE_DRIVER
)
1927 dwError
= RegSetValueExW(hServiceKey
,
1931 (LPBYTE
)lpImagePath
,
1932 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1933 if (dwError
!= ERROR_SUCCESS
)
1937 /* Set the group name */
1938 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1940 dwError
= RegSetValueExW(hServiceKey
,
1944 (LPBYTE
)lpLoadOrderGroup
,
1945 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1946 if (dwError
!= ERROR_SUCCESS
)
1950 if (lpdwTagId
!= NULL
)
1952 dwError
= RegSetValueExW(hServiceKey
,
1956 (LPBYTE
)&lpService
->dwTag
,
1958 if (dwError
!= ERROR_SUCCESS
)
1962 /* Write dependencies */
1963 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1965 dwError
= ScmWriteDependencies(hServiceKey
,
1966 (LPWSTR
)lpDependencies
,
1968 if (dwError
!= ERROR_SUCCESS
)
1972 /* If a non driver and NULL for lpServiceName, write ObjectName as LocalSystem */
1973 if ((dwServiceType
& SERVICE_WIN32
) && (!lpServiceName
))
1975 dwError
= RegSetValueExW(hServiceKey
,
1979 (LPBYTE
)L
"LocalSystem",
1981 if (dwError
!= ERROR_SUCCESS
)
1985 if (lpPassword
!= NULL
)
1987 /* FIXME: Write password */
1990 dwError
= ScmCreateServiceHandle(lpService
,
1992 if (dwError
!= ERROR_SUCCESS
)
1995 dwError
= ScmCheckAccess(hServiceHandle
,
1997 if (dwError
!= ERROR_SUCCESS
)
2000 lpService
->dwRefCount
= 1;
2001 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2004 if (hServiceKey
!= NULL
)
2005 RegCloseKey(hServiceKey
);
2007 if (dwError
== ERROR_SUCCESS
)
2009 DPRINT("hService %p\n", hServiceHandle
);
2010 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2012 if (lpdwTagId
!= NULL
)
2013 *lpdwTagId
= lpService
->dwTag
;
2017 /* Release the display name buffer */
2018 if (lpService
->lpServiceName
!= NULL
)
2019 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2023 /* Remove the service handle */
2024 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2027 if (lpService
!= NULL
)
2029 /* FIXME: remove the service entry */
2033 if (lpImagePath
!= NULL
)
2034 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2036 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2043 DWORD
REnumDependentServicesW(
2044 SC_RPC_HANDLE hService
,
2045 DWORD dwServiceState
,
2048 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2049 LPBOUNDED_DWORD_256K lpServicesReturned
)
2051 DWORD dwError
= ERROR_SUCCESS
;
2052 DWORD dwServicesReturned
= 0;
2053 DWORD dwServiceCount
;
2054 HKEY hServicesKey
= NULL
;
2055 LPSC_RPC_HANDLE hSCObject
;
2056 PSERVICE_HANDLE hSvc
;
2057 PSERVICE lpService
= NULL
;
2058 PSERVICE
*lpServicesArray
= NULL
;
2059 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2062 *pcbBytesNeeded
= 0;
2063 *lpServicesReturned
= 0;
2065 DPRINT("REnumDependentServicesW() called\n");
2067 hSCObject
= &hService
;
2068 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
2069 lpService
= hSvc
->ServiceEntry
;
2071 /* Check access rights */
2072 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2073 SC_MANAGER_ENUMERATE_SERVICE
))
2075 DPRINT1("Insufficient access rights! 0x%lx\n",
2076 hSvc
->Handle
.DesiredAccess
);
2077 return ERROR_ACCESS_DENIED
;
2080 /* Open the Services Reg key */
2081 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2082 L
"System\\CurrentControlSet\\Services",
2086 if (dwError
!= ERROR_SUCCESS
)
2089 /* First determine the bytes needed and get the number of dependent services */
2090 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2095 &dwServicesReturned
);
2096 if (dwError
!= ERROR_SUCCESS
)
2099 /* If buffer size is less than the bytes needed or pointer is null */
2100 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2102 dwError
= ERROR_MORE_DATA
;
2106 /* Allocate memory for array of service pointers */
2107 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2109 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2110 if (!lpServicesArray
)
2112 DPRINT1("Could not allocate a buffer!!\n");
2113 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2117 dwServicesReturned
= 0;
2118 *pcbBytesNeeded
= 0;
2120 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2125 &dwServicesReturned
);
2126 if (dwError
!= ERROR_SUCCESS
)
2131 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2132 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2134 /* Copy EnumDepenedentService to Buffer */
2135 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2137 lpService
= lpServicesArray
[dwServiceCount
];
2139 /* Copy status info */
2140 memcpy(&lpServicesPtr
->ServiceStatus
,
2142 sizeof(SERVICE_STATUS
));
2144 /* Copy display name */
2145 wcscpy(lpStr
, lpService
->lpDisplayName
);
2146 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2147 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2149 /* Copy service name */
2150 wcscpy(lpStr
, lpService
->lpServiceName
);
2151 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2152 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2157 *lpServicesReturned
= dwServicesReturned
;
2160 if (lpServicesArray
!= NULL
)
2161 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2163 RegCloseKey(hServicesKey
);
2165 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2172 DWORD
REnumServicesStatusW(
2173 SC_RPC_HANDLE hSCManager
,
2174 DWORD dwServiceType
,
2175 DWORD dwServiceState
,
2178 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2179 LPBOUNDED_DWORD_256K lpServicesReturned
,
2180 LPBOUNDED_DWORD_256K lpResumeHandle
)
2182 PMANAGER_HANDLE hManager
;
2184 DWORD dwError
= ERROR_SUCCESS
;
2185 PLIST_ENTRY ServiceEntry
;
2186 PSERVICE CurrentService
;
2188 DWORD dwRequiredSize
;
2189 DWORD dwServiceCount
;
2191 DWORD dwLastResumeCount
= 0;
2192 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2195 DPRINT("REnumServicesStatusW() called\n");
2198 return ERROR_SHUTDOWN_IN_PROGRESS
;
2200 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2201 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2203 DPRINT1("Invalid manager handle!\n");
2204 return ERROR_INVALID_HANDLE
;
2207 *pcbBytesNeeded
= 0;
2208 *lpServicesReturned
= 0;
2210 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2212 DPRINT("Not a valid Service Type!\n");
2213 return ERROR_INVALID_PARAMETER
;
2216 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2218 DPRINT("Not a valid Service State!\n");
2219 return ERROR_INVALID_PARAMETER
;
2222 /* Check access rights */
2223 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2224 SC_MANAGER_ENUMERATE_SERVICE
))
2226 DPRINT1("Insufficient access rights! 0x%lx\n",
2227 hManager
->Handle
.DesiredAccess
);
2228 return ERROR_ACCESS_DENIED
;
2231 if (lpResumeHandle
) dwLastResumeCount
= *lpResumeHandle
;
2233 /* FIXME: Lock the service list shared */
2235 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2236 if (lpService
== NULL
)
2238 dwError
= ERROR_SUCCESS
;
2245 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2246 ServiceEntry
!= &ServiceListHead
;
2247 ServiceEntry
= ServiceEntry
->Flink
)
2249 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2253 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2256 dwState
= SERVICE_ACTIVE
;
2257 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2258 dwState
= SERVICE_INACTIVE
;
2260 if ((dwState
& dwServiceState
) == 0)
2263 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2264 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2265 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2267 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2269 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2273 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2274 dwRequiredSize
+= dwSize
;
2276 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2279 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2280 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2283 ServiceEntry
!= &ServiceListHead
;
2284 ServiceEntry
= ServiceEntry
->Flink
)
2286 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2290 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2293 dwState
= SERVICE_ACTIVE
;
2294 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2295 dwState
= SERVICE_INACTIVE
;
2297 if ((dwState
& dwServiceState
) == 0)
2300 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2301 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2302 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2304 dwError
= ERROR_MORE_DATA
;
2307 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2309 if (lpResumeHandle
) *lpResumeHandle
= dwLastResumeCount
;
2310 *lpServicesReturned
= dwServiceCount
;
2311 *pcbBytesNeeded
= dwRequiredSize
;
2313 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2314 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2315 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2318 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2319 ServiceEntry
!= &ServiceListHead
;
2320 ServiceEntry
= ServiceEntry
->Flink
)
2322 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2326 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2329 dwState
= SERVICE_ACTIVE
;
2330 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2331 dwState
= SERVICE_INACTIVE
;
2333 if ((dwState
& dwServiceState
) == 0)
2336 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2337 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2338 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2340 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2343 /* Copy the service name */
2344 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2345 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2346 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2348 /* Copy the display name */
2349 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2350 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2351 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2353 /* Copy the status information */
2354 memcpy(&lpStatusPtr
->ServiceStatus
,
2355 &CurrentService
->Status
,
2356 sizeof(SERVICE_STATUS
));
2359 dwRequiredSize
+= dwSize
;
2364 *pcbBytesNeeded
= 0;
2365 if (lpResumeHandle
) *lpResumeHandle
= 0;
2369 /* FIXME: Unlock the service list */
2371 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2378 DWORD
ROpenSCManagerW(
2379 LPWSTR lpMachineName
,
2380 LPWSTR lpDatabaseName
,
2381 DWORD dwDesiredAccess
,
2382 LPSC_RPC_HANDLE lpScHandle
)
2387 DPRINT("ROpenSCManagerW() called\n");
2388 DPRINT("lpMachineName = %p\n", lpMachineName
);
2389 DPRINT("lpMachineName: %S\n", lpMachineName
);
2390 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2391 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2392 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2395 return ERROR_SHUTDOWN_IN_PROGRESS
;
2398 return ERROR_INVALID_PARAMETER
;
2400 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2402 if (dwError
!= ERROR_SUCCESS
)
2404 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2408 /* Check the desired access */
2409 dwError
= ScmCheckAccess(hHandle
,
2410 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2411 if (dwError
!= ERROR_SUCCESS
)
2413 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2414 HeapFree(GetProcessHeap(), 0, hHandle
);
2418 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2419 DPRINT("*hScm = %p\n", *lpScHandle
);
2421 DPRINT("ROpenSCManagerW() done\n");
2423 return ERROR_SUCCESS
;
2428 DWORD
ROpenServiceW(
2429 SC_RPC_HANDLE hSCManager
,
2430 LPWSTR lpServiceName
,
2431 DWORD dwDesiredAccess
,
2432 LPSC_RPC_HANDLE lpServiceHandle
)
2435 PMANAGER_HANDLE hManager
;
2439 DPRINT("ROpenServiceW() called\n");
2440 DPRINT("hSCManager = %p\n", hSCManager
);
2441 DPRINT("lpServiceName = %p\n", lpServiceName
);
2442 DPRINT("lpServiceName: %S\n", lpServiceName
);
2443 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2446 return ERROR_SHUTDOWN_IN_PROGRESS
;
2448 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2449 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2451 DPRINT1("Invalid manager handle!\n");
2452 return ERROR_INVALID_HANDLE
;
2455 if (!lpServiceHandle
)
2456 return ERROR_INVALID_PARAMETER
;
2459 return ERROR_INVALID_ADDRESS
;
2461 /* FIXME: Lock the service list */
2463 /* Get service database entry */
2464 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2465 if (lpService
== NULL
)
2467 DPRINT("Could not find a service!\n");
2468 return ERROR_SERVICE_DOES_NOT_EXIST
;
2471 /* Create a service handle */
2472 dwError
= ScmCreateServiceHandle(lpService
,
2474 if (dwError
!= ERROR_SUCCESS
)
2476 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2480 /* Check the desired access */
2481 dwError
= ScmCheckAccess(hHandle
,
2483 if (dwError
!= ERROR_SUCCESS
)
2485 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2486 HeapFree(GetProcessHeap(), 0, hHandle
);
2490 lpService
->dwRefCount
++;
2491 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2493 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2494 DPRINT("*hService = %p\n", *lpServiceHandle
);
2496 DPRINT("ROpenServiceW() done\n");
2498 return ERROR_SUCCESS
;
2503 DWORD
RQueryServiceConfigW(
2504 SC_RPC_HANDLE hService
,
2505 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2507 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2509 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2510 DWORD dwError
= ERROR_SUCCESS
;
2511 PSERVICE_HANDLE hSvc
;
2512 PSERVICE lpService
= NULL
;
2513 HKEY hServiceKey
= NULL
;
2514 LPWSTR lpImagePath
= NULL
;
2515 LPWSTR lpServiceStartName
= NULL
;
2516 DWORD dwRequiredSize
;
2517 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2518 WCHAR lpEmptyString
[] = {0,0};
2521 DPRINT("RQueryServiceConfigW() called\n");
2524 return ERROR_SHUTDOWN_IN_PROGRESS
;
2526 hSvc
= (PSERVICE_HANDLE
)hService
;
2527 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2529 DPRINT1("Invalid handle tag!\n");
2530 return ERROR_INVALID_HANDLE
;
2533 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2534 SERVICE_QUERY_CONFIG
))
2536 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2537 return ERROR_ACCESS_DENIED
;
2540 lpService
= hSvc
->ServiceEntry
;
2541 if (lpService
== NULL
)
2543 DPRINT1("lpService == NULL!\n");
2544 return ERROR_INVALID_HANDLE
;
2547 /* FIXME: Lock the service database shared */
2549 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2552 if (dwError
!= ERROR_SUCCESS
)
2555 dwError
= ScmReadString(hServiceKey
,
2558 if (dwError
!= ERROR_SUCCESS
)
2561 ScmReadString(hServiceKey
,
2563 &lpServiceStartName
);
2565 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2567 if (lpImagePath
!= NULL
)
2568 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2570 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2572 if (lpService
->lpGroup
!= NULL
)
2573 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2575 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2577 /* FIXME: Add Dependencies length*/
2579 if (lpServiceStartName
!= NULL
)
2580 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2582 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2584 if (lpService
->lpDisplayName
!= NULL
)
2585 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2587 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2589 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2591 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2595 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2596 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2597 lpConfig
->dwStartType
= lpService
->dwStartType
;
2598 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2599 lpConfig
->dwTagId
= lpService
->dwTag
;
2601 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2603 if (lpImagePath
!= NULL
)
2605 wcscpy(lpStr
, lpImagePath
);
2609 wcscpy(lpStr
, lpEmptyString
);
2612 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2613 lpStr
+= (wcslen(lpStr
) + 1);
2615 if (lpService
->lpGroup
!= NULL
)
2617 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2621 wcscpy(lpStr
, lpEmptyString
);
2624 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2625 lpStr
+= (wcslen(lpStr
) + 1);
2627 /* FIXME: Append Dependencies */
2628 wcscpy(lpStr
, lpEmptyString
);
2630 lpStr
+= (wcslen(lpStr
) + 1);
2631 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2633 if (lpServiceStartName
!= NULL
)
2635 wcscpy(lpStr
, lpServiceStartName
);
2639 wcscpy(lpStr
, lpEmptyString
);
2642 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2643 lpStr
+= (wcslen(lpStr
) + 1);
2645 if (lpService
->lpDisplayName
!= NULL
)
2647 wcscpy(lpStr
, lpService
->lpDisplayName
);
2651 wcscpy(lpStr
, lpEmptyString
);
2654 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2657 if (pcbBytesNeeded
!= NULL
)
2658 *pcbBytesNeeded
= dwRequiredSize
;
2661 if (lpImagePath
!= NULL
)
2662 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2664 if (lpServiceStartName
!= NULL
)
2665 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2667 if (hServiceKey
!= NULL
)
2668 RegCloseKey(hServiceKey
);
2670 /* FIXME: Unlock the service database */
2672 DPRINT("RQueryServiceConfigW() done\n");
2679 DWORD
RQueryServiceLockStatusW(
2680 SC_RPC_HANDLE hSCManager
,
2681 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2683 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2686 return ERROR_CALL_NOT_IMPLEMENTED
;
2691 DWORD
RStartServiceW(
2692 SC_RPC_HANDLE hService
,
2694 LPSTRING_PTRSW argv
)
2696 DWORD dwError
= ERROR_SUCCESS
;
2697 PSERVICE_HANDLE hSvc
;
2698 PSERVICE lpService
= NULL
;
2700 DPRINT("RStartServiceW() called\n");
2703 return ERROR_SHUTDOWN_IN_PROGRESS
;
2705 hSvc
= (PSERVICE_HANDLE
)hService
;
2706 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2708 DPRINT1("Invalid handle tag!\n");
2709 return ERROR_INVALID_HANDLE
;
2712 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2715 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2716 return ERROR_ACCESS_DENIED
;
2719 lpService
= hSvc
->ServiceEntry
;
2720 if (lpService
== NULL
)
2722 DPRINT1("lpService == NULL!\n");
2723 return ERROR_INVALID_HANDLE
;
2726 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2727 return ERROR_SERVICE_DISABLED
;
2729 if (lpService
->bDeleted
)
2730 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2737 /* Start the service */
2738 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2745 DWORD
RGetServiceDisplayNameW(
2746 SC_RPC_HANDLE hSCManager
,
2747 LPCWSTR lpServiceName
,
2748 LPWSTR lpDisplayName
,
2751 // PMANAGER_HANDLE hManager;
2756 DPRINT("RGetServiceDisplayNameW() called\n");
2757 DPRINT("hSCManager = %p\n", hSCManager
);
2758 DPRINT("lpServiceName: %S\n", lpServiceName
);
2759 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2760 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2762 // hManager = (PMANAGER_HANDLE)hSCManager;
2763 // if (hManager->Handle.Tag != MANAGER_TAG)
2765 // DPRINT1("Invalid manager handle!\n");
2766 // return ERROR_INVALID_HANDLE;
2769 /* Get service database entry */
2770 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2771 if (lpService
== NULL
)
2773 DPRINT1("Could not find a service!\n");
2775 /* If the service could not be found and lpcchBuffer is less than 2, windows
2776 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2777 if (*lpcchBuffer
< 2)
2780 if (lpDisplayName
!= NULL
)
2782 *lpDisplayName
= '\0';
2786 return ERROR_SERVICE_DOES_NOT_EXIST
;
2789 if (!lpService
->lpDisplayName
)
2791 dwLength
= wcslen(lpService
->lpServiceName
);
2793 if (lpDisplayName
!= NULL
&&
2794 *lpcchBuffer
> dwLength
)
2796 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2801 dwLength
= wcslen(lpService
->lpDisplayName
);
2803 if (lpDisplayName
!= NULL
&&
2804 *lpcchBuffer
> dwLength
)
2806 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2810 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2812 *lpcchBuffer
= dwLength
;
2819 DWORD
RGetServiceKeyNameW(
2820 SC_RPC_HANDLE hSCManager
,
2821 LPCWSTR lpDisplayName
,
2822 LPWSTR lpServiceName
,
2825 // PMANAGER_HANDLE hManager;
2830 DPRINT("RGetServiceKeyNameW() called\n");
2831 DPRINT("hSCManager = %p\n", hSCManager
);
2832 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2833 DPRINT("lpServiceName: %p\n", lpServiceName
);
2834 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2836 // hManager = (PMANAGER_HANDLE)hSCManager;
2837 // if (hManager->Handle.Tag != MANAGER_TAG)
2839 // DPRINT1("Invalid manager handle!\n");
2840 // return ERROR_INVALID_HANDLE;
2843 /* Get service database entry */
2844 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2845 if (lpService
== NULL
)
2847 DPRINT1("Could not find a service!\n");
2849 /* If the service could not be found and lpcchBuffer is less than 2, windows
2850 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2851 if (*lpcchBuffer
< 2)
2854 if (lpServiceName
!= NULL
)
2856 *lpServiceName
= '\0';
2860 return ERROR_SERVICE_DOES_NOT_EXIST
;
2863 dwLength
= wcslen(lpService
->lpServiceName
);
2865 if (lpServiceName
!= NULL
&&
2866 *lpcchBuffer
> dwLength
)
2868 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2869 *lpcchBuffer
= dwLength
;
2870 return ERROR_SUCCESS
;
2873 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2875 *lpcchBuffer
= dwLength
;
2882 DWORD
RI_ScSetServiceBitsA(
2883 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
2884 DWORD dwServiceBits
,
2886 int bUpdateImmediately
,
2890 return ERROR_CALL_NOT_IMPLEMENTED
;
2895 DWORD
RChangeServiceConfigA(
2896 SC_RPC_HANDLE hService
,
2897 DWORD dwServiceType
,
2899 DWORD dwErrorControl
,
2900 LPSTR lpBinaryPathName
,
2901 LPSTR lpLoadOrderGroup
,
2903 LPSTR lpDependencies
,
2905 LPSTR lpServiceStartName
,
2908 LPSTR lpDisplayName
)
2910 DWORD dwError
= ERROR_SUCCESS
;
2911 PSERVICE_HANDLE hSvc
;
2912 PSERVICE lpService
= NULL
;
2913 HKEY hServiceKey
= NULL
;
2914 LPWSTR lpDisplayNameW
= NULL
;
2915 // LPWSTR lpBinaryPathNameW = NULL;
2916 LPWSTR lpLoadOrderGroupW
= NULL
;
2917 LPWSTR lpDependenciesW
= NULL
;
2918 // LPWSTR lpPasswordW = NULL;
2920 DPRINT("RChangeServiceConfigA() called\n");
2921 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2922 DPRINT("dwStartType = %lu\n", dwStartType
);
2923 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2924 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2925 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2926 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2929 return ERROR_SHUTDOWN_IN_PROGRESS
;
2931 hSvc
= (PSERVICE_HANDLE
)hService
;
2932 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2934 DPRINT1("Invalid handle tag!\n");
2935 return ERROR_INVALID_HANDLE
;
2938 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2939 SERVICE_CHANGE_CONFIG
))
2941 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2942 return ERROR_ACCESS_DENIED
;
2945 lpService
= hSvc
->ServiceEntry
;
2946 if (lpService
== NULL
)
2948 DPRINT1("lpService == NULL!\n");
2949 return ERROR_INVALID_HANDLE
;
2952 /* FIXME: Lock database exclusively */
2954 if (lpService
->bDeleted
)
2956 /* FIXME: Unlock database */
2957 DPRINT1("The service has already been marked for delete!\n");
2958 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2961 /* Open the service key */
2962 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2965 if (dwError
!= ERROR_SUCCESS
)
2968 /* Write service data to the registry */
2970 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2972 /* Set the display name */
2973 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2975 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2976 if (lpDisplayNameW
== NULL
)
2978 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2982 MultiByteToWideChar(CP_ACP
,
2987 strlen(lpDisplayName
) + 1);
2989 RegSetValueExW(hServiceKey
,
2993 (LPBYTE
)lpDisplayNameW
,
2994 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2996 /* Update lpService->lpDisplayName */
2997 if (lpService
->lpDisplayName
)
2998 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3000 lpService
->lpDisplayName
= lpDisplayNameW
;
3003 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3005 /* Set the service type */
3006 dwError
= RegSetValueExW(hServiceKey
,
3010 (LPBYTE
)&dwServiceType
,
3012 if (dwError
!= ERROR_SUCCESS
)
3015 lpService
->Status
.dwServiceType
= dwServiceType
;
3018 if (dwStartType
!= SERVICE_NO_CHANGE
)
3020 /* Set the start value */
3021 dwError
= RegSetValueExW(hServiceKey
,
3025 (LPBYTE
)&dwStartType
,
3027 if (dwError
!= ERROR_SUCCESS
)
3030 lpService
->dwStartType
= dwStartType
;
3033 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3035 /* Set the error control value */
3036 dwError
= RegSetValueExW(hServiceKey
,
3040 (LPBYTE
)&dwErrorControl
,
3042 if (dwError
!= ERROR_SUCCESS
)
3045 lpService
->dwErrorControl
= dwErrorControl
;
3049 /* FIXME: set the new ImagePath value */
3051 /* Set the image path */
3052 if (dwServiceType
& SERVICE_WIN32
)
3054 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3056 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3057 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, wcslen(lpBinaryPathNameW
)+1);
3058 dwError
= RegSetValueExW(hServiceKey
,
3062 (LPBYTE
)lpBinaryPathNameW
,
3063 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3064 if (dwError
!= ERROR_SUCCESS
)
3068 else if (dwServiceType
& SERVICE_DRIVER
)
3070 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3072 dwError
= RegSetValueExW(hServiceKey
,
3076 (LPBYTE
)lpImagePath
,
3077 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3078 if (dwError
!= ERROR_SUCCESS
)
3084 /* Set the group name */
3085 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3087 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3089 (strlen(lpLoadOrderGroup
)+1) * sizeof(WCHAR
));
3090 if (lpLoadOrderGroupW
== NULL
)
3092 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3096 MultiByteToWideChar(CP_ACP
,
3101 wcslen(lpLoadOrderGroupW
) + 1);
3103 dwError
= RegSetValueExW(hServiceKey
,
3107 (LPBYTE
)lpLoadOrderGroupW
,
3108 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3109 if (dwError
!= ERROR_SUCCESS
)
3112 /* FIXME: Update lpService->lpServiceGroup */
3114 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3117 if (lpdwTagId
!= NULL
)
3119 dwError
= ScmAssignNewTag(lpService
);
3120 if (dwError
!= ERROR_SUCCESS
)
3123 dwError
= RegSetValueExW(hServiceKey
,
3127 (LPBYTE
)&lpService
->dwTag
,
3129 if (dwError
!= ERROR_SUCCESS
)
3132 *lpdwTagId
= lpService
->dwTag
;
3135 /* Write dependencies */
3136 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3138 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3140 (strlen(lpDependencies
)+1) * sizeof(WCHAR
));
3141 if (lpDependenciesW
== NULL
)
3143 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3147 MultiByteToWideChar(CP_ACP
,
3152 wcslen(lpDependenciesW
)+1);
3154 dwError
= ScmWriteDependencies(hServiceKey
,
3155 (LPWSTR
)lpDependenciesW
,
3158 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3161 if (lpPassword
!= NULL
)
3163 /* FIXME: Write password */
3166 /* FIXME: Unlock database */
3169 if (hServiceKey
!= NULL
)
3170 RegCloseKey(hServiceKey
);
3172 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3179 DWORD
RCreateServiceA(
3180 SC_RPC_HANDLE hSCManager
,
3181 LPSTR lpServiceName
,
3182 LPSTR lpDisplayName
,
3183 DWORD dwDesiredAccess
,
3184 DWORD dwServiceType
,
3186 DWORD dwErrorControl
,
3187 LPSTR lpBinaryPathName
,
3188 LPSTR lpLoadOrderGroup
,
3190 LPBYTE lpDependencies
,
3192 LPSTR lpServiceStartName
,
3195 LPSC_RPC_HANDLE lpServiceHandle
)
3198 return ERROR_CALL_NOT_IMPLEMENTED
;
3203 DWORD
REnumDependentServicesA(
3204 SC_RPC_HANDLE hService
,
3205 DWORD dwServiceState
,
3208 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3209 LPBOUNDED_DWORD_256K lpServicesReturned
)
3211 DWORD dwError
= ERROR_SUCCESS
;
3212 DWORD dwServicesReturned
= 0;
3213 DWORD dwServiceCount
;
3214 HKEY hServicesKey
= NULL
;
3215 LPSC_RPC_HANDLE hSCObject
;
3216 PSERVICE_HANDLE hSvc
;
3217 PSERVICE lpService
= NULL
;
3218 PSERVICE
*lpServicesArray
= NULL
;
3219 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3222 *pcbBytesNeeded
= 0;
3223 *lpServicesReturned
= 0;
3225 DPRINT("REnumDependentServicesA() called\n");
3227 hSCObject
= &hService
;
3228 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3229 lpService
= hSvc
->ServiceEntry
;
3231 /* Check access rights */
3232 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3233 SC_MANAGER_ENUMERATE_SERVICE
))
3235 DPRINT1("Insufficient access rights! 0x%lx\n",
3236 hSvc
->Handle
.DesiredAccess
);
3237 return ERROR_ACCESS_DENIED
;
3240 /* Open the Services Reg key */
3241 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3242 L
"System\\CurrentControlSet\\Services",
3247 if (dwError
!= ERROR_SUCCESS
) return dwError
;
3249 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3250 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3251 are the same for both. Verified in WINXP. */
3253 /* First determine the bytes needed and get the number of dependent services*/
3254 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3259 &dwServicesReturned
);
3260 if (dwError
!= ERROR_SUCCESS
)
3263 /* If buffer size is less than the bytes needed or pointer is null*/
3264 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3266 dwError
= ERROR_MORE_DATA
;
3270 /* Allocate memory for array of service pointers */
3271 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3273 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3274 if (!lpServicesArray
)
3276 DPRINT1("Could not allocate a buffer!!\n");
3277 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3281 dwServicesReturned
= 0;
3282 *pcbBytesNeeded
= 0;
3284 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3289 &dwServicesReturned
);
3290 if (dwError
!= ERROR_SUCCESS
)
3295 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3296 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3298 /* Copy EnumDepenedentService to Buffer */
3299 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3301 lpService
= lpServicesArray
[dwServiceCount
];
3303 /* Copy the status info */
3304 memcpy(&lpServicesPtr
->ServiceStatus
,
3306 sizeof(SERVICE_STATUS
));
3308 /* Copy display name */
3309 WideCharToMultiByte(CP_ACP
,
3311 lpService
->lpDisplayName
,
3314 wcslen(lpService
->lpDisplayName
),
3317 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3318 lpStr
+= strlen(lpStr
) + 1;
3320 /* Copy service name */
3321 WideCharToMultiByte(CP_ACP
,
3323 lpService
->lpServiceName
,
3326 wcslen(lpService
->lpServiceName
),
3329 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3330 lpStr
+= strlen(lpStr
) + 1;
3335 *lpServicesReturned
= dwServicesReturned
;
3338 if (lpServicesArray
)
3339 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3341 RegCloseKey(hServicesKey
);
3343 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3350 DWORD
REnumServicesStatusA(
3351 SC_RPC_HANDLE hSCManager
,
3352 DWORD dwServiceType
,
3353 DWORD dwServiceState
,
3356 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3357 LPBOUNDED_DWORD_256K lpServicesReturned
,
3358 LPBOUNDED_DWORD_256K lpResumeHandle
)
3360 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3361 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3362 LPWSTR lpStringPtrW
;
3365 DWORD dwServiceCount
;
3367 DPRINT("REnumServicesStatusA() called\n");
3369 if ((dwBufSize
> 0) && (lpBuffer
))
3371 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3374 DPRINT1("Failed to allocate buffer!\n");
3375 return ERROR_NOT_ENOUGH_MEMORY
;
3379 dwError
= REnumServicesStatusW(//BindingHandle,
3383 (LPBYTE
)lpStatusPtrW
,
3389 /* if no services were returned then we are Done */
3390 if (*lpServicesReturned
== 0) goto Done
;
3392 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3393 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3394 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3395 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3396 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3398 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3400 /* Copy the service name */
3401 WideCharToMultiByte(CP_ACP
,
3406 wcslen(lpStringPtrW
),
3410 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3411 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3412 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3414 /* Copy the display name */
3415 WideCharToMultiByte(CP_ACP
,
3420 wcslen(lpStringPtrW
),
3424 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3425 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3426 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3428 /* Copy the status information */
3429 memcpy(&lpStatusPtrA
->ServiceStatus
,
3430 &lpStatusPtrW
->ServiceStatus
,
3431 sizeof(SERVICE_STATUS
));
3437 if (lpStatusPtrW
) HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3439 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3446 DWORD
ROpenSCManagerA(
3447 LPSTR lpMachineName
,
3448 LPSTR lpDatabaseName
,
3449 DWORD dwDesiredAccess
,
3450 LPSC_RPC_HANDLE lpScHandle
)
3452 UNICODE_STRING MachineName
;
3453 UNICODE_STRING DatabaseName
;
3456 DPRINT("ROpenSCManagerA() called\n");
3459 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3463 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3466 dwError
= ROpenSCManagerW(//BindingHandle,
3467 lpMachineName
? MachineName
.Buffer
: NULL
,
3468 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3473 RtlFreeUnicodeString(&MachineName
);
3476 RtlFreeUnicodeString(&DatabaseName
);
3483 DWORD
ROpenServiceA(
3484 SC_RPC_HANDLE hSCManager
,
3485 LPSTR lpServiceName
,
3486 DWORD dwDesiredAccess
,
3487 LPSC_RPC_HANDLE lpServiceHandle
)
3489 UNICODE_STRING ServiceName
;
3492 DPRINT("ROpenServiceA() called\n");
3495 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3498 dwError
= ROpenServiceW(//BindingHandle,
3500 lpServiceName
? ServiceName
.Buffer
: NULL
,
3505 RtlFreeUnicodeString(&ServiceName
);
3512 DWORD
RQueryServiceConfigA(
3513 SC_RPC_HANDLE hService
,
3514 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3516 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3518 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3519 DWORD dwError
= ERROR_SUCCESS
;
3520 PSERVICE_HANDLE hSvc
;
3521 PSERVICE lpService
= NULL
;
3522 HKEY hServiceKey
= NULL
;
3523 LPWSTR lpImagePath
= NULL
;
3524 LPWSTR lpServiceStartName
= NULL
;
3525 DWORD dwRequiredSize
;
3526 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3527 CHAR lpEmptyString
[]={0,0};
3530 DPRINT("RQueryServiceConfigA() called\n");
3533 return ERROR_SHUTDOWN_IN_PROGRESS
;
3535 hSvc
= (PSERVICE_HANDLE
)hService
;
3536 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3538 DPRINT1("Invalid handle tag!\n");
3539 return ERROR_INVALID_HANDLE
;
3542 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3543 SERVICE_QUERY_CONFIG
))
3545 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3546 return ERROR_ACCESS_DENIED
;
3549 lpService
= hSvc
->ServiceEntry
;
3550 if (lpService
== NULL
)
3552 DPRINT1("lpService == NULL!\n");
3553 return ERROR_INVALID_HANDLE
;
3556 /* FIXME: Lock the service database shared */
3558 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3561 if (dwError
!= ERROR_SUCCESS
)
3564 dwError
= ScmReadString(hServiceKey
,
3567 if (dwError
!= ERROR_SUCCESS
)
3570 ScmReadString(hServiceKey
,
3572 &lpServiceStartName
);
3574 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3576 if (lpImagePath
!= NULL
)
3577 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3579 dwRequiredSize
+= 2;
3581 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3582 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3584 dwRequiredSize
+= 2;
3586 /* FIXME: Add Dependencies length*/
3587 dwRequiredSize
+= 2;
3589 if (lpServiceStartName
!= NULL
)
3590 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3592 dwRequiredSize
+= 2;
3594 if (lpService
->lpDisplayName
!= NULL
)
3595 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3597 dwRequiredSize
+= 2;
3599 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3601 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3605 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3606 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3607 lpConfig
->dwStartType
= lpService
->dwStartType
;
3608 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3609 lpConfig
->dwTagId
= lpService
->dwTag
;
3611 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3613 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3618 WideCharToMultiByte(CP_ACP
,
3623 wcslen(lpImagePath
)+1,
3629 strcpy(lpStr
, lpEmptyString
);
3632 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3633 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3635 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
3637 WideCharToMultiByte(CP_ACP
,
3639 lpService
->lpGroup
->lpGroupName
,
3642 wcslen(lpService
->lpGroup
->lpGroupName
)+1,
3648 strcpy(lpStr
, lpEmptyString
);
3651 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3652 lpStr
+= (strlen(lpStr
) + 1);
3654 /* FIXME: Append Dependencies */
3655 strcpy(lpStr
, lpEmptyString
);
3657 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3658 lpStr
+= (strlen(lpStr
) + 1);
3660 if (lpServiceStartName
)
3662 WideCharToMultiByte(CP_ACP
,
3667 wcslen(lpServiceStartName
)+1,
3673 strcpy(lpStr
, lpEmptyString
);
3676 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3677 lpStr
+= (strlen(lpStr
) + 1);
3679 if (lpService
->lpDisplayName
)
3681 WideCharToMultiByte(CP_ACP
,
3683 lpService
->lpDisplayName
,
3686 wcslen(lpService
->lpDisplayName
)+1,
3692 strcpy(lpStr
, lpEmptyString
);
3695 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3698 if (pcbBytesNeeded
!= NULL
)
3699 *pcbBytesNeeded
= dwRequiredSize
;
3702 if (lpImagePath
!= NULL
)
3703 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3705 if (lpServiceStartName
!= NULL
)
3706 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3708 if (hServiceKey
!= NULL
)
3709 RegCloseKey(hServiceKey
);
3711 /* FIXME: Unlock the service database */
3713 DPRINT("RQueryServiceConfigA() done\n");
3720 DWORD
RQueryServiceLockStatusA(
3721 SC_RPC_HANDLE hSCManager
,
3722 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
3724 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3727 return ERROR_CALL_NOT_IMPLEMENTED
;
3732 DWORD
RStartServiceA(
3733 SC_RPC_HANDLE hService
,
3735 LPSTRING_PTRSA argv
)
3737 DWORD dwError
= ERROR_SUCCESS
;
3738 PSERVICE_HANDLE hSvc
;
3739 PSERVICE lpService
= NULL
;
3741 DPRINT1("RStartServiceA() called\n");
3744 return ERROR_SHUTDOWN_IN_PROGRESS
;
3746 hSvc
= (PSERVICE_HANDLE
)hService
;
3747 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3749 DPRINT1("Invalid handle tag!\n");
3750 return ERROR_INVALID_HANDLE
;
3753 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3756 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3757 return ERROR_ACCESS_DENIED
;
3760 lpService
= hSvc
->ServiceEntry
;
3761 if (lpService
== NULL
)
3763 DPRINT1("lpService == NULL!\n");
3764 return ERROR_INVALID_HANDLE
;
3767 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3768 return ERROR_SERVICE_DISABLED
;
3770 if (lpService
->bDeleted
)
3771 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3773 /* FIXME: Convert argument vector to Unicode */
3775 /* Start the service */
3776 dwError
= ScmStartService(lpService
, 0, NULL
);
3778 /* FIXME: Free argument vector */
3785 DWORD
RGetServiceDisplayNameA(
3786 SC_RPC_HANDLE hSCManager
,
3787 LPCSTR lpServiceName
,
3788 LPSTR lpDisplayName
,
3789 LPBOUNDED_DWORD_4K lpcchBuffer
)
3791 // PMANAGER_HANDLE hManager;
3792 PSERVICE lpService
= NULL
;
3795 LPWSTR lpServiceNameW
;
3797 DPRINT("RGetServiceDisplayNameA() called\n");
3798 DPRINT("hSCManager = %p\n", hSCManager
);
3799 DPRINT("lpServiceName: %s\n", lpServiceName
);
3800 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3801 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3803 // hManager = (PMANAGER_HANDLE)hSCManager;
3804 // if (hManager->Handle.Tag != MANAGER_TAG)
3806 // DPRINT1("Invalid manager handle!\n");
3807 // return ERROR_INVALID_HANDLE;
3810 if (lpServiceName
!= NULL
)
3812 dwLength
= strlen(lpServiceName
) + 1;
3813 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
3815 dwLength
* sizeof(WCHAR
));
3816 if (!lpServiceNameW
)
3817 return ERROR_NOT_ENOUGH_MEMORY
;
3819 MultiByteToWideChar(CP_ACP
,
3826 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
3828 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3831 if (lpService
== NULL
)
3833 DPRINT1("Could not find a service!\n");
3835 /* If the service could not be found and lpcchBuffer is 0, windows
3836 puts null in lpDisplayName and puts 1 in lpcchBuffer */
3837 if (*lpcchBuffer
== 0)
3840 if (lpDisplayName
!= NULL
)
3842 *lpDisplayName
= '\0';
3845 return ERROR_SERVICE_DOES_NOT_EXIST
;
3848 if (!lpService
->lpDisplayName
)
3850 dwLength
= wcslen(lpService
->lpServiceName
);
3851 if (lpDisplayName
!= NULL
&&
3852 *lpcchBuffer
> dwLength
)
3854 WideCharToMultiByte(CP_ACP
,
3856 lpService
->lpServiceName
,
3857 wcslen(lpService
->lpServiceName
),
3862 return ERROR_SUCCESS
;
3867 dwLength
= wcslen(lpService
->lpDisplayName
);
3868 if (lpDisplayName
!= NULL
&&
3869 *lpcchBuffer
> dwLength
)
3871 WideCharToMultiByte(CP_ACP
,
3873 lpService
->lpDisplayName
,
3874 wcslen(lpService
->lpDisplayName
),
3879 return ERROR_SUCCESS
;
3883 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3885 *lpcchBuffer
= dwLength
* 2;
3892 DWORD
RGetServiceKeyNameA(
3893 SC_RPC_HANDLE hSCManager
,
3894 LPCSTR lpDisplayName
,
3895 LPSTR lpServiceName
,
3896 LPBOUNDED_DWORD_4K lpcchBuffer
)
3901 LPWSTR lpDisplayNameW
;
3903 DPRINT("RGetServiceKeyNameA() called\n");
3904 DPRINT("hSCManager = %p\n", hSCManager
);
3905 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
3906 DPRINT("lpServiceName: %p\n", lpServiceName
);
3907 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3909 dwLength
= strlen(lpDisplayName
) + 1;
3910 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3912 dwLength
* sizeof(WCHAR
));
3913 if (!lpDisplayNameW
)
3914 return ERROR_NOT_ENOUGH_MEMORY
;
3916 MultiByteToWideChar(CP_ACP
,
3923 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
3925 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3927 if (lpService
== NULL
)
3929 DPRINT1("Could not find the service!\n");
3931 /* If the service could not be found and lpcchBuffer is 0,
3932 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
3933 if (*lpcchBuffer
== 0)
3936 if (lpServiceName
!= NULL
)
3938 *lpServiceName
= '\0';
3942 return ERROR_SERVICE_DOES_NOT_EXIST
;
3945 dwLength
= wcslen(lpService
->lpServiceName
);
3946 if (lpServiceName
!= NULL
&&
3947 *lpcchBuffer
> dwLength
)
3949 WideCharToMultiByte(CP_ACP
,
3951 lpService
->lpServiceName
,
3952 wcslen(lpService
->lpServiceName
),
3957 return ERROR_SUCCESS
;
3960 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3962 *lpcchBuffer
= dwLength
* 2;
3969 DWORD
RI_ScGetCurrentGroupStateW(
3970 SC_RPC_HANDLE hSCManager
,
3971 LPWSTR lpLoadOrderGroup
,
3975 return ERROR_CALL_NOT_IMPLEMENTED
;
3980 DWORD
REnumServiceGroupW(
3981 SC_RPC_HANDLE hSCManager
,
3982 DWORD dwServiceType
,
3983 DWORD dwServiceState
,
3986 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3987 LPBOUNDED_DWORD_256K lpServicesReturned
,
3988 LPBOUNDED_DWORD_256K lpResumeIndex
,
3989 LPCWSTR pszGroupName
)
3992 return ERROR_CALL_NOT_IMPLEMENTED
;
3997 // WARNING: This function is untested
4000 DWORD
RChangeServiceConfig2A(
4001 SC_RPC_HANDLE hService
,
4002 SC_RPC_CONFIG_INFOA Info
)
4004 SC_RPC_CONFIG_INFOW InfoW
;
4005 DWORD dwRet
, dwLength
;
4008 DPRINT("RChangeServiceConfig2A() called\n");
4009 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4011 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4013 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4015 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4016 LPSERVICE_DESCRIPTIONA lpServiceDescriptonA
;
4018 lpServiceDescriptonA
= Info
.psd
;
4020 ///if (lpServiceDescriptonA &&
4021 ///lpServiceDescriptonA->lpDescription)
4023 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4025 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4027 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4028 if (!lpServiceDescriptonW
)
4030 return ERROR_NOT_ENOUGH_MEMORY
;
4033 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4035 MultiByteToWideChar(CP_ACP
,
4039 lpServiceDescriptonW
->lpDescription
,
4042 ptr
= lpServiceDescriptonW
;
4043 InfoW
.psd
= lpServiceDescriptonW
;
4046 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4048 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4049 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4050 DWORD dwRebootLen
= 0;
4051 DWORD dwCommandLen
= 0;
4053 lpServiceFailureActionsA
= Info
.psfa
;
4055 if (lpServiceFailureActionsA
)
4057 if (lpServiceFailureActionsA
->lpRebootMsg
)
4059 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4061 if (lpServiceFailureActionsA
->lpCommand
)
4063 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4065 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4067 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4070 if (!lpServiceFailureActionsW
)
4072 return ERROR_NOT_ENOUGH_MEMORY
;
4075 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4076 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4077 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4079 if (lpServiceFailureActionsA
->lpRebootMsg
)
4081 MultiByteToWideChar(CP_ACP
,
4083 lpServiceFailureActionsA
->lpRebootMsg
,
4085 lpServiceFailureActionsW
->lpRebootMsg
,
4089 if (lpServiceFailureActionsA
->lpCommand
)
4091 MultiByteToWideChar(CP_ACP
,
4093 lpServiceFailureActionsA
->lpCommand
,
4095 lpServiceFailureActionsW
->lpCommand
,
4099 ptr
= lpServiceFailureActionsW
;
4103 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4105 HeapFree(GetProcessHeap(), 0, ptr
);
4112 DWORD
RChangeServiceConfig2W(
4113 SC_RPC_HANDLE hService
,
4114 SC_RPC_CONFIG_INFOW Info
)
4116 DWORD dwError
= ERROR_SUCCESS
;
4117 PSERVICE_HANDLE hSvc
;
4118 PSERVICE lpService
= NULL
;
4119 HKEY hServiceKey
= NULL
;
4121 DPRINT("RChangeServiceConfig2W() called\n");
4122 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4125 return ERROR_SHUTDOWN_IN_PROGRESS
;
4127 hSvc
= (PSERVICE_HANDLE
)hService
;
4128 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4130 DPRINT1("Invalid handle tag!\n");
4131 return ERROR_INVALID_HANDLE
;
4134 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4135 SERVICE_CHANGE_CONFIG
))
4137 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4138 return ERROR_ACCESS_DENIED
;
4141 lpService
= hSvc
->ServiceEntry
;
4142 if (lpService
== NULL
)
4144 DPRINT1("lpService == NULL!\n");
4145 return ERROR_INVALID_HANDLE
;
4148 /* FIXME: Lock database exclusively */
4150 if (lpService
->bDeleted
)
4152 /* FIXME: Unlock database */
4153 DPRINT1("The service has already been marked for delete!\n");
4154 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4157 /* Open the service key */
4158 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4161 if (dwError
!= ERROR_SUCCESS
)
4164 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4166 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4168 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4169 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4171 if (lpServiceDescription
!= NULL
&&
4172 lpServiceDescription
->lpDescription
!= NULL
)
4174 DPRINT1("Setting value %S\n", lpServiceDescription
->lpDescription
);
4175 RegSetValueExW(hServiceKey
,
4179 (LPBYTE
)lpServiceDescription
->lpDescription
,
4180 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4182 if (dwError
!= ERROR_SUCCESS
)
4186 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4189 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4194 /* FIXME: Unlock database */
4195 if (hServiceKey
!= NULL
)
4196 RegCloseKey(hServiceKey
);
4198 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4205 DWORD
RQueryServiceConfig2A(
4206 SC_RPC_HANDLE hService
,
4210 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4212 DWORD dwError
= ERROR_SUCCESS
;
4213 PSERVICE_HANDLE hSvc
;
4214 PSERVICE lpService
= NULL
;
4215 HKEY hServiceKey
= NULL
;
4216 LPWSTR lpDescriptionW
= NULL
;
4217 LPSTR lpDescription
= NULL
;
4219 DPRINT1("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4222 return ERROR_INVALID_ADDRESS
;
4225 return ERROR_SHUTDOWN_IN_PROGRESS
;
4227 hSvc
= (PSERVICE_HANDLE
)hService
;
4228 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4230 DPRINT1("Invalid handle tag!\n");
4231 return ERROR_INVALID_HANDLE
;
4234 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4235 SERVICE_QUERY_CONFIG
))
4237 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4238 return ERROR_ACCESS_DENIED
;
4241 lpService
= hSvc
->ServiceEntry
;
4242 if (lpService
== NULL
)
4244 DPRINT1("lpService == NULL!\n");
4245 return ERROR_INVALID_HANDLE
;
4248 /* FIXME: Lock the service database shared */
4250 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4253 if (dwError
!= ERROR_SUCCESS
)
4256 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4258 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4261 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4263 dwError
= ScmReadString(hServiceKey
,
4266 if (dwError
== ERROR_SUCCESS
)
4268 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4271 if (cbBufSize
>= *pcbBytesNeeded
)
4274 if (dwError
== ERROR_SUCCESS
)
4276 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4278 WideCharToMultiByte(CP_ACP
,
4283 wcslen(lpDescriptionW
),
4286 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4290 lpServiceDescription
->lpDescription
= NULL
;
4296 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4300 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4303 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4308 if (lpDescription
!= NULL
)
4309 HeapFree(GetProcessHeap(), 0, lpDescription
);
4311 if (hServiceKey
!= NULL
)
4312 RegCloseKey(hServiceKey
);
4314 /* FIXME: Unlock database */
4316 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4323 DWORD
RQueryServiceConfig2W(
4324 SC_RPC_HANDLE hService
,
4328 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4330 DWORD dwError
= ERROR_SUCCESS
;
4331 PSERVICE_HANDLE hSvc
;
4332 PSERVICE lpService
= NULL
;
4333 HKEY hServiceKey
= NULL
;
4334 DWORD dwRequiredSize
;
4335 LPWSTR lpDescription
= NULL
;
4336 LPWSTR lpFailureCommand
= NULL
;
4337 LPWSTR lpRebootMessage
= NULL
;
4339 DPRINT("RQueryServiceConfig2W() called\n");
4342 return ERROR_INVALID_ADDRESS
;
4345 return ERROR_SHUTDOWN_IN_PROGRESS
;
4347 hSvc
= (PSERVICE_HANDLE
)hService
;
4348 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4350 DPRINT1("Invalid handle tag!\n");
4351 return ERROR_INVALID_HANDLE
;
4354 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4355 SERVICE_QUERY_CONFIG
))
4357 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4358 return ERROR_ACCESS_DENIED
;
4361 lpService
= hSvc
->ServiceEntry
;
4362 if (lpService
== NULL
)
4364 DPRINT1("lpService == NULL!\n");
4365 return ERROR_INVALID_HANDLE
;
4368 /* FIXME: Lock the service database shared */
4370 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4373 if (dwError
!= ERROR_SUCCESS
)
4376 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4378 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4381 dwError
= ScmReadString(hServiceKey
,
4384 if (dwError
!= ERROR_SUCCESS
)
4387 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4389 if (cbBufSize
< dwRequiredSize
)
4391 *pcbBytesNeeded
= dwRequiredSize
;
4392 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4396 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4397 wcscpy(lpStr
, lpDescription
);
4398 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4400 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4403 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
4407 dwError
= ScmReadString(hServiceKey
,
4411 dwError
= ScmReadString(hServiceKey
,
4415 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
4417 if (lpFailureCommand
)
4418 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
4420 if (lpRebootMessage
)
4421 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
4423 if (cbBufSize
< dwRequiredSize
)
4425 *pcbBytesNeeded
= dwRequiredSize
;
4426 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4430 lpFailureActions
->cActions
= 0;
4431 lpFailureActions
->dwResetPeriod
= 0;
4432 lpFailureActions
->lpCommand
= NULL
;
4433 lpFailureActions
->lpRebootMsg
= NULL
;
4434 lpFailureActions
->lpsaActions
= NULL
;
4436 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
4437 if (lpRebootMessage
)
4439 wcscpy(lpStr
, lpRebootMessage
);
4440 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
4441 lpStr
+= wcslen(lpRebootMessage
) + 1;
4444 if (lpFailureCommand
)
4446 wcscpy(lpStr
, lpFailureCommand
);
4447 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
4448 lpStr
+= wcslen(lpRebootMessage
) + 1;
4450 dwError
= STATUS_SUCCESS
;
4455 if (lpDescription
!= NULL
)
4456 HeapFree(GetProcessHeap(), 0, lpDescription
);
4458 if (lpRebootMessage
!= NULL
)
4459 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
4461 if (lpFailureCommand
!= NULL
)
4462 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
4464 if (hServiceKey
!= NULL
)
4465 RegCloseKey(hServiceKey
);
4467 /* FIXME: Unlock database */
4469 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4476 DWORD
RQueryServiceStatusEx(
4477 SC_RPC_HANDLE hService
,
4478 SC_STATUS_TYPE InfoLevel
,
4481 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4483 LPSERVICE_STATUS_PROCESS lpStatus
;
4484 PSERVICE_HANDLE hSvc
;
4487 DPRINT("RQueryServiceStatusEx() called\n");
4490 return ERROR_SHUTDOWN_IN_PROGRESS
;
4492 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4493 return ERROR_INVALID_LEVEL
;
4495 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4497 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4498 return ERROR_INSUFFICIENT_BUFFER
;
4500 hSvc
= (PSERVICE_HANDLE
)hService
;
4501 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4503 DPRINT1("Invalid handle tag!\n");
4504 return ERROR_INVALID_HANDLE
;
4507 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4508 SERVICE_QUERY_STATUS
))
4510 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4511 return ERROR_ACCESS_DENIED
;
4514 lpService
= hSvc
->ServiceEntry
;
4515 if (lpService
== NULL
)
4517 DPRINT1("lpService == NULL!\n");
4518 return ERROR_INVALID_HANDLE
;
4521 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4523 /* Return service status information */
4524 RtlCopyMemory(lpStatus
,
4526 sizeof(SERVICE_STATUS
));
4528 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
4529 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4531 return ERROR_SUCCESS
;
4536 DWORD
REnumServicesStatusExA(
4537 SC_RPC_HANDLE hSCManager
,
4538 SC_ENUM_TYPE InfoLevel
,
4539 DWORD dwServiceType
,
4540 DWORD dwServiceState
,
4543 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4544 LPBOUNDED_DWORD_256K lpServicesReturned
,
4545 LPBOUNDED_DWORD_256K lpResumeIndex
,
4546 LPCSTR pszGroupName
)
4548 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
4549 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
4550 LPWSTR lpStringPtrW
;
4552 LPWSTR pszGroupNameW
= NULL
;
4554 DWORD dwServiceCount
;
4556 DPRINT("REnumServicesStatusExA() called\n");
4560 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
4563 DPRINT1("Failed to allocate buffer!\n");
4564 return ERROR_NOT_ENOUGH_MEMORY
;
4566 MultiByteToWideChar(CP_ACP
,
4571 strlen(pszGroupName
) + 1);
4574 if ((cbBufSize
> 0) && (lpBuffer
))
4576 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
4579 DPRINT1("Failed to allocate buffer!\n");
4580 return ERROR_NOT_ENOUGH_MEMORY
;
4584 dwError
= REnumServicesStatusExW(hSCManager
,
4588 (LPBYTE
)lpStatusPtrW
,
4595 /* if no services were returned then we are Done */
4596 if (*lpServicesReturned
== 0) goto Done
;
4598 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
4599 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
4600 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
4601 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
4602 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4604 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
4606 /* Copy the service name */
4607 WideCharToMultiByte(CP_ACP
,
4612 wcslen(lpStringPtrW
),
4616 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4617 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4618 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4620 /* Copy the display name */
4621 WideCharToMultiByte(CP_ACP
,
4626 wcslen(lpStringPtrW
),
4630 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4631 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4632 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4634 /* Copy the status information */
4635 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
4636 &lpStatusPtrW
->ServiceStatusProcess
,
4637 sizeof(SERVICE_STATUS
));
4639 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
4640 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4645 if (pszGroupNameW
) HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
4647 if (lpStatusPtrW
) HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
4649 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
4656 DWORD
REnumServicesStatusExW(
4657 SC_RPC_HANDLE hSCManager
,
4658 SC_ENUM_TYPE InfoLevel
,
4659 DWORD dwServiceType
,
4660 DWORD dwServiceState
,
4663 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4664 LPBOUNDED_DWORD_256K lpServicesReturned
,
4665 LPBOUNDED_DWORD_256K lpResumeIndex
,
4666 LPCWSTR pszGroupName
)
4668 PMANAGER_HANDLE hManager
;
4670 DWORD dwError
= ERROR_SUCCESS
;
4671 PLIST_ENTRY ServiceEntry
;
4672 PSERVICE CurrentService
;
4674 DWORD dwRequiredSize
;
4675 DWORD dwServiceCount
;
4677 DWORD dwLastResumeCount
= 0;
4678 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
4681 DPRINT("REnumServicesStatusExW() called\n");
4684 return ERROR_SHUTDOWN_IN_PROGRESS
;
4686 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
4687 return ERROR_INVALID_LEVEL
;
4689 hManager
= (PMANAGER_HANDLE
)hSCManager
;
4690 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
4692 DPRINT1("Invalid manager handle!\n");
4693 return ERROR_INVALID_HANDLE
;
4696 *pcbBytesNeeded
= 0;
4697 *lpServicesReturned
= 0;
4699 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
4701 DPRINT1("Not a valid Service Type!\n");
4702 return ERROR_INVALID_PARAMETER
;
4705 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
4707 DPRINT1("Not a valid Service State!\n");
4708 return ERROR_INVALID_PARAMETER
;
4711 /* Check access rights */
4712 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4713 SC_MANAGER_ENUMERATE_SERVICE
))
4715 DPRINT1("Insufficient access rights! 0x%lx\n",
4716 hManager
->Handle
.DesiredAccess
);
4717 return ERROR_ACCESS_DENIED
;
4720 if (lpResumeIndex
) dwLastResumeCount
= *lpResumeIndex
;
4722 /* Lock the service list shared */
4724 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4725 if (lpService
== NULL
)
4727 dwError
= ERROR_SUCCESS
;
4734 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4735 ServiceEntry
!= &ServiceListHead
;
4736 ServiceEntry
= ServiceEntry
->Flink
)
4738 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4742 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4745 dwState
= SERVICE_ACTIVE
;
4746 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4747 dwState
= SERVICE_INACTIVE
;
4749 if ((dwState
& dwServiceState
) == 0)
4754 if (*pszGroupName
== 0)
4756 if (CurrentService
->lpGroup
!= NULL
)
4761 if ((CurrentService
->lpGroup
== NULL
) ||
4762 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4767 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4768 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4769 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4771 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4773 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
4774 dwRequiredSize
+= dwSize
;
4776 dwLastResumeCount
= CurrentService
->dwResumeCount
;
4780 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
4786 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
4787 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
4790 ServiceEntry
!= &ServiceListHead
;
4791 ServiceEntry
= ServiceEntry
->Flink
)
4793 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4797 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4800 dwState
= SERVICE_ACTIVE
;
4801 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4802 dwState
= SERVICE_INACTIVE
;
4804 if ((dwState
& dwServiceState
) == 0)
4809 if (*pszGroupName
== 0)
4811 if (CurrentService
->lpGroup
!= NULL
)
4816 if ((CurrentService
->lpGroup
== NULL
) ||
4817 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4822 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4823 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4824 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
4826 dwError
= ERROR_MORE_DATA
;
4829 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
4831 if (lpResumeIndex
) *lpResumeIndex
= dwLastResumeCount
;
4832 *lpServicesReturned
= dwServiceCount
;
4833 *pcbBytesNeeded
= dwRequiredSize
;
4835 /* If there was no services that matched */
4836 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
4838 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
4842 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
4843 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
4844 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4847 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4848 ServiceEntry
!= &ServiceListHead
;
4849 ServiceEntry
= ServiceEntry
->Flink
)
4851 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4855 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4858 dwState
= SERVICE_ACTIVE
;
4859 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4860 dwState
= SERVICE_INACTIVE
;
4862 if ((dwState
& dwServiceState
) == 0)
4867 if (*pszGroupName
== 0)
4869 if (CurrentService
->lpGroup
!= NULL
)
4874 if ((CurrentService
->lpGroup
== NULL
) ||
4875 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4880 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4881 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4882 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4884 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4886 /* Copy the service name */
4888 CurrentService
->lpServiceName
);
4889 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4890 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
4892 /* Copy the display name */
4894 CurrentService
->lpDisplayName
);
4895 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4896 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
4898 /* Copy the status information */
4899 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
4900 &CurrentService
->Status
,
4901 sizeof(SERVICE_STATUS
));
4902 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
4903 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4906 dwRequiredSize
+= dwSize
;
4916 *pcbBytesNeeded
= 0;
4917 if (lpResumeIndex
) *lpResumeIndex
= 0;
4921 /* Unlock the service list */
4923 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
4930 DWORD
RSendTSMessage(
4931 handle_t BindingHandle
) /* FIXME */
4934 return ERROR_CALL_NOT_IMPLEMENTED
;
4939 DWORD
RCreateServiceWOW64A(
4940 handle_t BindingHandle
,
4941 LPSTR lpServiceName
,
4942 LPSTR lpDisplayName
,
4943 DWORD dwDesiredAccess
,
4944 DWORD dwServiceType
,
4946 DWORD dwErrorControl
,
4947 LPSTR lpBinaryPathName
,
4948 LPSTR lpLoadOrderGroup
,
4950 LPBYTE lpDependencies
,
4952 LPSTR lpServiceStartName
,
4955 LPSC_RPC_HANDLE lpServiceHandle
)
4958 return ERROR_CALL_NOT_IMPLEMENTED
;
4963 DWORD
RCreateServiceWOW64W(
4964 handle_t BindingHandle
,
4965 LPWSTR lpServiceName
,
4966 LPWSTR lpDisplayName
,
4967 DWORD dwDesiredAccess
,
4968 DWORD dwServiceType
,
4970 DWORD dwErrorControl
,
4971 LPWSTR lpBinaryPathName
,
4972 LPWSTR lpLoadOrderGroup
,
4974 LPBYTE lpDependencies
,
4976 LPWSTR lpServiceStartName
,
4979 LPSC_RPC_HANDLE lpServiceHandle
)
4982 return ERROR_CALL_NOT_IMPLEMENTED
;
4987 DWORD
RQueryServiceTagInfo(
4988 handle_t BindingHandle
) /* FIXME */
4991 return ERROR_CALL_NOT_IMPLEMENTED
;
4996 DWORD
RNotifyServiceStatusChange(
4997 SC_RPC_HANDLE hService
,
4998 SC_RPC_NOTIFY_PARAMS NotifyParams
,
4999 GUID
*pClientProcessGuid
,
5000 GUID
*pSCMProcessGuid
,
5001 PBOOL pfCreateRemoteQueue
,
5002 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5005 return ERROR_CALL_NOT_IMPLEMENTED
;
5010 DWORD
RGetNotifyResults(
5011 SC_NOTIFY_RPC_HANDLE hNotify
,
5012 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5015 return ERROR_CALL_NOT_IMPLEMENTED
;
5020 DWORD
RCloseNotifyHandle(
5021 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5025 return ERROR_CALL_NOT_IMPLEMENTED
;
5030 DWORD
RControlServiceExA(
5031 SC_RPC_HANDLE hService
,
5036 return ERROR_CALL_NOT_IMPLEMENTED
;
5041 DWORD
RControlServiceExW(
5042 SC_RPC_HANDLE hService
,
5047 return ERROR_CALL_NOT_IMPLEMENTED
;
5052 DWORD
RSendPnPMessage(
5053 handle_t BindingHandle
) /* FIXME */
5056 return ERROR_CALL_NOT_IMPLEMENTED
;
5061 DWORD
RValidatePnPService(
5062 handle_t BindingHandle
) /* FIXME */
5065 return ERROR_CALL_NOT_IMPLEMENTED
;
5070 DWORD
ROpenServiceStatusHandle(
5071 handle_t BindingHandle
) /* FIXME */
5074 return ERROR_CALL_NOT_IMPLEMENTED
;
5080 handle_t BindingHandle
) /* FIXME */
5083 return ERROR_CALL_NOT_IMPLEMENTED
;
5087 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5089 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5093 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5095 HeapFree(GetProcessHeap(), 0, ptr
);
5099 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5104 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5109 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)