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
)
1286 dwError
= ScmSetServiceGroup(lpService
,
1288 if (dwError
!= ERROR_SUCCESS
)
1292 if (lpdwTagId
!= NULL
)
1294 dwError
= ScmAssignNewTag(lpService
);
1295 if (dwError
!= ERROR_SUCCESS
)
1298 dwError
= RegSetValueExW(hServiceKey
,
1302 (LPBYTE
)&lpService
->dwTag
,
1304 if (dwError
!= ERROR_SUCCESS
)
1307 *lpdwTagId
= lpService
->dwTag
;
1310 /* Write dependencies */
1311 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1313 dwError
= ScmWriteDependencies(hServiceKey
,
1314 (LPWSTR
)lpDependencies
,
1316 if (dwError
!= ERROR_SUCCESS
)
1320 if (lpPassword
!= NULL
)
1322 /* FIXME: Write password */
1325 /* FIXME: Unlock database */
1328 if (hServiceKey
!= NULL
)
1329 RegCloseKey(hServiceKey
);
1331 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1337 /* Create a path suitable for the bootloader out of the full path */
1339 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1341 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1344 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1345 OBJECT_ATTRIBUTES ObjectAttributes
;
1347 HANDLE SymbolicLinkHandle
;
1349 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1351 ServiceNameLen
= wcslen(CanonName
);
1353 /* First check, if it's already good */
1354 if (ServiceNameLen
> 12 &&
1355 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1357 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1358 if (*RelativeName
== NULL
)
1360 DPRINT1("Error allocating memory for boot driver name!\n");
1361 return ERROR_NOT_ENOUGH_MEMORY
;
1365 wcscpy(*RelativeName
, CanonName
);
1367 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1368 return ERROR_SUCCESS
;
1371 /* If it has %SystemRoot% prefix, substitute it to \System*/
1372 if (ServiceNameLen
> 13 &&
1373 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1375 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1376 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1378 if (*RelativeName
== NULL
)
1380 DPRINT1("Error allocating memory for boot driver name!\n");
1381 return ERROR_NOT_ENOUGH_MEMORY
;
1385 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1386 wcscat(*RelativeName
, CanonName
+ 13);
1388 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1389 return ERROR_SUCCESS
;
1392 /* Get buffer size needed for expanding env strings */
1393 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1395 if (BufferSize
<= 1)
1397 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1398 return ERROR_INVALID_ENVIRONMENT
;
1401 /* Allocate memory, since the size is known now */
1402 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1405 DPRINT1("Error allocating memory for boot driver name!\n");
1406 return ERROR_NOT_ENOUGH_MEMORY
;
1410 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1413 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1414 LocalFree(Expanded
);
1415 return ERROR_NOT_ENOUGH_MEMORY
;
1418 /* Convert to NY-style path */
1419 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1421 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1422 return ERROR_INVALID_ENVIRONMENT
;
1425 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1427 /* No need to keep the dos-path anymore */
1428 LocalFree(Expanded
);
1430 /* Copy it to the allocated place */
1431 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1434 DPRINT1("Error allocating memory for boot driver name!\n");
1435 return ERROR_NOT_ENOUGH_MEMORY
;
1438 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1439 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1440 Expanded
[ExpandedLen
] = 0;
1442 if (ServiceNameLen
> ExpandedLen
&&
1443 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1445 /* Only \SystemRoot\ is missing */
1446 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1447 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1448 if (*RelativeName
== NULL
)
1450 DPRINT1("Error allocating memory for boot driver name!\n");
1451 LocalFree(Expanded
);
1452 return ERROR_NOT_ENOUGH_MEMORY
;
1455 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1456 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1458 RtlFreeUnicodeString(&NtPathName
);
1459 return ERROR_SUCCESS
;
1462 /* The most complex case starts here */
1463 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1464 InitializeObjectAttributes(&ObjectAttributes
,
1466 OBJ_CASE_INSENSITIVE
,
1470 /* Open this symlink */
1471 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1473 if (NT_SUCCESS(Status
))
1475 LinkTarget
.Length
= 0;
1476 LinkTarget
.MaximumLength
= 0;
1478 DPRINT("Opened symbolic link object\n");
1480 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1481 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1483 /* Check if required buffer size is sane */
1484 if (BufferSize
> 0xFFFD)
1486 DPRINT1("Too large buffer required\n");
1489 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1490 LocalFree(Expanded
);
1491 return ERROR_NOT_ENOUGH_MEMORY
;
1494 /* Alloc the string */
1495 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1496 if (!LinkTarget
.Buffer
)
1498 DPRINT1("Unable to alloc buffer\n");
1499 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1500 LocalFree(Expanded
);
1501 return ERROR_NOT_ENOUGH_MEMORY
;
1504 /* Do a real query now */
1505 LinkTarget
.Length
= BufferSize
;
1506 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1508 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1509 if (NT_SUCCESS(Status
))
1511 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1513 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1514 if ((ServiceNameLen
> ExpandedLen
) &&
1515 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1517 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1518 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1520 if (*RelativeName
== NULL
)
1522 DPRINT1("Unable to alloc buffer\n");
1523 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1524 LocalFree(Expanded
);
1525 RtlFreeUnicodeString(&NtPathName
);
1526 return ERROR_NOT_ENOUGH_MEMORY
;
1529 /* Copy it over, substituting the first part
1531 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1532 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1535 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1536 LocalFree(Expanded
);
1537 RtlFreeUnicodeString(&NtPathName
);
1539 /* Return success */
1540 return ERROR_SUCCESS
;
1544 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1545 LocalFree(Expanded
);
1546 RtlFreeUnicodeString(&NtPathName
);
1547 return ERROR_INVALID_PARAMETER
;
1552 DPRINT1("Error, Status = %08X\n", Status
);
1553 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1554 LocalFree(Expanded
);
1555 RtlFreeUnicodeString(&NtPathName
);
1556 return ERROR_INVALID_PARAMETER
;
1561 DPRINT1("Error, Status = %08X\n", Status
);
1562 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1563 LocalFree(Expanded
);
1564 RtlFreeUnicodeString(&NtPathName
);
1565 return ERROR_INVALID_PARAMETER
;
1570 DPRINT1("Error, Status = %08X\n", Status
);
1571 LocalFree(Expanded
);
1572 return ERROR_INVALID_PARAMETER
;
1576 *RelativeName
= NULL
;
1577 return ERROR_INVALID_PARAMETER
;
1581 ScmCanonDriverImagePath(DWORD dwStartType
,
1582 const wchar_t *lpServiceName
,
1583 wchar_t **lpCanonName
)
1585 DWORD ServiceNameLen
, Result
;
1586 UNICODE_STRING NtServiceName
;
1587 WCHAR
*RelativeName
;
1588 const WCHAR
*SourceName
= lpServiceName
;
1590 /* Calculate the length of the service's name */
1591 ServiceNameLen
= wcslen(lpServiceName
);
1593 /* 12 is wcslen(L"\\SystemRoot\\") */
1594 if (ServiceNameLen
> 12 &&
1595 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1597 /* SystemRoot prefix is already included */
1599 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1601 if (*lpCanonName
== NULL
)
1603 DPRINT1("Error allocating memory for canonized service name!\n");
1604 return ERROR_NOT_ENOUGH_MEMORY
;
1607 /* If it's a boot-time driver, it must be systemroot relative */
1608 if (dwStartType
== SERVICE_BOOT_START
)
1612 wcscpy(*lpCanonName
, SourceName
);
1614 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1618 /* Check if it has %SystemRoot% (len=13) */
1619 if (ServiceNameLen
> 13 &&
1620 !_wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1622 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1623 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1625 if (*lpCanonName
== NULL
)
1627 DPRINT1("Error allocating memory for canonized service name!\n");
1628 return ERROR_NOT_ENOUGH_MEMORY
;
1631 /* If it's a boot-time driver, it must be systemroot relative */
1632 if (dwStartType
== SERVICE_BOOT_START
)
1633 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1635 wcscat(*lpCanonName
, lpServiceName
+ 13);
1637 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1641 /* Check if it's a relative path name */
1642 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1644 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1646 if (*lpCanonName
== NULL
)
1648 DPRINT1("Error allocating memory for canonized service name!\n");
1649 return ERROR_NOT_ENOUGH_MEMORY
;
1652 /* Just copy it over without changing */
1653 wcscpy(*lpCanonName
, lpServiceName
);
1658 /* It seems to be a DOS path, convert it */
1659 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1661 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1662 return ERROR_INVALID_PARAMETER
;
1665 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1667 if (*lpCanonName
== NULL
)
1669 DPRINT1("Error allocating memory for canonized service name!\n");
1670 RtlFreeUnicodeString(&NtServiceName
);
1671 return ERROR_NOT_ENOUGH_MEMORY
;
1674 /* Copy the string */
1675 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1677 /* The unicode string is not needed anymore */
1678 RtlFreeUnicodeString(&NtServiceName
);
1680 if (dwStartType
!= SERVICE_BOOT_START
)
1682 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1686 /* The service is boot-started, so must be relative */
1687 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1690 /* There is a problem, free name and return */
1691 LocalFree(*lpCanonName
);
1692 DPRINT1("Error converting named!\n");
1696 ASSERT(RelativeName
);
1698 /* Copy that string */
1699 wcscpy(*lpCanonName
, RelativeName
+ 12);
1701 /* Free the allocated buffer */
1702 LocalFree(RelativeName
);
1704 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1712 DWORD
RCreateServiceW(
1713 SC_RPC_HANDLE hSCManager
,
1714 LPCWSTR lpServiceName
,
1715 LPCWSTR lpDisplayName
,
1716 DWORD dwDesiredAccess
,
1717 DWORD dwServiceType
,
1719 DWORD dwErrorControl
,
1720 LPCWSTR lpBinaryPathName
,
1721 LPCWSTR lpLoadOrderGroup
,
1723 LPBYTE lpDependencies
,
1725 LPCWSTR lpServiceStartName
,
1728 LPSC_RPC_HANDLE lpServiceHandle
)
1730 PMANAGER_HANDLE hManager
;
1731 DWORD dwError
= ERROR_SUCCESS
;
1732 PSERVICE lpService
= NULL
;
1733 SC_HANDLE hServiceHandle
= NULL
;
1734 LPWSTR lpImagePath
= NULL
;
1735 HKEY hServiceKey
= NULL
;
1736 LPWSTR lpObjectName
;
1738 DPRINT("RCreateServiceW() called\n");
1739 DPRINT("lpServiceName = %S\n", lpServiceName
);
1740 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1741 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1742 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1743 DPRINT("dwStartType = %lu\n", dwStartType
);
1744 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1745 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1746 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1749 return ERROR_SHUTDOWN_IN_PROGRESS
;
1751 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1752 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1754 DPRINT1("Invalid manager handle!\n");
1755 return ERROR_INVALID_HANDLE
;
1758 /* Check access rights */
1759 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1760 SC_MANAGER_CREATE_SERVICE
))
1762 DPRINT1("Insufficient access rights! 0x%lx\n",
1763 hManager
->Handle
.DesiredAccess
);
1764 return ERROR_ACCESS_DENIED
;
1767 if (wcslen(lpServiceName
) == 0)
1769 return ERROR_INVALID_NAME
;
1772 if (wcslen(lpBinaryPathName
) == 0)
1774 return ERROR_INVALID_PARAMETER
;
1777 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1778 (lpServiceStartName
))
1780 return ERROR_INVALID_PARAMETER
;
1783 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1784 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1785 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1787 return ERROR_INVALID_PARAMETER
;
1790 if (dwStartType
> SERVICE_DISABLED
)
1792 return ERROR_INVALID_PARAMETER
;
1795 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1798 /* check if it is marked for deletion */
1799 if (lpService
->bDeleted
)
1800 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1801 /* Return Error exist */
1802 return ERROR_SERVICE_EXISTS
;
1805 if (lpDisplayName
!= NULL
&&
1806 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1807 return ERROR_DUPLICATE_SERVICE_NAME
;
1809 if (dwServiceType
& SERVICE_DRIVER
)
1811 dwError
= ScmCanonDriverImagePath(dwStartType
,
1814 if (dwError
!= ERROR_SUCCESS
)
1819 if (dwStartType
== SERVICE_BOOT_START
||
1820 dwStartType
== SERVICE_SYSTEM_START
)
1822 return ERROR_INVALID_PARAMETER
;
1826 /* Allocate a new service entry */
1827 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1829 if (dwError
!= ERROR_SUCCESS
)
1832 /* Fill the new service entry */
1833 lpService
->Status
.dwServiceType
= dwServiceType
;
1834 lpService
->dwStartType
= dwStartType
;
1835 lpService
->dwErrorControl
= dwErrorControl
;
1837 /* Fill the display name */
1838 if (lpDisplayName
!= NULL
&&
1839 *lpDisplayName
!= 0 &&
1840 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1842 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1843 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1844 if (lpService
->lpDisplayName
== NULL
)
1846 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1849 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1852 /* Assign the service to a group */
1853 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1855 dwError
= ScmSetServiceGroup(lpService
,
1857 if (dwError
!= ERROR_SUCCESS
)
1861 /* Assign a new tag */
1862 if (lpdwTagId
!= NULL
)
1864 dwError
= ScmAssignNewTag(lpService
);
1865 if (dwError
!= ERROR_SUCCESS
)
1869 /* Write service data to the registry */
1870 /* Create the service key */
1871 dwError
= ScmCreateServiceKey(lpServiceName
,
1874 if (dwError
!= ERROR_SUCCESS
)
1877 /* Set the display name */
1878 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1880 RegSetValueExW(hServiceKey
,
1884 (LPBYTE
)lpDisplayName
,
1885 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1888 /* Set the service type */
1889 dwError
= RegSetValueExW(hServiceKey
,
1893 (LPBYTE
)&dwServiceType
,
1895 if (dwError
!= ERROR_SUCCESS
)
1898 /* Set the start value */
1899 dwError
= RegSetValueExW(hServiceKey
,
1903 (LPBYTE
)&dwStartType
,
1905 if (dwError
!= ERROR_SUCCESS
)
1908 /* Set the error control value */
1909 dwError
= RegSetValueExW(hServiceKey
,
1913 (LPBYTE
)&dwErrorControl
,
1915 if (dwError
!= ERROR_SUCCESS
)
1918 /* Set the image path */
1919 if (dwServiceType
& SERVICE_WIN32
)
1921 dwError
= RegSetValueExW(hServiceKey
,
1925 (LPBYTE
)lpBinaryPathName
,
1926 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1927 if (dwError
!= ERROR_SUCCESS
)
1930 else if (dwServiceType
& SERVICE_DRIVER
)
1932 dwError
= RegSetValueExW(hServiceKey
,
1936 (LPBYTE
)lpImagePath
,
1937 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1938 if (dwError
!= ERROR_SUCCESS
)
1942 /* Set the group name */
1943 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1945 dwError
= RegSetValueExW(hServiceKey
,
1949 (LPBYTE
)lpLoadOrderGroup
,
1950 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1951 if (dwError
!= ERROR_SUCCESS
)
1955 if (lpdwTagId
!= NULL
)
1957 dwError
= RegSetValueExW(hServiceKey
,
1961 (LPBYTE
)&lpService
->dwTag
,
1963 if (dwError
!= ERROR_SUCCESS
)
1967 /* Write dependencies */
1968 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1970 dwError
= ScmWriteDependencies(hServiceKey
,
1971 (LPWSTR
)lpDependencies
,
1973 if (dwError
!= ERROR_SUCCESS
)
1977 /* Write service start name */
1978 if (dwServiceType
& SERVICE_WIN32
)
1980 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
1981 dwError
= RegSetValueExW(hServiceKey
,
1985 (LPBYTE
)lpObjectName
,
1986 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
1987 if (dwError
!= ERROR_SUCCESS
)
1991 if (lpPassword
!= NULL
)
1993 /* FIXME: Write password */
1996 dwError
= ScmCreateServiceHandle(lpService
,
1998 if (dwError
!= ERROR_SUCCESS
)
2001 dwError
= ScmCheckAccess(hServiceHandle
,
2003 if (dwError
!= ERROR_SUCCESS
)
2006 lpService
->dwRefCount
= 1;
2007 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2010 if (hServiceKey
!= NULL
)
2011 RegCloseKey(hServiceKey
);
2013 if (dwError
== ERROR_SUCCESS
)
2015 DPRINT("hService %p\n", hServiceHandle
);
2016 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2018 if (lpdwTagId
!= NULL
)
2019 *lpdwTagId
= lpService
->dwTag
;
2023 /* Release the display name buffer */
2024 if (lpService
->lpServiceName
!= NULL
)
2025 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2029 /* Remove the service handle */
2030 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2033 if (lpService
!= NULL
)
2035 /* FIXME: remove the service entry */
2039 if (lpImagePath
!= NULL
)
2040 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2042 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2049 DWORD
REnumDependentServicesW(
2050 SC_RPC_HANDLE hService
,
2051 DWORD dwServiceState
,
2054 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2055 LPBOUNDED_DWORD_256K lpServicesReturned
)
2057 DWORD dwError
= ERROR_SUCCESS
;
2058 DWORD dwServicesReturned
= 0;
2059 DWORD dwServiceCount
;
2060 HKEY hServicesKey
= NULL
;
2061 LPSC_RPC_HANDLE hSCObject
;
2062 PSERVICE_HANDLE hSvc
;
2063 PSERVICE lpService
= NULL
;
2064 PSERVICE
*lpServicesArray
= NULL
;
2065 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2068 *pcbBytesNeeded
= 0;
2069 *lpServicesReturned
= 0;
2071 DPRINT("REnumDependentServicesW() called\n");
2073 hSCObject
= &hService
;
2074 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
2075 lpService
= hSvc
->ServiceEntry
;
2077 /* Check access rights */
2078 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2079 SC_MANAGER_ENUMERATE_SERVICE
))
2081 DPRINT1("Insufficient access rights! 0x%lx\n",
2082 hSvc
->Handle
.DesiredAccess
);
2083 return ERROR_ACCESS_DENIED
;
2086 /* Open the Services Reg key */
2087 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2088 L
"System\\CurrentControlSet\\Services",
2092 if (dwError
!= ERROR_SUCCESS
)
2095 /* First determine the bytes needed and get the number of dependent services */
2096 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2101 &dwServicesReturned
);
2102 if (dwError
!= ERROR_SUCCESS
)
2105 /* If buffer size is less than the bytes needed or pointer is null */
2106 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2108 dwError
= ERROR_MORE_DATA
;
2112 /* Allocate memory for array of service pointers */
2113 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2115 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2116 if (!lpServicesArray
)
2118 DPRINT1("Could not allocate a buffer!!\n");
2119 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2123 dwServicesReturned
= 0;
2124 *pcbBytesNeeded
= 0;
2126 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2131 &dwServicesReturned
);
2132 if (dwError
!= ERROR_SUCCESS
)
2137 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2138 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2140 /* Copy EnumDepenedentService to Buffer */
2141 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2143 lpService
= lpServicesArray
[dwServiceCount
];
2145 /* Copy status info */
2146 memcpy(&lpServicesPtr
->ServiceStatus
,
2148 sizeof(SERVICE_STATUS
));
2150 /* Copy display name */
2151 wcscpy(lpStr
, lpService
->lpDisplayName
);
2152 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2153 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2155 /* Copy service name */
2156 wcscpy(lpStr
, lpService
->lpServiceName
);
2157 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2158 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2163 *lpServicesReturned
= dwServicesReturned
;
2166 if (lpServicesArray
!= NULL
)
2167 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2169 RegCloseKey(hServicesKey
);
2171 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2178 DWORD
REnumServicesStatusW(
2179 SC_RPC_HANDLE hSCManager
,
2180 DWORD dwServiceType
,
2181 DWORD dwServiceState
,
2184 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2185 LPBOUNDED_DWORD_256K lpServicesReturned
,
2186 LPBOUNDED_DWORD_256K lpResumeHandle
)
2188 PMANAGER_HANDLE hManager
;
2190 DWORD dwError
= ERROR_SUCCESS
;
2191 PLIST_ENTRY ServiceEntry
;
2192 PSERVICE CurrentService
;
2194 DWORD dwRequiredSize
;
2195 DWORD dwServiceCount
;
2197 DWORD dwLastResumeCount
= 0;
2198 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2201 DPRINT("REnumServicesStatusW() called\n");
2204 return ERROR_SHUTDOWN_IN_PROGRESS
;
2206 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2207 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2209 DPRINT1("Invalid manager handle!\n");
2210 return ERROR_INVALID_HANDLE
;
2213 *pcbBytesNeeded
= 0;
2214 *lpServicesReturned
= 0;
2216 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2218 DPRINT("Not a valid Service Type!\n");
2219 return ERROR_INVALID_PARAMETER
;
2222 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2224 DPRINT("Not a valid Service State!\n");
2225 return ERROR_INVALID_PARAMETER
;
2228 /* Check access rights */
2229 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2230 SC_MANAGER_ENUMERATE_SERVICE
))
2232 DPRINT1("Insufficient access rights! 0x%lx\n",
2233 hManager
->Handle
.DesiredAccess
);
2234 return ERROR_ACCESS_DENIED
;
2238 dwLastResumeCount
= *lpResumeHandle
;
2240 /* FIXME: Lock the service list shared */
2242 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2243 if (lpService
== NULL
)
2245 dwError
= ERROR_SUCCESS
;
2252 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2253 ServiceEntry
!= &ServiceListHead
;
2254 ServiceEntry
= ServiceEntry
->Flink
)
2256 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2260 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2263 dwState
= SERVICE_ACTIVE
;
2264 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2265 dwState
= SERVICE_INACTIVE
;
2267 if ((dwState
& dwServiceState
) == 0)
2270 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2271 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2272 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2274 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2276 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2280 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2281 dwRequiredSize
+= dwSize
;
2283 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2286 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2287 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2290 ServiceEntry
!= &ServiceListHead
;
2291 ServiceEntry
= ServiceEntry
->Flink
)
2293 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2297 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2300 dwState
= SERVICE_ACTIVE
;
2301 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2302 dwState
= SERVICE_INACTIVE
;
2304 if ((dwState
& dwServiceState
) == 0)
2307 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2308 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2309 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2311 dwError
= ERROR_MORE_DATA
;
2314 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2317 *lpResumeHandle
= dwLastResumeCount
;
2319 *lpServicesReturned
= dwServiceCount
;
2320 *pcbBytesNeeded
= dwRequiredSize
;
2322 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2323 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2324 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2327 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2328 ServiceEntry
!= &ServiceListHead
;
2329 ServiceEntry
= ServiceEntry
->Flink
)
2331 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2335 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2338 dwState
= SERVICE_ACTIVE
;
2339 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2340 dwState
= SERVICE_INACTIVE
;
2342 if ((dwState
& dwServiceState
) == 0)
2345 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2346 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2347 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2349 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2352 /* Copy the service name */
2353 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2354 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2355 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2357 /* Copy the display name */
2358 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2359 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2360 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2362 /* Copy the status information */
2363 memcpy(&lpStatusPtr
->ServiceStatus
,
2364 &CurrentService
->Status
,
2365 sizeof(SERVICE_STATUS
));
2368 dwRequiredSize
+= dwSize
;
2373 *pcbBytesNeeded
= 0;
2374 if (lpResumeHandle
) *lpResumeHandle
= 0;
2378 /* FIXME: Unlock the service list */
2380 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2387 DWORD
ROpenSCManagerW(
2388 LPWSTR lpMachineName
,
2389 LPWSTR lpDatabaseName
,
2390 DWORD dwDesiredAccess
,
2391 LPSC_RPC_HANDLE lpScHandle
)
2396 DPRINT("ROpenSCManagerW() called\n");
2397 DPRINT("lpMachineName = %p\n", lpMachineName
);
2398 DPRINT("lpMachineName: %S\n", lpMachineName
);
2399 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2400 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2401 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2404 return ERROR_SHUTDOWN_IN_PROGRESS
;
2407 return ERROR_INVALID_PARAMETER
;
2409 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2411 if (dwError
!= ERROR_SUCCESS
)
2413 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2417 /* Check the desired access */
2418 dwError
= ScmCheckAccess(hHandle
,
2419 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2420 if (dwError
!= ERROR_SUCCESS
)
2422 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2423 HeapFree(GetProcessHeap(), 0, hHandle
);
2427 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2428 DPRINT("*hScm = %p\n", *lpScHandle
);
2430 DPRINT("ROpenSCManagerW() done\n");
2432 return ERROR_SUCCESS
;
2437 DWORD
ROpenServiceW(
2438 SC_RPC_HANDLE hSCManager
,
2439 LPWSTR lpServiceName
,
2440 DWORD dwDesiredAccess
,
2441 LPSC_RPC_HANDLE lpServiceHandle
)
2444 PMANAGER_HANDLE hManager
;
2448 DPRINT("ROpenServiceW() called\n");
2449 DPRINT("hSCManager = %p\n", hSCManager
);
2450 DPRINT("lpServiceName = %p\n", lpServiceName
);
2451 DPRINT("lpServiceName: %S\n", lpServiceName
);
2452 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2455 return ERROR_SHUTDOWN_IN_PROGRESS
;
2457 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2458 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2460 DPRINT1("Invalid manager handle!\n");
2461 return ERROR_INVALID_HANDLE
;
2464 if (!lpServiceHandle
)
2465 return ERROR_INVALID_PARAMETER
;
2468 return ERROR_INVALID_ADDRESS
;
2470 /* FIXME: Lock the service list */
2472 /* Get service database entry */
2473 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2474 if (lpService
== NULL
)
2476 DPRINT("Could not find a service!\n");
2477 return ERROR_SERVICE_DOES_NOT_EXIST
;
2480 /* Create a service handle */
2481 dwError
= ScmCreateServiceHandle(lpService
,
2483 if (dwError
!= ERROR_SUCCESS
)
2485 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2489 /* Check the desired access */
2490 dwError
= ScmCheckAccess(hHandle
,
2492 if (dwError
!= ERROR_SUCCESS
)
2494 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2495 HeapFree(GetProcessHeap(), 0, hHandle
);
2499 lpService
->dwRefCount
++;
2500 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2502 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2503 DPRINT("*hService = %p\n", *lpServiceHandle
);
2505 DPRINT("ROpenServiceW() done\n");
2507 return ERROR_SUCCESS
;
2512 DWORD
RQueryServiceConfigW(
2513 SC_RPC_HANDLE hService
,
2514 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2516 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2518 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2519 DWORD dwError
= ERROR_SUCCESS
;
2520 PSERVICE_HANDLE hSvc
;
2521 PSERVICE lpService
= NULL
;
2522 HKEY hServiceKey
= NULL
;
2523 LPWSTR lpImagePath
= NULL
;
2524 LPWSTR lpServiceStartName
= NULL
;
2525 LPWSTR lpDependencies
= NULL
;
2526 DWORD dwDependenciesLength
= 0;
2527 DWORD dwRequiredSize
;
2528 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2529 WCHAR lpEmptyString
[] = {0,0};
2532 DPRINT("RQueryServiceConfigW() called\n");
2535 return ERROR_SHUTDOWN_IN_PROGRESS
;
2537 hSvc
= (PSERVICE_HANDLE
)hService
;
2538 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2540 DPRINT1("Invalid handle tag!\n");
2541 return ERROR_INVALID_HANDLE
;
2544 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2545 SERVICE_QUERY_CONFIG
))
2547 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2548 return ERROR_ACCESS_DENIED
;
2551 lpService
= hSvc
->ServiceEntry
;
2552 if (lpService
== NULL
)
2554 DPRINT1("lpService == NULL!\n");
2555 return ERROR_INVALID_HANDLE
;
2558 /* FIXME: Lock the service database shared */
2560 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2563 if (dwError
!= ERROR_SUCCESS
)
2566 /* Read the image path */
2567 dwError
= ScmReadString(hServiceKey
,
2570 if (dwError
!= ERROR_SUCCESS
)
2573 /* Read the service start name */
2574 ScmReadString(hServiceKey
,
2576 &lpServiceStartName
);
2578 /* Read the dependencies */
2579 ScmReadDependencies(hServiceKey
,
2581 &dwDependenciesLength
);
2583 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2585 if (lpImagePath
!= NULL
)
2586 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2588 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2590 if (lpService
->lpGroup
!= NULL
)
2591 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2593 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2595 if (lpDependencies
!= NULL
)
2596 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2598 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2600 if (lpServiceStartName
!= NULL
)
2601 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2603 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2605 if (lpService
->lpDisplayName
!= NULL
)
2606 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2608 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2610 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2612 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2616 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2617 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2618 lpConfig
->dwStartType
= lpService
->dwStartType
;
2619 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2620 lpConfig
->dwTagId
= lpService
->dwTag
;
2622 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2624 /* Append the image path */
2625 if (lpImagePath
!= NULL
)
2627 wcscpy(lpStr
, lpImagePath
);
2631 wcscpy(lpStr
, lpEmptyString
);
2634 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2635 lpStr
+= (wcslen(lpStr
) + 1);
2637 /* Append the group name */
2638 if (lpService
->lpGroup
!= NULL
)
2640 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2644 wcscpy(lpStr
, lpEmptyString
);
2647 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2648 lpStr
+= (wcslen(lpStr
) + 1);
2650 /* Append Dependencies */
2651 if (lpDependencies
!= NULL
)
2655 dwDependenciesLength
* sizeof(WCHAR
));
2659 wcscpy(lpStr
, lpEmptyString
);
2662 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2663 if (lpDependencies
!= NULL
)
2664 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2666 lpStr
+= (wcslen(lpStr
) + 1);
2668 /* Append the service start name */
2669 if (lpServiceStartName
!= NULL
)
2671 wcscpy(lpStr
, lpServiceStartName
);
2675 wcscpy(lpStr
, lpEmptyString
);
2678 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2679 lpStr
+= (wcslen(lpStr
) + 1);
2681 /* Append the display name */
2682 if (lpService
->lpDisplayName
!= NULL
)
2684 wcscpy(lpStr
, lpService
->lpDisplayName
);
2688 wcscpy(lpStr
, lpEmptyString
);
2691 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2694 if (pcbBytesNeeded
!= NULL
)
2695 *pcbBytesNeeded
= dwRequiredSize
;
2698 if (lpImagePath
!= NULL
)
2699 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2701 if (lpServiceStartName
!= NULL
)
2702 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2704 if (lpDependencies
!= NULL
)
2705 HeapFree(GetProcessHeap(), 0, lpDependencies
);
2707 if (hServiceKey
!= NULL
)
2708 RegCloseKey(hServiceKey
);
2710 /* FIXME: Unlock the service database */
2712 DPRINT("RQueryServiceConfigW() done\n");
2719 DWORD
RQueryServiceLockStatusW(
2720 SC_RPC_HANDLE hSCManager
,
2721 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2723 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2726 return ERROR_CALL_NOT_IMPLEMENTED
;
2731 DWORD
RStartServiceW(
2732 SC_RPC_HANDLE hService
,
2734 LPSTRING_PTRSW argv
)
2736 DWORD dwError
= ERROR_SUCCESS
;
2737 PSERVICE_HANDLE hSvc
;
2738 PSERVICE lpService
= NULL
;
2740 DPRINT("RStartServiceW() called\n");
2743 return ERROR_SHUTDOWN_IN_PROGRESS
;
2745 hSvc
= (PSERVICE_HANDLE
)hService
;
2746 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2748 DPRINT1("Invalid handle tag!\n");
2749 return ERROR_INVALID_HANDLE
;
2752 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2755 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2756 return ERROR_ACCESS_DENIED
;
2759 lpService
= hSvc
->ServiceEntry
;
2760 if (lpService
== NULL
)
2762 DPRINT1("lpService == NULL!\n");
2763 return ERROR_INVALID_HANDLE
;
2766 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2767 return ERROR_SERVICE_DISABLED
;
2769 if (lpService
->bDeleted
)
2770 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2777 /* Start the service */
2778 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2785 DWORD
RGetServiceDisplayNameW(
2786 SC_RPC_HANDLE hSCManager
,
2787 LPCWSTR lpServiceName
,
2788 LPWSTR lpDisplayName
,
2791 // PMANAGER_HANDLE hManager;
2796 DPRINT("RGetServiceDisplayNameW() called\n");
2797 DPRINT("hSCManager = %p\n", hSCManager
);
2798 DPRINT("lpServiceName: %S\n", lpServiceName
);
2799 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2800 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2802 // hManager = (PMANAGER_HANDLE)hSCManager;
2803 // if (hManager->Handle.Tag != MANAGER_TAG)
2805 // DPRINT1("Invalid manager handle!\n");
2806 // return ERROR_INVALID_HANDLE;
2809 /* Get service database entry */
2810 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2811 if (lpService
== NULL
)
2813 DPRINT1("Could not find a service!\n");
2815 /* If the service could not be found and lpcchBuffer is less than 2, windows
2816 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2817 if (*lpcchBuffer
< 2)
2820 if (lpDisplayName
!= NULL
)
2822 *lpDisplayName
= '\0';
2826 return ERROR_SERVICE_DOES_NOT_EXIST
;
2829 if (!lpService
->lpDisplayName
)
2831 dwLength
= wcslen(lpService
->lpServiceName
);
2833 if (lpDisplayName
!= NULL
&&
2834 *lpcchBuffer
> dwLength
)
2836 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2841 dwLength
= wcslen(lpService
->lpDisplayName
);
2843 if (lpDisplayName
!= NULL
&&
2844 *lpcchBuffer
> dwLength
)
2846 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2850 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2852 *lpcchBuffer
= dwLength
;
2859 DWORD
RGetServiceKeyNameW(
2860 SC_RPC_HANDLE hSCManager
,
2861 LPCWSTR lpDisplayName
,
2862 LPWSTR lpServiceName
,
2865 // PMANAGER_HANDLE hManager;
2870 DPRINT("RGetServiceKeyNameW() called\n");
2871 DPRINT("hSCManager = %p\n", hSCManager
);
2872 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2873 DPRINT("lpServiceName: %p\n", lpServiceName
);
2874 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2876 // hManager = (PMANAGER_HANDLE)hSCManager;
2877 // if (hManager->Handle.Tag != MANAGER_TAG)
2879 // DPRINT1("Invalid manager handle!\n");
2880 // return ERROR_INVALID_HANDLE;
2883 /* Get service database entry */
2884 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2885 if (lpService
== NULL
)
2887 DPRINT1("Could not find a service!\n");
2889 /* If the service could not be found and lpcchBuffer is less than 2, windows
2890 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2891 if (*lpcchBuffer
< 2)
2894 if (lpServiceName
!= NULL
)
2896 *lpServiceName
= '\0';
2900 return ERROR_SERVICE_DOES_NOT_EXIST
;
2903 dwLength
= wcslen(lpService
->lpServiceName
);
2905 if (lpServiceName
!= NULL
&&
2906 *lpcchBuffer
> dwLength
)
2908 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2909 *lpcchBuffer
= dwLength
;
2910 return ERROR_SUCCESS
;
2913 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2915 *lpcchBuffer
= dwLength
;
2922 DWORD
RI_ScSetServiceBitsA(
2923 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
2924 DWORD dwServiceBits
,
2926 int bUpdateImmediately
,
2930 return ERROR_CALL_NOT_IMPLEMENTED
;
2935 DWORD
RChangeServiceConfigA(
2936 SC_RPC_HANDLE hService
,
2937 DWORD dwServiceType
,
2939 DWORD dwErrorControl
,
2940 LPSTR lpBinaryPathName
,
2941 LPSTR lpLoadOrderGroup
,
2943 LPSTR lpDependencies
,
2945 LPSTR lpServiceStartName
,
2948 LPSTR lpDisplayName
)
2950 DWORD dwError
= ERROR_SUCCESS
;
2951 PSERVICE_HANDLE hSvc
;
2952 PSERVICE lpService
= NULL
;
2953 HKEY hServiceKey
= NULL
;
2954 LPWSTR lpDisplayNameW
= NULL
;
2955 // LPWSTR lpBinaryPathNameW = NULL;
2956 LPWSTR lpLoadOrderGroupW
= NULL
;
2957 LPWSTR lpDependenciesW
= NULL
;
2958 // LPWSTR lpPasswordW = NULL;
2960 DPRINT("RChangeServiceConfigA() called\n");
2961 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2962 DPRINT("dwStartType = %lu\n", dwStartType
);
2963 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2964 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2965 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2966 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2969 return ERROR_SHUTDOWN_IN_PROGRESS
;
2971 hSvc
= (PSERVICE_HANDLE
)hService
;
2972 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2974 DPRINT1("Invalid handle tag!\n");
2975 return ERROR_INVALID_HANDLE
;
2978 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2979 SERVICE_CHANGE_CONFIG
))
2981 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2982 return ERROR_ACCESS_DENIED
;
2985 lpService
= hSvc
->ServiceEntry
;
2986 if (lpService
== NULL
)
2988 DPRINT1("lpService == NULL!\n");
2989 return ERROR_INVALID_HANDLE
;
2992 /* FIXME: Lock database exclusively */
2994 if (lpService
->bDeleted
)
2996 /* FIXME: Unlock database */
2997 DPRINT1("The service has already been marked for delete!\n");
2998 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3001 /* Open the service key */
3002 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3005 if (dwError
!= ERROR_SUCCESS
)
3008 /* Write service data to the registry */
3010 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3012 /* Set the display name */
3013 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3015 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3016 if (lpDisplayNameW
== NULL
)
3018 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3022 MultiByteToWideChar(CP_ACP
,
3027 strlen(lpDisplayName
) + 1);
3029 RegSetValueExW(hServiceKey
,
3033 (LPBYTE
)lpDisplayNameW
,
3034 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3036 /* Update lpService->lpDisplayName */
3037 if (lpService
->lpDisplayName
)
3038 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3040 lpService
->lpDisplayName
= lpDisplayNameW
;
3043 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3045 /* Set the service type */
3046 dwError
= RegSetValueExW(hServiceKey
,
3050 (LPBYTE
)&dwServiceType
,
3052 if (dwError
!= ERROR_SUCCESS
)
3055 lpService
->Status
.dwServiceType
= dwServiceType
;
3058 if (dwStartType
!= SERVICE_NO_CHANGE
)
3060 /* Set the start value */
3061 dwError
= RegSetValueExW(hServiceKey
,
3065 (LPBYTE
)&dwStartType
,
3067 if (dwError
!= ERROR_SUCCESS
)
3070 lpService
->dwStartType
= dwStartType
;
3073 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3075 /* Set the error control value */
3076 dwError
= RegSetValueExW(hServiceKey
,
3080 (LPBYTE
)&dwErrorControl
,
3082 if (dwError
!= ERROR_SUCCESS
)
3085 lpService
->dwErrorControl
= dwErrorControl
;
3089 /* FIXME: set the new ImagePath value */
3091 /* Set the image path */
3092 if (dwServiceType
& SERVICE_WIN32
)
3094 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3096 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3097 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, strlen(lpBinaryPathName
)+1);
3098 dwError
= RegSetValueExW(hServiceKey
,
3102 (LPBYTE
)lpBinaryPathNameW
,
3103 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3104 if (dwError
!= ERROR_SUCCESS
)
3108 else if (dwServiceType
& SERVICE_DRIVER
)
3110 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3112 dwError
= RegSetValueExW(hServiceKey
,
3116 (LPBYTE
)lpImagePath
,
3117 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3118 if (dwError
!= ERROR_SUCCESS
)
3124 /* Set the group name */
3125 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3127 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3129 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3130 if (lpLoadOrderGroupW
== NULL
)
3132 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3136 MultiByteToWideChar(CP_ACP
,
3141 strlen(lpLoadOrderGroup
) + 1);
3143 dwError
= RegSetValueExW(hServiceKey
,
3147 (LPBYTE
)lpLoadOrderGroupW
,
3148 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3149 if (dwError
!= ERROR_SUCCESS
)
3151 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3155 dwError
= ScmSetServiceGroup(lpService
,
3158 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3160 if (dwError
!= ERROR_SUCCESS
)
3164 if (lpdwTagId
!= NULL
)
3166 dwError
= ScmAssignNewTag(lpService
);
3167 if (dwError
!= ERROR_SUCCESS
)
3170 dwError
= RegSetValueExW(hServiceKey
,
3174 (LPBYTE
)&lpService
->dwTag
,
3176 if (dwError
!= ERROR_SUCCESS
)
3179 *lpdwTagId
= lpService
->dwTag
;
3182 /* Write dependencies */
3183 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3185 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3187 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3188 if (lpDependenciesW
== NULL
)
3190 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3194 MultiByteToWideChar(CP_ACP
,
3199 strlen(lpDependencies
) + 1);
3201 dwError
= ScmWriteDependencies(hServiceKey
,
3202 (LPWSTR
)lpDependenciesW
,
3205 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3208 if (lpPassword
!= NULL
)
3210 /* FIXME: Write password */
3213 /* FIXME: Unlock database */
3216 if (hServiceKey
!= NULL
)
3217 RegCloseKey(hServiceKey
);
3219 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3226 DWORD
RCreateServiceA(
3227 SC_RPC_HANDLE hSCManager
,
3228 LPSTR lpServiceName
,
3229 LPSTR lpDisplayName
,
3230 DWORD dwDesiredAccess
,
3231 DWORD dwServiceType
,
3233 DWORD dwErrorControl
,
3234 LPSTR lpBinaryPathName
,
3235 LPSTR lpLoadOrderGroup
,
3237 LPBYTE lpDependencies
,
3239 LPSTR lpServiceStartName
,
3242 LPSC_RPC_HANDLE lpServiceHandle
)
3245 return ERROR_CALL_NOT_IMPLEMENTED
;
3250 DWORD
REnumDependentServicesA(
3251 SC_RPC_HANDLE hService
,
3252 DWORD dwServiceState
,
3255 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3256 LPBOUNDED_DWORD_256K lpServicesReturned
)
3258 DWORD dwError
= ERROR_SUCCESS
;
3259 DWORD dwServicesReturned
= 0;
3260 DWORD dwServiceCount
;
3261 HKEY hServicesKey
= NULL
;
3262 LPSC_RPC_HANDLE hSCObject
;
3263 PSERVICE_HANDLE hSvc
;
3264 PSERVICE lpService
= NULL
;
3265 PSERVICE
*lpServicesArray
= NULL
;
3266 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3269 *pcbBytesNeeded
= 0;
3270 *lpServicesReturned
= 0;
3272 DPRINT("REnumDependentServicesA() called\n");
3274 hSCObject
= &hService
;
3275 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3276 lpService
= hSvc
->ServiceEntry
;
3278 /* Check access rights */
3279 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3280 SC_MANAGER_ENUMERATE_SERVICE
))
3282 DPRINT1("Insufficient access rights! 0x%lx\n",
3283 hSvc
->Handle
.DesiredAccess
);
3284 return ERROR_ACCESS_DENIED
;
3287 /* Open the Services Reg key */
3288 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3289 L
"System\\CurrentControlSet\\Services",
3294 if (dwError
!= ERROR_SUCCESS
)
3297 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3298 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3299 are the same for both. Verified in WINXP. */
3301 /* First determine the bytes needed and get the number of dependent services*/
3302 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3307 &dwServicesReturned
);
3308 if (dwError
!= ERROR_SUCCESS
)
3311 /* If buffer size is less than the bytes needed or pointer is null*/
3312 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3314 dwError
= ERROR_MORE_DATA
;
3318 /* Allocate memory for array of service pointers */
3319 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3321 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3322 if (!lpServicesArray
)
3324 DPRINT1("Could not allocate a buffer!!\n");
3325 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3329 dwServicesReturned
= 0;
3330 *pcbBytesNeeded
= 0;
3332 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3337 &dwServicesReturned
);
3338 if (dwError
!= ERROR_SUCCESS
)
3343 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3344 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3346 /* Copy EnumDepenedentService to Buffer */
3347 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3349 lpService
= lpServicesArray
[dwServiceCount
];
3351 /* Copy the status info */
3352 memcpy(&lpServicesPtr
->ServiceStatus
,
3354 sizeof(SERVICE_STATUS
));
3356 /* Copy display name */
3357 WideCharToMultiByte(CP_ACP
,
3359 lpService
->lpDisplayName
,
3362 wcslen(lpService
->lpDisplayName
),
3365 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3366 lpStr
+= strlen(lpStr
) + 1;
3368 /* Copy service name */
3369 WideCharToMultiByte(CP_ACP
,
3371 lpService
->lpServiceName
,
3374 wcslen(lpService
->lpServiceName
),
3377 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3378 lpStr
+= strlen(lpStr
) + 1;
3383 *lpServicesReturned
= dwServicesReturned
;
3386 if (lpServicesArray
)
3387 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3389 RegCloseKey(hServicesKey
);
3391 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3398 DWORD
REnumServicesStatusA(
3399 SC_RPC_HANDLE hSCManager
,
3400 DWORD dwServiceType
,
3401 DWORD dwServiceState
,
3404 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3405 LPBOUNDED_DWORD_256K lpServicesReturned
,
3406 LPBOUNDED_DWORD_256K lpResumeHandle
)
3408 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3409 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3410 LPWSTR lpStringPtrW
;
3413 DWORD dwServiceCount
;
3415 DPRINT("REnumServicesStatusA() called\n");
3417 if ((dwBufSize
> 0) && (lpBuffer
))
3419 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3422 DPRINT1("Failed to allocate buffer!\n");
3423 return ERROR_NOT_ENOUGH_MEMORY
;
3427 dwError
= REnumServicesStatusW(hSCManager
,
3430 (LPBYTE
)lpStatusPtrW
,
3436 /* if no services were returned then we are Done */
3437 if (*lpServicesReturned
== 0)
3440 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3441 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3442 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3443 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3444 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3446 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3448 /* Copy the service name */
3449 WideCharToMultiByte(CP_ACP
,
3454 wcslen(lpStringPtrW
),
3458 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3459 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3460 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3462 /* Copy the display name */
3463 WideCharToMultiByte(CP_ACP
,
3468 wcslen(lpStringPtrW
),
3472 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3473 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3474 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3476 /* Copy the status information */
3477 memcpy(&lpStatusPtrA
->ServiceStatus
,
3478 &lpStatusPtrW
->ServiceStatus
,
3479 sizeof(SERVICE_STATUS
));
3486 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3488 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3495 DWORD
ROpenSCManagerA(
3496 LPSTR lpMachineName
,
3497 LPSTR lpDatabaseName
,
3498 DWORD dwDesiredAccess
,
3499 LPSC_RPC_HANDLE lpScHandle
)
3501 UNICODE_STRING MachineName
;
3502 UNICODE_STRING DatabaseName
;
3505 DPRINT("ROpenSCManagerA() called\n");
3508 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3512 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3515 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3516 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3521 RtlFreeUnicodeString(&MachineName
);
3524 RtlFreeUnicodeString(&DatabaseName
);
3531 DWORD
ROpenServiceA(
3532 SC_RPC_HANDLE hSCManager
,
3533 LPSTR lpServiceName
,
3534 DWORD dwDesiredAccess
,
3535 LPSC_RPC_HANDLE lpServiceHandle
)
3537 UNICODE_STRING ServiceName
;
3540 DPRINT("ROpenServiceA() called\n");
3543 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3546 dwError
= ROpenServiceW(hSCManager
,
3547 lpServiceName
? ServiceName
.Buffer
: NULL
,
3552 RtlFreeUnicodeString(&ServiceName
);
3559 DWORD
RQueryServiceConfigA(
3560 SC_RPC_HANDLE hService
,
3561 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3563 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3565 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3566 DWORD dwError
= ERROR_SUCCESS
;
3567 PSERVICE_HANDLE hSvc
;
3568 PSERVICE lpService
= NULL
;
3569 HKEY hServiceKey
= NULL
;
3570 LPWSTR lpImagePath
= NULL
;
3571 LPWSTR lpServiceStartName
= NULL
;
3572 LPWSTR lpDependencies
= NULL
;
3573 DWORD dwDependenciesLength
= 0;
3574 DWORD dwRequiredSize
;
3575 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3576 CHAR lpEmptyString
[]={0,0};
3579 DPRINT("RQueryServiceConfigA() called\n");
3582 return ERROR_SHUTDOWN_IN_PROGRESS
;
3584 hSvc
= (PSERVICE_HANDLE
)hService
;
3585 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3587 DPRINT1("Invalid handle tag!\n");
3588 return ERROR_INVALID_HANDLE
;
3591 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3592 SERVICE_QUERY_CONFIG
))
3594 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3595 return ERROR_ACCESS_DENIED
;
3598 lpService
= hSvc
->ServiceEntry
;
3599 if (lpService
== NULL
)
3601 DPRINT1("lpService == NULL!\n");
3602 return ERROR_INVALID_HANDLE
;
3605 /* FIXME: Lock the service database shared */
3607 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3610 if (dwError
!= ERROR_SUCCESS
)
3613 /* Read the image path */
3614 dwError
= ScmReadString(hServiceKey
,
3617 if (dwError
!= ERROR_SUCCESS
)
3620 /* Read the service start name */
3621 ScmReadString(hServiceKey
,
3623 &lpServiceStartName
);
3625 /* Read the dependencies */
3626 ScmReadDependencies(hServiceKey
,
3628 &dwDependenciesLength
);
3630 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3632 if (lpImagePath
!= NULL
)
3633 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3635 dwRequiredSize
+= 2;
3637 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3638 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3640 dwRequiredSize
+= 2;
3642 /* Add Dependencies length */
3643 if (lpDependencies
!= NULL
)
3644 dwRequiredSize
+= dwDependenciesLength
;
3646 dwRequiredSize
+= 2;
3648 if (lpServiceStartName
!= NULL
)
3649 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3651 dwRequiredSize
+= 2;
3653 if (lpService
->lpDisplayName
!= NULL
)
3654 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3656 dwRequiredSize
+= 2;
3658 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3660 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3664 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3665 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3666 lpConfig
->dwStartType
= lpService
->dwStartType
;
3667 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3668 lpConfig
->dwTagId
= lpService
->dwTag
;
3670 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3672 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3677 WideCharToMultiByte(CP_ACP
,
3682 wcslen(lpImagePath
) + 1,
3688 strcpy(lpStr
, lpEmptyString
);
3691 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3692 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3694 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
3696 WideCharToMultiByte(CP_ACP
,
3698 lpService
->lpGroup
->lpGroupName
,
3701 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
3707 strcpy(lpStr
, lpEmptyString
);
3710 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3711 lpStr
+= (strlen(lpStr
) + 1);
3713 /* Append Dependencies */
3716 WideCharToMultiByte(CP_ACP
,
3719 dwDependenciesLength
,
3721 dwDependenciesLength
,
3727 strcpy(lpStr
, lpEmptyString
);
3730 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3732 lpStr
+= dwDependenciesLength
;
3734 lpStr
+= (strlen(lpStr
) + 1);
3736 if (lpServiceStartName
)
3738 WideCharToMultiByte(CP_ACP
,
3743 wcslen(lpServiceStartName
) + 1,
3749 strcpy(lpStr
, lpEmptyString
);
3752 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3753 lpStr
+= (strlen(lpStr
) + 1);
3755 if (lpService
->lpDisplayName
)
3757 WideCharToMultiByte(CP_ACP
,
3759 lpService
->lpDisplayName
,
3762 wcslen(lpService
->lpDisplayName
) + 1,
3768 strcpy(lpStr
, lpEmptyString
);
3771 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3774 if (pcbBytesNeeded
!= NULL
)
3775 *pcbBytesNeeded
= dwRequiredSize
;
3778 if (lpImagePath
!= NULL
)
3779 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3781 if (lpServiceStartName
!= NULL
)
3782 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3784 if (lpDependencies
!= NULL
)
3785 HeapFree(GetProcessHeap(), 0, lpDependencies
);
3787 if (hServiceKey
!= NULL
)
3788 RegCloseKey(hServiceKey
);
3790 /* FIXME: Unlock the service database */
3792 DPRINT("RQueryServiceConfigA() done\n");
3799 DWORD
RQueryServiceLockStatusA(
3800 SC_RPC_HANDLE hSCManager
,
3801 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
3803 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3806 return ERROR_CALL_NOT_IMPLEMENTED
;
3811 DWORD
RStartServiceA(
3812 SC_RPC_HANDLE hService
,
3814 LPSTRING_PTRSA argv
)
3816 DWORD dwError
= ERROR_SUCCESS
;
3817 PSERVICE_HANDLE hSvc
;
3818 PSERVICE lpService
= NULL
;
3820 DPRINT1("RStartServiceA() called\n");
3823 return ERROR_SHUTDOWN_IN_PROGRESS
;
3825 hSvc
= (PSERVICE_HANDLE
)hService
;
3826 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3828 DPRINT1("Invalid handle tag!\n");
3829 return ERROR_INVALID_HANDLE
;
3832 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3835 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3836 return ERROR_ACCESS_DENIED
;
3839 lpService
= hSvc
->ServiceEntry
;
3840 if (lpService
== NULL
)
3842 DPRINT1("lpService == NULL!\n");
3843 return ERROR_INVALID_HANDLE
;
3846 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3847 return ERROR_SERVICE_DISABLED
;
3849 if (lpService
->bDeleted
)
3850 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3852 /* FIXME: Convert argument vector to Unicode */
3854 /* Start the service */
3855 dwError
= ScmStartService(lpService
, 0, NULL
);
3857 /* FIXME: Free argument vector */
3864 DWORD
RGetServiceDisplayNameA(
3865 SC_RPC_HANDLE hSCManager
,
3866 LPCSTR lpServiceName
,
3867 LPSTR lpDisplayName
,
3868 LPBOUNDED_DWORD_4K lpcchBuffer
)
3870 // PMANAGER_HANDLE hManager;
3871 PSERVICE lpService
= NULL
;
3874 LPWSTR lpServiceNameW
;
3876 DPRINT("RGetServiceDisplayNameA() called\n");
3877 DPRINT("hSCManager = %p\n", hSCManager
);
3878 DPRINT("lpServiceName: %s\n", lpServiceName
);
3879 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3880 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3882 // hManager = (PMANAGER_HANDLE)hSCManager;
3883 // if (hManager->Handle.Tag != MANAGER_TAG)
3885 // DPRINT1("Invalid manager handle!\n");
3886 // return ERROR_INVALID_HANDLE;
3889 if (lpServiceName
!= NULL
)
3891 dwLength
= strlen(lpServiceName
) + 1;
3892 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
3894 dwLength
* sizeof(WCHAR
));
3895 if (!lpServiceNameW
)
3896 return ERROR_NOT_ENOUGH_MEMORY
;
3898 MultiByteToWideChar(CP_ACP
,
3905 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
3907 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3910 if (lpService
== NULL
)
3912 DPRINT1("Could not find a service!\n");
3914 /* If the service could not be found and lpcchBuffer is 0, windows
3915 puts null in lpDisplayName and puts 1 in lpcchBuffer */
3916 if (*lpcchBuffer
== 0)
3919 if (lpDisplayName
!= NULL
)
3921 *lpDisplayName
= '\0';
3924 return ERROR_SERVICE_DOES_NOT_EXIST
;
3927 if (!lpService
->lpDisplayName
)
3929 dwLength
= wcslen(lpService
->lpServiceName
);
3930 if (lpDisplayName
!= NULL
&&
3931 *lpcchBuffer
> dwLength
)
3933 WideCharToMultiByte(CP_ACP
,
3935 lpService
->lpServiceName
,
3936 wcslen(lpService
->lpServiceName
),
3941 return ERROR_SUCCESS
;
3946 dwLength
= wcslen(lpService
->lpDisplayName
);
3947 if (lpDisplayName
!= NULL
&&
3948 *lpcchBuffer
> dwLength
)
3950 WideCharToMultiByte(CP_ACP
,
3952 lpService
->lpDisplayName
,
3953 wcslen(lpService
->lpDisplayName
),
3958 return ERROR_SUCCESS
;
3962 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3964 *lpcchBuffer
= dwLength
* 2;
3971 DWORD
RGetServiceKeyNameA(
3972 SC_RPC_HANDLE hSCManager
,
3973 LPCSTR lpDisplayName
,
3974 LPSTR lpServiceName
,
3975 LPBOUNDED_DWORD_4K lpcchBuffer
)
3980 LPWSTR lpDisplayNameW
;
3982 DPRINT("RGetServiceKeyNameA() called\n");
3983 DPRINT("hSCManager = %p\n", hSCManager
);
3984 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
3985 DPRINT("lpServiceName: %p\n", lpServiceName
);
3986 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3988 dwLength
= strlen(lpDisplayName
) + 1;
3989 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3991 dwLength
* sizeof(WCHAR
));
3992 if (!lpDisplayNameW
)
3993 return ERROR_NOT_ENOUGH_MEMORY
;
3995 MultiByteToWideChar(CP_ACP
,
4002 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4004 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4006 if (lpService
== NULL
)
4008 DPRINT1("Could not find the service!\n");
4010 /* If the service could not be found and lpcchBuffer is 0,
4011 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4012 if (*lpcchBuffer
== 0)
4015 if (lpServiceName
!= NULL
)
4017 *lpServiceName
= '\0';
4021 return ERROR_SERVICE_DOES_NOT_EXIST
;
4024 dwLength
= wcslen(lpService
->lpServiceName
);
4025 if (lpServiceName
!= NULL
&&
4026 *lpcchBuffer
> dwLength
)
4028 WideCharToMultiByte(CP_ACP
,
4030 lpService
->lpServiceName
,
4031 wcslen(lpService
->lpServiceName
),
4036 return ERROR_SUCCESS
;
4039 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4041 *lpcchBuffer
= dwLength
* 2;
4048 DWORD
RI_ScGetCurrentGroupStateW(
4049 SC_RPC_HANDLE hSCManager
,
4050 LPWSTR lpLoadOrderGroup
,
4054 return ERROR_CALL_NOT_IMPLEMENTED
;
4059 DWORD
REnumServiceGroupW(
4060 SC_RPC_HANDLE hSCManager
,
4061 DWORD dwServiceType
,
4062 DWORD dwServiceState
,
4065 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4066 LPBOUNDED_DWORD_256K lpServicesReturned
,
4067 LPBOUNDED_DWORD_256K lpResumeIndex
,
4068 LPCWSTR pszGroupName
)
4071 return ERROR_CALL_NOT_IMPLEMENTED
;
4076 // WARNING: This function is untested
4079 DWORD
RChangeServiceConfig2A(
4080 SC_RPC_HANDLE hService
,
4081 SC_RPC_CONFIG_INFOA Info
)
4083 SC_RPC_CONFIG_INFOW InfoW
;
4084 DWORD dwRet
, dwLength
;
4087 DPRINT("RChangeServiceConfig2A() called\n");
4088 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4090 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4092 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4094 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4095 LPSERVICE_DESCRIPTIONA lpServiceDescriptonA
;
4097 lpServiceDescriptonA
= Info
.psd
;
4099 ///if (lpServiceDescriptonA &&
4100 ///lpServiceDescriptonA->lpDescription)
4102 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4104 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4106 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4107 if (!lpServiceDescriptonW
)
4109 return ERROR_NOT_ENOUGH_MEMORY
;
4112 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4114 MultiByteToWideChar(CP_ACP
,
4118 lpServiceDescriptonW
->lpDescription
,
4121 ptr
= lpServiceDescriptonW
;
4122 InfoW
.psd
= lpServiceDescriptonW
;
4125 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4127 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4128 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4129 DWORD dwRebootLen
= 0;
4130 DWORD dwCommandLen
= 0;
4132 lpServiceFailureActionsA
= Info
.psfa
;
4134 if (lpServiceFailureActionsA
)
4136 if (lpServiceFailureActionsA
->lpRebootMsg
)
4138 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4140 if (lpServiceFailureActionsA
->lpCommand
)
4142 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4144 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4146 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4149 if (!lpServiceFailureActionsW
)
4151 return ERROR_NOT_ENOUGH_MEMORY
;
4154 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4155 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4156 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4158 if (lpServiceFailureActionsA
->lpRebootMsg
)
4160 MultiByteToWideChar(CP_ACP
,
4162 lpServiceFailureActionsA
->lpRebootMsg
,
4164 lpServiceFailureActionsW
->lpRebootMsg
,
4168 if (lpServiceFailureActionsA
->lpCommand
)
4170 MultiByteToWideChar(CP_ACP
,
4172 lpServiceFailureActionsA
->lpCommand
,
4174 lpServiceFailureActionsW
->lpCommand
,
4178 ptr
= lpServiceFailureActionsW
;
4182 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4184 HeapFree(GetProcessHeap(), 0, ptr
);
4191 DWORD
RChangeServiceConfig2W(
4192 SC_RPC_HANDLE hService
,
4193 SC_RPC_CONFIG_INFOW Info
)
4195 DWORD dwError
= ERROR_SUCCESS
;
4196 PSERVICE_HANDLE hSvc
;
4197 PSERVICE lpService
= NULL
;
4198 HKEY hServiceKey
= NULL
;
4200 DPRINT("RChangeServiceConfig2W() called\n");
4201 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4204 return ERROR_SHUTDOWN_IN_PROGRESS
;
4206 hSvc
= (PSERVICE_HANDLE
)hService
;
4207 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4209 DPRINT1("Invalid handle tag!\n");
4210 return ERROR_INVALID_HANDLE
;
4213 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4214 SERVICE_CHANGE_CONFIG
))
4216 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4217 return ERROR_ACCESS_DENIED
;
4220 lpService
= hSvc
->ServiceEntry
;
4221 if (lpService
== NULL
)
4223 DPRINT1("lpService == NULL!\n");
4224 return ERROR_INVALID_HANDLE
;
4227 /* FIXME: Lock database exclusively */
4229 if (lpService
->bDeleted
)
4231 /* FIXME: Unlock database */
4232 DPRINT1("The service has already been marked for delete!\n");
4233 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4236 /* Open the service key */
4237 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4240 if (dwError
!= ERROR_SUCCESS
)
4243 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4245 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4247 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4248 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4250 if (lpServiceDescription
!= NULL
&&
4251 lpServiceDescription
->lpDescription
!= NULL
)
4253 DPRINT1("Setting value %S\n", lpServiceDescription
->lpDescription
);
4254 RegSetValueExW(hServiceKey
,
4258 (LPBYTE
)lpServiceDescription
->lpDescription
,
4259 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4261 if (dwError
!= ERROR_SUCCESS
)
4265 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4268 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4273 /* FIXME: Unlock database */
4274 if (hServiceKey
!= NULL
)
4275 RegCloseKey(hServiceKey
);
4277 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4284 DWORD
RQueryServiceConfig2A(
4285 SC_RPC_HANDLE hService
,
4289 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4291 DWORD dwError
= ERROR_SUCCESS
;
4292 PSERVICE_HANDLE hSvc
;
4293 PSERVICE lpService
= NULL
;
4294 HKEY hServiceKey
= NULL
;
4295 LPWSTR lpDescriptionW
= NULL
;
4296 LPSTR lpDescription
= NULL
;
4298 DPRINT1("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4299 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4302 return ERROR_INVALID_ADDRESS
;
4305 return ERROR_SHUTDOWN_IN_PROGRESS
;
4307 hSvc
= (PSERVICE_HANDLE
)hService
;
4308 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4310 DPRINT1("Invalid handle tag!\n");
4311 return ERROR_INVALID_HANDLE
;
4314 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4315 SERVICE_QUERY_CONFIG
))
4317 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4318 return ERROR_ACCESS_DENIED
;
4321 lpService
= hSvc
->ServiceEntry
;
4322 if (lpService
== NULL
)
4324 DPRINT1("lpService == NULL!\n");
4325 return ERROR_INVALID_HANDLE
;
4328 /* FIXME: Lock the service database shared */
4330 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4333 if (dwError
!= ERROR_SUCCESS
)
4336 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4338 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4341 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4343 dwError
= ScmReadString(hServiceKey
,
4346 if (dwError
== ERROR_SUCCESS
)
4348 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4351 if (cbBufSize
>= *pcbBytesNeeded
)
4354 if (dwError
== ERROR_SUCCESS
)
4356 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4358 WideCharToMultiByte(CP_ACP
,
4363 wcslen(lpDescriptionW
),
4366 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4370 lpServiceDescription
->lpDescription
= NULL
;
4376 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4380 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4383 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4388 if (lpDescription
!= NULL
)
4389 HeapFree(GetProcessHeap(), 0, lpDescription
);
4391 if (hServiceKey
!= NULL
)
4392 RegCloseKey(hServiceKey
);
4394 /* FIXME: Unlock database */
4396 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4403 DWORD
RQueryServiceConfig2W(
4404 SC_RPC_HANDLE hService
,
4408 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4410 DWORD dwError
= ERROR_SUCCESS
;
4411 PSERVICE_HANDLE hSvc
;
4412 PSERVICE lpService
= NULL
;
4413 HKEY hServiceKey
= NULL
;
4414 DWORD dwRequiredSize
;
4415 LPWSTR lpDescription
= NULL
;
4416 LPWSTR lpFailureCommand
= NULL
;
4417 LPWSTR lpRebootMessage
= NULL
;
4419 DPRINT("RQueryServiceConfig2W() called\n");
4422 return ERROR_INVALID_ADDRESS
;
4425 return ERROR_SHUTDOWN_IN_PROGRESS
;
4427 hSvc
= (PSERVICE_HANDLE
)hService
;
4428 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4430 DPRINT1("Invalid handle tag!\n");
4431 return ERROR_INVALID_HANDLE
;
4434 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4435 SERVICE_QUERY_CONFIG
))
4437 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4438 return ERROR_ACCESS_DENIED
;
4441 lpService
= hSvc
->ServiceEntry
;
4442 if (lpService
== NULL
)
4444 DPRINT1("lpService == NULL!\n");
4445 return ERROR_INVALID_HANDLE
;
4448 /* FIXME: Lock the service database shared */
4450 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4453 if (dwError
!= ERROR_SUCCESS
)
4456 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4458 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4461 dwError
= ScmReadString(hServiceKey
,
4464 if (dwError
!= ERROR_SUCCESS
)
4467 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4469 if (cbBufSize
< dwRequiredSize
)
4471 *pcbBytesNeeded
= dwRequiredSize
;
4472 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4476 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4477 wcscpy(lpStr
, lpDescription
);
4478 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4480 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4483 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
4487 dwError
= ScmReadString(hServiceKey
,
4491 dwError
= ScmReadString(hServiceKey
,
4495 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
4497 if (lpFailureCommand
)
4498 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
4500 if (lpRebootMessage
)
4501 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
4503 if (cbBufSize
< dwRequiredSize
)
4505 *pcbBytesNeeded
= dwRequiredSize
;
4506 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4510 lpFailureActions
->cActions
= 0;
4511 lpFailureActions
->dwResetPeriod
= 0;
4512 lpFailureActions
->lpCommand
= NULL
;
4513 lpFailureActions
->lpRebootMsg
= NULL
;
4514 lpFailureActions
->lpsaActions
= NULL
;
4516 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
4517 if (lpRebootMessage
)
4519 wcscpy(lpStr
, lpRebootMessage
);
4520 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
4521 lpStr
+= wcslen(lpRebootMessage
) + 1;
4524 if (lpFailureCommand
)
4526 wcscpy(lpStr
, lpFailureCommand
);
4527 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
4528 lpStr
+= wcslen(lpRebootMessage
) + 1;
4530 dwError
= STATUS_SUCCESS
;
4535 if (lpDescription
!= NULL
)
4536 HeapFree(GetProcessHeap(), 0, lpDescription
);
4538 if (lpRebootMessage
!= NULL
)
4539 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
4541 if (lpFailureCommand
!= NULL
)
4542 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
4544 if (hServiceKey
!= NULL
)
4545 RegCloseKey(hServiceKey
);
4547 /* FIXME: Unlock database */
4549 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4556 DWORD
RQueryServiceStatusEx(
4557 SC_RPC_HANDLE hService
,
4558 SC_STATUS_TYPE InfoLevel
,
4561 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4563 LPSERVICE_STATUS_PROCESS lpStatus
;
4564 PSERVICE_HANDLE hSvc
;
4567 DPRINT("RQueryServiceStatusEx() called\n");
4570 return ERROR_SHUTDOWN_IN_PROGRESS
;
4572 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4573 return ERROR_INVALID_LEVEL
;
4575 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4577 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4578 return ERROR_INSUFFICIENT_BUFFER
;
4580 hSvc
= (PSERVICE_HANDLE
)hService
;
4581 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4583 DPRINT1("Invalid handle tag!\n");
4584 return ERROR_INVALID_HANDLE
;
4587 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4588 SERVICE_QUERY_STATUS
))
4590 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4591 return ERROR_ACCESS_DENIED
;
4594 lpService
= hSvc
->ServiceEntry
;
4595 if (lpService
== NULL
)
4597 DPRINT1("lpService == NULL!\n");
4598 return ERROR_INVALID_HANDLE
;
4601 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4603 /* Return service status information */
4604 RtlCopyMemory(lpStatus
,
4606 sizeof(SERVICE_STATUS
));
4608 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
4609 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4611 return ERROR_SUCCESS
;
4616 DWORD
REnumServicesStatusExA(
4617 SC_RPC_HANDLE hSCManager
,
4618 SC_ENUM_TYPE InfoLevel
,
4619 DWORD dwServiceType
,
4620 DWORD dwServiceState
,
4623 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4624 LPBOUNDED_DWORD_256K lpServicesReturned
,
4625 LPBOUNDED_DWORD_256K lpResumeIndex
,
4626 LPCSTR pszGroupName
)
4628 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
4629 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
4630 LPWSTR lpStringPtrW
;
4632 LPWSTR pszGroupNameW
= NULL
;
4634 DWORD dwServiceCount
;
4636 DPRINT("REnumServicesStatusExA() called\n");
4640 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
4643 DPRINT1("Failed to allocate buffer!\n");
4644 return ERROR_NOT_ENOUGH_MEMORY
;
4647 MultiByteToWideChar(CP_ACP
,
4652 strlen(pszGroupName
) + 1);
4655 if ((cbBufSize
> 0) && (lpBuffer
))
4657 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
4660 DPRINT1("Failed to allocate buffer!\n");
4661 return ERROR_NOT_ENOUGH_MEMORY
;
4665 dwError
= REnumServicesStatusExW(hSCManager
,
4669 (LPBYTE
)lpStatusPtrW
,
4676 /* if no services were returned then we are Done */
4677 if (*lpServicesReturned
== 0)
4680 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
4681 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
4682 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
4683 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
4684 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4686 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
4688 /* Copy the service name */
4689 WideCharToMultiByte(CP_ACP
,
4694 wcslen(lpStringPtrW
),
4698 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4699 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4700 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4702 /* Copy the display name */
4703 WideCharToMultiByte(CP_ACP
,
4708 wcslen(lpStringPtrW
),
4712 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4713 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4714 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4716 /* Copy the status information */
4717 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
4718 &lpStatusPtrW
->ServiceStatusProcess
,
4719 sizeof(SERVICE_STATUS
));
4721 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
4722 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4728 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
4731 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
4733 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
4740 DWORD
REnumServicesStatusExW(
4741 SC_RPC_HANDLE hSCManager
,
4742 SC_ENUM_TYPE InfoLevel
,
4743 DWORD dwServiceType
,
4744 DWORD dwServiceState
,
4747 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4748 LPBOUNDED_DWORD_256K lpServicesReturned
,
4749 LPBOUNDED_DWORD_256K lpResumeIndex
,
4750 LPCWSTR pszGroupName
)
4752 PMANAGER_HANDLE hManager
;
4754 DWORD dwError
= ERROR_SUCCESS
;
4755 PLIST_ENTRY ServiceEntry
;
4756 PSERVICE CurrentService
;
4758 DWORD dwRequiredSize
;
4759 DWORD dwServiceCount
;
4761 DWORD dwLastResumeCount
= 0;
4762 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
4765 DPRINT("REnumServicesStatusExW() called\n");
4768 return ERROR_SHUTDOWN_IN_PROGRESS
;
4770 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
4771 return ERROR_INVALID_LEVEL
;
4773 hManager
= (PMANAGER_HANDLE
)hSCManager
;
4774 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
4776 DPRINT1("Invalid manager handle!\n");
4777 return ERROR_INVALID_HANDLE
;
4780 *pcbBytesNeeded
= 0;
4781 *lpServicesReturned
= 0;
4783 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
4785 DPRINT1("Not a valid Service Type!\n");
4786 return ERROR_INVALID_PARAMETER
;
4789 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
4791 DPRINT1("Not a valid Service State!\n");
4792 return ERROR_INVALID_PARAMETER
;
4795 /* Check access rights */
4796 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4797 SC_MANAGER_ENUMERATE_SERVICE
))
4799 DPRINT1("Insufficient access rights! 0x%lx\n",
4800 hManager
->Handle
.DesiredAccess
);
4801 return ERROR_ACCESS_DENIED
;
4804 if (lpResumeIndex
) dwLastResumeCount
= *lpResumeIndex
;
4806 /* Lock the service list shared */
4808 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4809 if (lpService
== NULL
)
4811 dwError
= ERROR_SUCCESS
;
4818 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4819 ServiceEntry
!= &ServiceListHead
;
4820 ServiceEntry
= ServiceEntry
->Flink
)
4822 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4826 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4829 dwState
= SERVICE_ACTIVE
;
4830 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4831 dwState
= SERVICE_INACTIVE
;
4833 if ((dwState
& dwServiceState
) == 0)
4838 if (*pszGroupName
== 0)
4840 if (CurrentService
->lpGroup
!= NULL
)
4845 if ((CurrentService
->lpGroup
== NULL
) ||
4846 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4851 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4852 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4853 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4855 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4857 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
4858 dwRequiredSize
+= dwSize
;
4860 dwLastResumeCount
= CurrentService
->dwResumeCount
;
4864 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
4870 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
4871 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
4874 ServiceEntry
!= &ServiceListHead
;
4875 ServiceEntry
= ServiceEntry
->Flink
)
4877 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4881 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4884 dwState
= SERVICE_ACTIVE
;
4885 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4886 dwState
= SERVICE_INACTIVE
;
4888 if ((dwState
& dwServiceState
) == 0)
4893 if (*pszGroupName
== 0)
4895 if (CurrentService
->lpGroup
!= NULL
)
4900 if ((CurrentService
->lpGroup
== NULL
) ||
4901 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4906 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4907 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4908 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
4910 dwError
= ERROR_MORE_DATA
;
4913 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
4916 *lpResumeIndex
= dwLastResumeCount
;
4918 *lpServicesReturned
= dwServiceCount
;
4919 *pcbBytesNeeded
= dwRequiredSize
;
4921 /* If there was no services that matched */
4922 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
4924 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
4928 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
4929 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
4930 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4933 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4934 ServiceEntry
!= &ServiceListHead
;
4935 ServiceEntry
= ServiceEntry
->Flink
)
4937 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4941 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4944 dwState
= SERVICE_ACTIVE
;
4945 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4946 dwState
= SERVICE_INACTIVE
;
4948 if ((dwState
& dwServiceState
) == 0)
4953 if (*pszGroupName
== 0)
4955 if (CurrentService
->lpGroup
!= NULL
)
4960 if ((CurrentService
->lpGroup
== NULL
) ||
4961 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4966 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4967 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4968 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4970 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4972 /* Copy the service name */
4974 CurrentService
->lpServiceName
);
4975 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4976 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
4978 /* Copy the display name */
4980 CurrentService
->lpDisplayName
);
4981 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4982 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
4984 /* Copy the status information */
4985 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
4986 &CurrentService
->Status
,
4987 sizeof(SERVICE_STATUS
));
4988 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
4989 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4992 dwRequiredSize
+= dwSize
;
5002 *pcbBytesNeeded
= 0;
5008 /* Unlock the service list */
5010 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5017 DWORD
RSendTSMessage(
5018 handle_t BindingHandle
) /* FIXME */
5021 return ERROR_CALL_NOT_IMPLEMENTED
;
5026 DWORD
RCreateServiceWOW64A(
5027 handle_t BindingHandle
,
5028 LPSTR lpServiceName
,
5029 LPSTR lpDisplayName
,
5030 DWORD dwDesiredAccess
,
5031 DWORD dwServiceType
,
5033 DWORD dwErrorControl
,
5034 LPSTR lpBinaryPathName
,
5035 LPSTR lpLoadOrderGroup
,
5037 LPBYTE lpDependencies
,
5039 LPSTR lpServiceStartName
,
5042 LPSC_RPC_HANDLE lpServiceHandle
)
5045 return ERROR_CALL_NOT_IMPLEMENTED
;
5050 DWORD
RCreateServiceWOW64W(
5051 handle_t BindingHandle
,
5052 LPWSTR lpServiceName
,
5053 LPWSTR lpDisplayName
,
5054 DWORD dwDesiredAccess
,
5055 DWORD dwServiceType
,
5057 DWORD dwErrorControl
,
5058 LPWSTR lpBinaryPathName
,
5059 LPWSTR lpLoadOrderGroup
,
5061 LPBYTE lpDependencies
,
5063 LPWSTR lpServiceStartName
,
5066 LPSC_RPC_HANDLE lpServiceHandle
)
5069 return ERROR_CALL_NOT_IMPLEMENTED
;
5074 DWORD
RQueryServiceTagInfo(
5075 handle_t BindingHandle
) /* FIXME */
5078 return ERROR_CALL_NOT_IMPLEMENTED
;
5083 DWORD
RNotifyServiceStatusChange(
5084 SC_RPC_HANDLE hService
,
5085 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5086 GUID
*pClientProcessGuid
,
5087 GUID
*pSCMProcessGuid
,
5088 PBOOL pfCreateRemoteQueue
,
5089 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5092 return ERROR_CALL_NOT_IMPLEMENTED
;
5097 DWORD
RGetNotifyResults(
5098 SC_NOTIFY_RPC_HANDLE hNotify
,
5099 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5102 return ERROR_CALL_NOT_IMPLEMENTED
;
5107 DWORD
RCloseNotifyHandle(
5108 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5112 return ERROR_CALL_NOT_IMPLEMENTED
;
5117 DWORD
RControlServiceExA(
5118 SC_RPC_HANDLE hService
,
5123 return ERROR_CALL_NOT_IMPLEMENTED
;
5128 DWORD
RControlServiceExW(
5129 SC_RPC_HANDLE hService
,
5134 return ERROR_CALL_NOT_IMPLEMENTED
;
5139 DWORD
RSendPnPMessage(
5140 handle_t BindingHandle
) /* FIXME */
5143 return ERROR_CALL_NOT_IMPLEMENTED
;
5148 DWORD
RValidatePnPService(
5149 handle_t BindingHandle
) /* FIXME */
5152 return ERROR_CALL_NOT_IMPLEMENTED
;
5157 DWORD
ROpenServiceStatusHandle(
5158 handle_t BindingHandle
) /* FIXME */
5161 return ERROR_CALL_NOT_IMPLEMENTED
;
5167 handle_t BindingHandle
) /* FIXME */
5170 return ERROR_CALL_NOT_IMPLEMENTED
;
5174 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5176 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5180 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5182 HeapFree(GetProcessHeap(), 0, ptr
);
5186 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5191 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5196 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)