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 handle_t BindingHandle
,
404 LPSC_RPC_HANDLE hSCObject
)
406 PMANAGER_HANDLE hManager
;
407 PSERVICE_HANDLE hService
;
411 DWORD pcbBytesNeeded
= 0;
412 DWORD dwServicesReturned
= 0;
414 DPRINT("RCloseServiceHandle() called\n");
416 DPRINT("hSCObject = %p\n", *hSCObject
);
419 return ERROR_INVALID_HANDLE
;
421 hManager
= (PMANAGER_HANDLE
)*hSCObject
;
422 hService
= (PSERVICE_HANDLE
)*hSCObject
;
423 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
425 DPRINT("Found manager handle\n");
427 hManager
->Handle
.RefCount
--;
428 if (hManager
->Handle
.RefCount
== 0)
430 /* FIXME: add handle cleanup code */
432 HeapFree(GetProcessHeap(), 0, hManager
);
436 DPRINT("RCloseServiceHandle() done\n");
437 return ERROR_SUCCESS
;
439 else if (hService
->Handle
.Tag
== SERVICE_TAG
)
441 DPRINT("Found service handle\n");
443 /* Get the pointer to the service record */
444 lpService
= hService
->ServiceEntry
;
446 ASSERT(hService
->Handle
.RefCount
> 0);
448 hService
->Handle
.RefCount
--;
449 if (hService
->Handle
.RefCount
== 0)
451 /* FIXME: add handle cleanup code */
453 /* Free the handle */
454 HeapFree(GetProcessHeap(), 0, hService
);
458 ASSERT(lpService
->dwRefCount
> 0);
460 lpService
->dwRefCount
--;
461 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
462 lpService
->dwRefCount
);
464 if (lpService
->dwRefCount
== 0)
466 /* If this service has been marked for deletion */
467 if (lpService
->bDeleted
)
469 /* Open the Services Reg key */
470 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
471 L
"System\\CurrentControlSet\\Services",
473 KEY_SET_VALUE
| KEY_READ
,
475 if (dwError
!= ERROR_SUCCESS
)
477 DPRINT1("Failed to open services key\n");
481 /* Call the internal function with NULL, just to get bytes we need */
482 Int_EnumDependentServicesW(hServicesKey
,
487 &dwServicesReturned
);
489 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
492 DPRINT1("Deletion failed due to running dependencies.\n");
493 RegCloseKey(hServicesKey
);
494 return ERROR_SUCCESS
;
497 /* There are no references and no runnning dependencies,
498 it is now safe to delete the service */
500 /* Delete the Service Key */
501 dwError
= RegDeleteKey(hServicesKey
,
502 lpService
->lpServiceName
);
504 RegCloseKey(hServicesKey
);
506 if (dwError
!= ERROR_SUCCESS
)
508 DPRINT1("Failed to Delete the Service Registry key\n");
512 /* Delete the Service */
513 ScmDeleteServiceRecord(lpService
);
517 DPRINT("RCloseServiceHandle() done\n");
518 return ERROR_SUCCESS
;
521 DPRINT1("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
523 return ERROR_INVALID_HANDLE
;
528 DWORD
RControlService(
529 handle_t BindingHandle
,
530 SC_RPC_HANDLE hService
,
532 LPSERVICE_STATUS lpServiceStatus
)
534 PSERVICE_HANDLE hSvc
;
536 ACCESS_MASK DesiredAccess
;
537 DWORD dwError
= ERROR_SUCCESS
;
538 DWORD pcbBytesNeeded
= 0;
539 DWORD dwServicesReturned
= 0;
540 HKEY hServicesKey
= NULL
;
542 DPRINT("RControlService() called\n");
545 return ERROR_SHUTDOWN_IN_PROGRESS
;
547 /* Check the service handle */
548 hSvc
= (PSERVICE_HANDLE
)hService
;
549 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
551 DPRINT1("Invalid handle tag!\n");
552 return ERROR_INVALID_HANDLE
;
555 /* Check the service entry point */
556 lpService
= hSvc
->ServiceEntry
;
557 if (lpService
== NULL
)
559 DPRINT1("lpService == NULL!\n");
560 return ERROR_INVALID_HANDLE
;
563 /* Check access rights */
566 case SERVICE_CONTROL_STOP
:
567 DesiredAccess
= SERVICE_STOP
;
570 case SERVICE_CONTROL_PAUSE
:
571 case SERVICE_CONTROL_CONTINUE
:
572 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
575 case SERVICE_INTERROGATE
:
576 DesiredAccess
= SERVICE_INTERROGATE
;
580 if (dwControl
>= 128 && dwControl
<= 255)
581 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
583 DesiredAccess
= SERVICE_QUERY_CONFIG
|
584 SERVICE_CHANGE_CONFIG
|
585 SERVICE_QUERY_STATUS
|
587 SERVICE_PAUSE_CONTINUE
;
591 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
593 return ERROR_ACCESS_DENIED
;
595 if (dwControl
== SERVICE_CONTROL_STOP
)
597 /* Check if the service has dependencies running as windows
598 doesn't stop a service that does */
600 /* Open the Services Reg key */
601 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
602 L
"System\\CurrentControlSet\\Services",
606 if (dwError
!= ERROR_SUCCESS
)
608 DPRINT1("Failed to open services key\n");
612 /* Call the internal function with NULL, just to get bytes we need */
613 Int_EnumDependentServicesW(hServicesKey
,
618 &dwServicesReturned
);
620 RegCloseKey(hServicesKey
);
622 /* If pcbBytesNeeded is not zero then there are services running that
623 are dependent on this service */
624 if (pcbBytesNeeded
!= 0)
626 DPRINT("Service has running dependencies. Failed to stop service.\n");
627 return ERROR_DEPENDENT_SERVICES_RUNNING
;
631 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
633 /* Send control code to the driver */
634 dwError
= ScmControlDriver(lpService
,
640 /* Send control code to the service */
641 dwError
= ScmControlService(lpService
,
646 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
647 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
649 /* Return service status information */
650 RtlCopyMemory(lpServiceStatus
,
652 sizeof(SERVICE_STATUS
));
659 DWORD
RDeleteService(
660 handle_t BindingHandle
,
661 SC_RPC_HANDLE hService
)
663 PSERVICE_HANDLE hSvc
;
667 DPRINT("RDeleteService() called\n");
670 return ERROR_SHUTDOWN_IN_PROGRESS
;
672 hSvc
= (PSERVICE_HANDLE
)hService
;
673 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
674 return ERROR_INVALID_HANDLE
;
676 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
678 return ERROR_ACCESS_DENIED
;
680 lpService
= hSvc
->ServiceEntry
;
681 if (lpService
== NULL
)
683 DPRINT1("lpService == NULL!\n");
684 return ERROR_INVALID_HANDLE
;
687 /* FIXME: Acquire service database lock exclusively */
689 if (lpService
->bDeleted
)
691 DPRINT1("The service has already been marked for delete!\n");
692 return ERROR_SERVICE_MARKED_FOR_DELETE
;
695 /* Mark service for delete */
696 lpService
->bDeleted
= TRUE
;
698 dwError
= ScmMarkServiceForDelete(lpService
);
700 /* FIXME: Release service database lock */
702 DPRINT("RDeleteService() done\n");
709 DWORD
RLockServiceDatabase(
710 handle_t BindingHandle
,
711 SC_RPC_HANDLE hSCManager
,
712 LPSC_RPC_LOCK lpLock
)
714 PMANAGER_HANDLE hMgr
;
716 DPRINT("RLockServiceDatabase() called\n");
720 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
721 if (!hMgr
|| hMgr
->Handle
.Tag
!= MANAGER_TAG
)
722 return ERROR_INVALID_HANDLE
;
724 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
726 return ERROR_ACCESS_DENIED
;
728 // return ScmLockDatabase(0, hMgr->0xC, hLock);
730 /* FIXME: Lock the database */
731 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
733 return ERROR_SUCCESS
;
738 DWORD
RQueryServiceObjectSecurity(
739 handle_t BindingHandle
,
740 SC_RPC_HANDLE hService
,
741 SECURITY_INFORMATION dwSecurityInformation
,
742 LPBYTE lpSecurityDescriptor
,
744 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
747 PSERVICE_HANDLE hSvc
;
749 ULONG DesiredAccess
= 0;
754 DPRINT("RQueryServiceObjectSecurity() called\n");
756 hSvc
= (PSERVICE_HANDLE
)hService
;
757 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
759 DPRINT1("Invalid handle tag!\n");
760 return ERROR_INVALID_HANDLE
;
763 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
764 GROUP_SECURITY_INFORMATION
||
765 OWNER_SECURITY_INFORMATION
))
766 DesiredAccess
|= READ_CONTROL
;
768 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
769 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
771 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
774 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
775 return ERROR_ACCESS_DENIED
;
778 lpService
= hSvc
->ServiceEntry
;
779 if (lpService
== NULL
)
781 DPRINT1("lpService == NULL!\n");
782 return ERROR_INVALID_HANDLE
;
785 /* FIXME: Lock the service list */
787 Status
= RtlQuerySecurityObject(lpService
->lpSecurityDescriptor
,
788 dwSecurityInformation
,
789 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
790 dwSecuityDescriptorSize
,
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
);
817 return ERROR_CALL_NOT_IMPLEMENTED
;
822 DWORD
RSetServiceObjectSecurity(
823 handle_t BindingHandle
,
824 SC_RPC_HANDLE hService
,
825 DWORD dwSecurityInformation
,
826 LPBYTE lpSecurityDescriptor
,
827 DWORD dwSecuityDescriptorSize
)
829 PSERVICE_HANDLE hSvc
;
831 ULONG DesiredAccess
= 0;
832 HANDLE hToken
= NULL
;
837 DPRINT1("RSetServiceObjectSecurity() called\n");
839 hSvc
= (PSERVICE_HANDLE
)hService
;
840 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
842 DPRINT1("Invalid handle tag!\n");
843 return ERROR_INVALID_HANDLE
;
846 if (dwSecurityInformation
== 0 ||
847 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
848 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
849 return ERROR_INVALID_PARAMETER
;
851 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
852 return ERROR_INVALID_PARAMETER
;
854 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
855 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
857 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
858 DesiredAccess
|= WRITE_DAC
;
860 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
861 DesiredAccess
|= WRITE_OWNER
;
863 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
864 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
865 return ERROR_INVALID_PARAMETER
;
867 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
868 (((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
869 return ERROR_INVALID_PARAMETER
;
871 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
874 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
875 return ERROR_ACCESS_DENIED
;
878 lpService
= hSvc
->ServiceEntry
;
879 if (lpService
== NULL
)
881 DPRINT1("lpService == NULL!\n");
882 return ERROR_INVALID_HANDLE
;
885 if (lpService
->bDeleted
)
886 return ERROR_SERVICE_MARKED_FOR_DELETE
;
888 RpcImpersonateClient(NULL
);
890 Status
= NtOpenThreadToken(NtCurrentThread(),
894 if (!NT_SUCCESS(Status
))
895 return RtlNtStatusToDosError(Status
);
899 /* FIXME: Lock service database */
902 Status
= RtlSetSecurityObject(dwSecurityInformation
,
903 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
904 &lpService
->lpSecurityDescriptor
,
907 if (!NT_SUCCESS(Status
))
909 dwError
= RtlNtStatusToDosError(Status
);
914 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
915 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
917 if (dwError
!= ERROR_SUCCESS
)
921 dwError
= ERROR_SUCCESS
;
922 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
923 // lpService->lpSecurityDescriptor);
925 RegFlushKey(hServiceKey
);
926 RegCloseKey(hServiceKey
);
933 /* FIXME: Unlock service database */
935 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
942 DWORD
RQueryServiceStatus(
943 handle_t BindingHandle
,
944 SC_RPC_HANDLE hService
,
945 LPSERVICE_STATUS lpServiceStatus
)
947 PSERVICE_HANDLE hSvc
;
950 DPRINT("RQueryServiceStatus() called\n");
953 return ERROR_SHUTDOWN_IN_PROGRESS
;
955 hSvc
= (PSERVICE_HANDLE
)hService
;
956 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
958 DPRINT1("Invalid handle tag!\n");
959 return ERROR_INVALID_HANDLE
;
962 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
963 SERVICE_QUERY_STATUS
))
965 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
966 return ERROR_ACCESS_DENIED
;
969 lpService
= hSvc
->ServiceEntry
;
970 if (lpService
== NULL
)
972 DPRINT1("lpService == NULL!\n");
973 return ERROR_INVALID_HANDLE
;
976 /* Return service status information */
977 RtlCopyMemory(lpServiceStatus
,
979 sizeof(SERVICE_STATUS
));
981 return ERROR_SUCCESS
;
986 ScmIsValidServiceState(DWORD dwCurrentState
)
988 switch (dwCurrentState
)
990 case SERVICE_STOPPED
:
991 case SERVICE_START_PENDING
:
992 case SERVICE_STOP_PENDING
:
993 case SERVICE_RUNNING
:
994 case SERVICE_CONTINUE_PENDING
:
995 case SERVICE_PAUSE_PENDING
:
1006 DWORD
RSetServiceStatus(
1007 handle_t BindingHandle
,
1008 SC_RPC_HANDLE hServiceStatus
,
1009 LPSERVICE_STATUS lpServiceStatus
)
1013 DPRINT("RSetServiceStatus() called\n");
1014 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1015 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1016 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1017 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1018 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1019 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1020 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1021 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1023 if (hServiceStatus
== 0)
1025 DPRINT1("hServiceStatus == NULL!\n");
1026 return ERROR_INVALID_HANDLE
;
1029 lpService
= ScmGetServiceEntryByClientHandle((ULONG
)hServiceStatus
);
1030 if (lpService
== NULL
)
1032 DPRINT1("lpService == NULL!\n");
1033 return ERROR_INVALID_HANDLE
;
1036 /* Check current state */
1037 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1039 DPRINT1("Invalid service state!\n");
1040 return ERROR_INVALID_DATA
;
1043 /* Check service type */
1044 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1045 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1047 DPRINT1("Invalid service type!\n");
1048 return ERROR_INVALID_DATA
;
1051 /* Check accepted controls */
1052 if (lpServiceStatus
->dwControlsAccepted
== 0 ||
1053 lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1055 DPRINT1("Invalid controls accepted!\n");
1056 return ERROR_INVALID_DATA
;
1060 RtlCopyMemory(&lpService
->Status
,
1062 sizeof(SERVICE_STATUS
));
1064 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1065 DPRINT("RSetServiceStatus() done\n");
1067 return ERROR_SUCCESS
;
1072 DWORD
RUnlockServiceDatabase(
1073 handle_t BindingHandle
,
1077 return ERROR_SUCCESS
;
1082 DWORD
RNotifyBootConfigStatus(
1083 handle_t BindingHandle
,
1084 SVCCTL_HANDLEW lpMachineName
,
1085 DWORD BootAcceptable
)
1088 return ERROR_CALL_NOT_IMPLEMENTED
;
1093 DWORD
RI_ScSetServiceBitsW(
1094 handle_t BindingHandle
,
1095 SC_RPC_HANDLE hServiceStatus
,
1096 DWORD dwServiceBits
,
1098 int bUpdateImmediately
,
1102 return ERROR_CALL_NOT_IMPLEMENTED
;
1107 DWORD
RChangeServiceConfigW(
1108 handle_t BindingHandle
,
1109 SC_RPC_HANDLE hService
,
1110 DWORD dwServiceType
,
1112 DWORD dwErrorControl
,
1113 LPWSTR lpBinaryPathName
,
1114 LPWSTR lpLoadOrderGroup
,
1116 LPBYTE lpDependencies
,
1118 LPWSTR lpServiceStartName
,
1121 LPWSTR lpDisplayName
)
1123 DWORD dwError
= ERROR_SUCCESS
;
1124 PSERVICE_HANDLE hSvc
;
1125 PSERVICE lpService
= NULL
;
1126 HKEY hServiceKey
= NULL
;
1127 LPWSTR lpDisplayNameW
= NULL
;
1129 DPRINT("RChangeServiceConfigW() called\n");
1130 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1131 DPRINT("dwStartType = %lu\n", dwStartType
);
1132 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1133 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1134 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1135 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1138 return ERROR_SHUTDOWN_IN_PROGRESS
;
1140 hSvc
= (PSERVICE_HANDLE
)hService
;
1141 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1143 DPRINT1("Invalid handle tag!\n");
1144 return ERROR_INVALID_HANDLE
;
1147 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1148 SERVICE_CHANGE_CONFIG
))
1150 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1151 return ERROR_ACCESS_DENIED
;
1154 lpService
= hSvc
->ServiceEntry
;
1155 if (lpService
== NULL
)
1157 DPRINT1("lpService == NULL!\n");
1158 return ERROR_INVALID_HANDLE
;
1161 /* FIXME: Lock database exclusively */
1163 if (lpService
->bDeleted
)
1165 /* FIXME: Unlock database */
1166 DPRINT1("The service has already been marked for delete!\n");
1167 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1170 /* Open the service key */
1171 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1174 if (dwError
!= ERROR_SUCCESS
)
1177 /* Write service data to the registry */
1178 /* Set the display name */
1179 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1181 RegSetValueExW(hServiceKey
,
1185 (LPBYTE
)lpDisplayName
,
1186 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1188 /* Update the display name */
1189 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1191 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1192 if (lpDisplayNameW
== NULL
)
1194 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1198 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1199 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1201 lpService
->lpDisplayName
= lpDisplayNameW
;
1204 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1206 /* Set the service type */
1207 dwError
= RegSetValueExW(hServiceKey
,
1211 (LPBYTE
)&dwServiceType
,
1213 if (dwError
!= ERROR_SUCCESS
)
1216 lpService
->Status
.dwServiceType
= dwServiceType
;
1219 if (dwStartType
!= SERVICE_NO_CHANGE
)
1221 /* Set the start value */
1222 dwError
= RegSetValueExW(hServiceKey
,
1226 (LPBYTE
)&dwStartType
,
1228 if (dwError
!= ERROR_SUCCESS
)
1231 lpService
->dwStartType
= dwStartType
;
1234 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1236 /* Set the error control value */
1237 dwError
= RegSetValueExW(hServiceKey
,
1241 (LPBYTE
)&dwErrorControl
,
1243 if (dwError
!= ERROR_SUCCESS
)
1246 lpService
->dwErrorControl
= dwErrorControl
;
1250 /* FIXME: set the new ImagePath value */
1252 /* Set the image path */
1253 if (dwServiceType
& SERVICE_WIN32
)
1255 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1257 dwError
= RegSetValueExW(hServiceKey
,
1261 (LPBYTE
)lpBinaryPathName
,
1262 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1263 if (dwError
!= ERROR_SUCCESS
)
1267 else if (dwServiceType
& SERVICE_DRIVER
)
1269 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1271 dwError
= RegSetValueExW(hServiceKey
,
1275 (LPBYTE
)lpImagePath
,
1276 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1277 if (dwError
!= ERROR_SUCCESS
)
1283 /* Set the group name */
1284 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1286 dwError
= RegSetValueExW(hServiceKey
,
1290 (LPBYTE
)lpLoadOrderGroup
,
1291 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1292 if (dwError
!= ERROR_SUCCESS
)
1294 /* FIXME: Update lpService->lpServiceGroup */
1297 if (lpdwTagId
!= NULL
)
1299 dwError
= ScmAssignNewTag(lpService
);
1300 if (dwError
!= ERROR_SUCCESS
)
1303 dwError
= RegSetValueExW(hServiceKey
,
1307 (LPBYTE
)&lpService
->dwTag
,
1309 if (dwError
!= ERROR_SUCCESS
)
1312 *lpdwTagId
= lpService
->dwTag
;
1315 /* Write dependencies */
1316 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1318 dwError
= ScmWriteDependencies(hServiceKey
,
1319 (LPWSTR
)lpDependencies
,
1321 if (dwError
!= ERROR_SUCCESS
)
1325 if (lpPassword
!= NULL
)
1327 /* FIXME: Write password */
1330 /* FIXME: Unlock database */
1333 if (hServiceKey
!= NULL
)
1334 RegCloseKey(hServiceKey
);
1336 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1342 /* Create a path suitable for the bootloader out of the full path */
1344 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1346 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1349 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1350 OBJECT_ATTRIBUTES ObjectAttributes
;
1352 HANDLE SymbolicLinkHandle
;
1354 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1356 ServiceNameLen
= wcslen(CanonName
);
1358 /* First check, if it's already good */
1359 if (ServiceNameLen
> 12 &&
1360 !wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1362 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1363 if (*RelativeName
== NULL
)
1365 DPRINT1("Error allocating memory for boot driver name!\n");
1366 return ERROR_NOT_ENOUGH_MEMORY
;
1370 wcscpy(*RelativeName
, CanonName
);
1372 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1373 return ERROR_SUCCESS
;
1376 /* If it has %SystemRoot% prefix, substitute it to \System*/
1377 if (ServiceNameLen
> 13 &&
1378 !wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1380 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1381 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1383 if (*RelativeName
== NULL
)
1385 DPRINT1("Error allocating memory for boot driver name!\n");
1386 return ERROR_NOT_ENOUGH_MEMORY
;
1390 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1391 wcscat(*RelativeName
, CanonName
+ 13);
1393 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1394 return ERROR_SUCCESS
;
1397 /* Get buffer size needed for expanding env strings */
1398 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1400 if (BufferSize
<= 1)
1402 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1403 return ERROR_INVALID_ENVIRONMENT
;
1406 /* Allocate memory, since the size is known now */
1407 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1410 DPRINT1("Error allocating memory for boot driver name!\n");
1411 return ERROR_NOT_ENOUGH_MEMORY
;
1415 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1418 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1419 LocalFree(Expanded
);
1420 return ERROR_NOT_ENOUGH_MEMORY
;
1423 /* Convert to NY-style path */
1424 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1426 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1427 return ERROR_INVALID_ENVIRONMENT
;
1430 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1432 /* No need to keep the dos-path anymore */
1433 LocalFree(Expanded
);
1435 /* Copy it to the allocated place */
1436 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1439 DPRINT1("Error allocating memory for boot driver name!\n");
1440 return ERROR_NOT_ENOUGH_MEMORY
;
1443 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1444 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1445 Expanded
[ExpandedLen
] = 0;
1447 if (ServiceNameLen
> ExpandedLen
&&
1448 !wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1450 /* Only \SystemRoot\ is missing */
1451 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1452 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1453 if (*RelativeName
== NULL
)
1455 DPRINT1("Error allocating memory for boot driver name!\n");
1456 LocalFree(Expanded
);
1457 return ERROR_NOT_ENOUGH_MEMORY
;
1460 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1461 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1463 RtlFreeUnicodeString(&NtPathName
);
1464 return ERROR_SUCCESS
;
1467 /* The most complex case starts here */
1468 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1469 InitializeObjectAttributes(&ObjectAttributes
,
1471 OBJ_CASE_INSENSITIVE
,
1475 /* Open this symlink */
1476 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1478 if (NT_SUCCESS(Status
))
1480 LinkTarget
.Length
= 0;
1481 LinkTarget
.MaximumLength
= 0;
1483 DPRINT("Opened symbolic link object\n");
1485 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1486 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1488 /* Check if required buffer size is sane */
1489 if (BufferSize
> 0xFFFD)
1491 DPRINT1("Too large buffer required\n");
1494 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1495 LocalFree(Expanded
);
1496 return ERROR_NOT_ENOUGH_MEMORY
;
1499 /* Alloc the string */
1500 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1501 if (!LinkTarget
.Buffer
)
1503 DPRINT1("Unable to alloc buffer\n");
1504 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1505 LocalFree(Expanded
);
1506 return ERROR_NOT_ENOUGH_MEMORY
;
1509 /* Do a real query now */
1510 LinkTarget
.Length
= BufferSize
;
1511 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1513 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1514 if (NT_SUCCESS(Status
))
1516 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1518 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1519 if ((ServiceNameLen
> ExpandedLen
) &&
1520 !wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1522 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1523 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1525 if (*RelativeName
== NULL
)
1527 DPRINT1("Unable to alloc buffer\n");
1528 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1529 LocalFree(Expanded
);
1530 RtlFreeUnicodeString(&NtPathName
);
1531 return ERROR_NOT_ENOUGH_MEMORY
;
1534 /* Copy it over, substituting the first part
1536 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1537 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1540 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1541 LocalFree(Expanded
);
1542 RtlFreeUnicodeString(&NtPathName
);
1544 /* Return success */
1545 return ERROR_SUCCESS
;
1549 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1550 LocalFree(Expanded
);
1551 RtlFreeUnicodeString(&NtPathName
);
1552 return ERROR_INVALID_PARAMETER
;
1557 DPRINT1("Error, Status = %08X\n", Status
);
1558 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1559 LocalFree(Expanded
);
1560 RtlFreeUnicodeString(&NtPathName
);
1561 return ERROR_INVALID_PARAMETER
;
1566 DPRINT1("Error, Status = %08X\n", Status
);
1567 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1568 LocalFree(Expanded
);
1569 RtlFreeUnicodeString(&NtPathName
);
1570 return ERROR_INVALID_PARAMETER
;
1575 DPRINT1("Error, Status = %08X\n", Status
);
1576 LocalFree(Expanded
);
1577 return ERROR_INVALID_PARAMETER
;
1581 *RelativeName
= NULL
;
1582 return ERROR_INVALID_PARAMETER
;
1586 ScmCanonDriverImagePath(DWORD dwStartType
,
1587 wchar_t *lpServiceName
,
1588 wchar_t **lpCanonName
)
1590 DWORD ServiceNameLen
, Result
;
1591 UNICODE_STRING NtServiceName
;
1592 WCHAR
*RelativeName
;
1593 WCHAR
*SourceName
= lpServiceName
;
1595 /* Calculate the length of the service's name */
1596 ServiceNameLen
= wcslen(lpServiceName
);
1598 /* 12 is wcslen(L"\\SystemRoot\\") */
1599 if (ServiceNameLen
> 12 &&
1600 !wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1602 /* SystemRoot prefix is already included */
1604 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1606 if (*lpCanonName
== NULL
)
1608 DPRINT1("Error allocating memory for canonized service name!\n");
1609 return ERROR_NOT_ENOUGH_MEMORY
;
1612 /* If it's a boot-time driver, it must be systemroot relative */
1613 if (dwStartType
== SERVICE_BOOT_START
)
1617 wcscpy(*lpCanonName
, SourceName
);
1619 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1623 /* Check if it has %SystemRoot% (len=13) */
1624 if (ServiceNameLen
> 13 &&
1625 !wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1627 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1628 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1630 if (*lpCanonName
== NULL
)
1632 DPRINT1("Error allocating memory for canonized service name!\n");
1633 return ERROR_NOT_ENOUGH_MEMORY
;
1636 /* If it's a boot-time driver, it must be systemroot relative */
1637 if (dwStartType
== SERVICE_BOOT_START
)
1638 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1640 wcscat(*lpCanonName
, lpServiceName
+ 13);
1642 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1646 /* Check if it's a relative path name */
1647 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1649 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1651 if (*lpCanonName
== NULL
)
1653 DPRINT1("Error allocating memory for canonized service name!\n");
1654 return ERROR_NOT_ENOUGH_MEMORY
;
1657 /* Just copy it over without changing */
1658 wcscpy(*lpCanonName
, lpServiceName
);
1663 /* It seems to be a DOS path, convert it */
1664 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1666 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1667 return ERROR_INVALID_PARAMETER
;
1670 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1672 if (*lpCanonName
== NULL
)
1674 DPRINT1("Error allocating memory for canonized service name!\n");
1675 RtlFreeUnicodeString(&NtServiceName
);
1676 return ERROR_NOT_ENOUGH_MEMORY
;
1679 /* Copy the string */
1680 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1682 /* The unicode string is not needed anymore */
1683 RtlFreeUnicodeString(&NtServiceName
);
1685 if (dwStartType
!= SERVICE_BOOT_START
)
1687 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1691 /* The service is boot-started, so must be relative */
1692 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1695 /* There is a problem, free name and return */
1696 LocalFree(*lpCanonName
);
1697 DPRINT1("Error converting named!\n");
1701 ASSERT(RelativeName
);
1703 /* Copy that string */
1704 wcscpy(*lpCanonName
, RelativeName
+ 12);
1706 /* Free the allocated buffer */
1707 LocalFree(RelativeName
);
1709 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1717 DWORD
RCreateServiceW(
1718 handle_t BindingHandle
,
1719 SC_RPC_HANDLE hSCManager
,
1720 LPWSTR lpServiceName
,
1721 LPWSTR lpDisplayName
,
1722 DWORD dwDesiredAccess
,
1723 DWORD dwServiceType
,
1725 DWORD dwErrorControl
,
1726 LPWSTR lpBinaryPathName
,
1727 LPWSTR lpLoadOrderGroup
,
1729 LPBYTE lpDependencies
,
1731 LPWSTR lpServiceStartName
,
1734 LPSC_RPC_HANDLE lpServiceHandle
)
1736 PMANAGER_HANDLE hManager
;
1737 DWORD dwError
= ERROR_SUCCESS
;
1738 PSERVICE lpService
= NULL
;
1739 SC_HANDLE hServiceHandle
= NULL
;
1740 LPWSTR lpImagePath
= NULL
;
1741 HKEY hServiceKey
= NULL
;
1743 DPRINT("RCreateServiceW() called\n");
1744 DPRINT("lpServiceName = %S\n", lpServiceName
);
1745 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1746 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1747 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1748 DPRINT("dwStartType = %lu\n", dwStartType
);
1749 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1750 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1751 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1754 return ERROR_SHUTDOWN_IN_PROGRESS
;
1756 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1757 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1759 DPRINT1("Invalid manager handle!\n");
1760 return ERROR_INVALID_HANDLE
;
1763 /* Check access rights */
1764 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1765 SC_MANAGER_CREATE_SERVICE
))
1767 DPRINT1("Insufficient access rights! 0x%lx\n",
1768 hManager
->Handle
.DesiredAccess
);
1769 return ERROR_ACCESS_DENIED
;
1772 if (wcslen(lpServiceName
) == 0)
1774 return ERROR_INVALID_NAME
;
1777 if (wcslen(lpBinaryPathName
) == 0)
1779 return ERROR_INVALID_PARAMETER
;
1782 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1783 (lpServiceStartName
))
1785 return ERROR_INVALID_PARAMETER
;
1788 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1789 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1790 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1792 return ERROR_INVALID_PARAMETER
;
1795 if (dwStartType
> SERVICE_DISABLED
)
1797 return ERROR_INVALID_PARAMETER
;
1800 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1803 /* check if it is marked for deletion */
1804 if (lpService
->bDeleted
)
1805 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1806 /* Return Error exist */
1807 return ERROR_SERVICE_EXISTS
;
1810 if (lpDisplayName
!= NULL
&&
1811 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1812 return ERROR_DUPLICATE_SERVICE_NAME
;
1814 if (dwServiceType
& SERVICE_DRIVER
)
1816 dwError
= ScmCanonDriverImagePath(dwStartType
,
1819 if (dwError
!= ERROR_SUCCESS
)
1824 if (dwStartType
== SERVICE_BOOT_START
||
1825 dwStartType
== SERVICE_SYSTEM_START
)
1827 return ERROR_INVALID_PARAMETER
;
1831 /* Allocate a new service entry */
1832 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1834 if (dwError
!= ERROR_SUCCESS
)
1837 /* Fill the new service entry */
1838 lpService
->Status
.dwServiceType
= dwServiceType
;
1839 lpService
->dwStartType
= dwStartType
;
1840 lpService
->dwErrorControl
= dwErrorControl
;
1842 /* Fill the display name */
1843 if (lpDisplayName
!= NULL
&&
1844 *lpDisplayName
!= 0 &&
1845 wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1847 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1848 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1849 if (lpService
->lpDisplayName
== NULL
)
1851 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1854 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1857 /* Assign the service to a group */
1858 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1860 dwError
= ScmSetServiceGroup(lpService
,
1862 if (dwError
!= ERROR_SUCCESS
)
1866 /* Assign a new tag */
1867 if (lpdwTagId
!= NULL
)
1869 dwError
= ScmAssignNewTag(lpService
);
1870 if (dwError
!= ERROR_SUCCESS
)
1874 /* Write service data to the registry */
1875 /* Create the service key */
1876 dwError
= ScmCreateServiceKey(lpServiceName
,
1879 if (dwError
!= ERROR_SUCCESS
)
1882 /* Set the display name */
1883 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1885 RegSetValueExW(hServiceKey
,
1889 (LPBYTE
)lpDisplayName
,
1890 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1893 /* Set the service type */
1894 dwError
= RegSetValueExW(hServiceKey
,
1898 (LPBYTE
)&dwServiceType
,
1900 if (dwError
!= ERROR_SUCCESS
)
1903 /* Set the start value */
1904 dwError
= RegSetValueExW(hServiceKey
,
1908 (LPBYTE
)&dwStartType
,
1910 if (dwError
!= ERROR_SUCCESS
)
1913 /* Set the error control value */
1914 dwError
= RegSetValueExW(hServiceKey
,
1918 (LPBYTE
)&dwErrorControl
,
1920 if (dwError
!= ERROR_SUCCESS
)
1923 /* Set the image path */
1924 if (dwServiceType
& SERVICE_WIN32
)
1926 dwError
= RegSetValueExW(hServiceKey
,
1930 (LPBYTE
)lpBinaryPathName
,
1931 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1932 if (dwError
!= ERROR_SUCCESS
)
1935 else if (dwServiceType
& SERVICE_DRIVER
)
1937 dwError
= RegSetValueExW(hServiceKey
,
1941 (LPBYTE
)lpImagePath
,
1942 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1943 if (dwError
!= ERROR_SUCCESS
)
1947 /* Set the group name */
1948 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1950 dwError
= RegSetValueExW(hServiceKey
,
1954 (LPBYTE
)lpLoadOrderGroup
,
1955 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1956 if (dwError
!= ERROR_SUCCESS
)
1960 if (lpdwTagId
!= NULL
)
1962 dwError
= RegSetValueExW(hServiceKey
,
1966 (LPBYTE
)&lpService
->dwTag
,
1968 if (dwError
!= ERROR_SUCCESS
)
1972 /* Write dependencies */
1973 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1975 dwError
= ScmWriteDependencies(hServiceKey
,
1976 (LPWSTR
)lpDependencies
,
1978 if (dwError
!= ERROR_SUCCESS
)
1982 /* If a non driver and NULL for lpServiceName, write ObjectName as LocalSystem */
1983 if ((dwServiceType
& SERVICE_WIN32
) && (!lpServiceName
))
1985 dwError
= RegSetValueExW(hServiceKey
,
1989 (LPBYTE
)L
"LocalSystem",
1991 if (dwError
!= ERROR_SUCCESS
)
1995 if (lpPassword
!= NULL
)
1997 /* FIXME: Write password */
2000 dwError
= ScmCreateServiceHandle(lpService
,
2002 if (dwError
!= ERROR_SUCCESS
)
2005 dwError
= ScmCheckAccess(hServiceHandle
,
2007 if (dwError
!= ERROR_SUCCESS
)
2010 lpService
->dwRefCount
= 1;
2011 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2014 if (hServiceKey
!= NULL
)
2015 RegCloseKey(hServiceKey
);
2017 if (dwError
== ERROR_SUCCESS
)
2019 DPRINT("hService %p\n", hServiceHandle
);
2020 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2022 if (lpdwTagId
!= NULL
)
2023 *lpdwTagId
= lpService
->dwTag
;
2027 /* Release the display name buffer */
2028 if (lpService
->lpServiceName
!= NULL
)
2029 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2033 /* Remove the service handle */
2034 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2037 if (lpService
!= NULL
)
2039 /* FIXME: remove the service entry */
2043 if (lpImagePath
!= NULL
)
2044 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2046 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2053 DWORD
REnumDependentServicesW(
2054 handle_t BindingHandle
,
2055 SC_RPC_HANDLE hService
,
2056 DWORD dwServiceState
,
2059 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2060 LPBOUNDED_DWORD_256K lpServicesReturned
)
2062 DWORD dwError
= ERROR_SUCCESS
;
2063 DWORD dwServicesReturned
= 0;
2064 DWORD dwServiceCount
;
2065 HKEY hServicesKey
= NULL
;
2066 LPSC_RPC_HANDLE hSCObject
;
2067 PSERVICE_HANDLE hSvc
;
2068 PSERVICE lpService
= NULL
;
2069 PSERVICE
*lpServicesArray
= NULL
;
2070 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2073 *pcbBytesNeeded
= 0;
2074 *lpServicesReturned
= 0;
2076 DPRINT("REnumDependentServicesW() called\n");
2078 hSCObject
= &hService
;
2079 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
2080 lpService
= hSvc
->ServiceEntry
;
2082 /* Check access rights */
2083 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2084 SC_MANAGER_ENUMERATE_SERVICE
))
2086 DPRINT1("Insufficient access rights! 0x%lx\n",
2087 hSvc
->Handle
.DesiredAccess
);
2088 return ERROR_ACCESS_DENIED
;
2091 /* Open the Services Reg key */
2092 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2093 L
"System\\CurrentControlSet\\Services",
2097 if (dwError
!= ERROR_SUCCESS
)
2100 /* First determine the bytes needed and get the number of dependent services */
2101 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2106 &dwServicesReturned
);
2107 if (dwError
!= ERROR_SUCCESS
)
2110 /* If buffer size is less than the bytes needed or pointer is null */
2111 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2113 dwError
= ERROR_MORE_DATA
;
2117 /* Allocate memory for array of service pointers */
2118 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2120 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2121 if (!lpServicesArray
)
2123 DPRINT1("Could not allocate a buffer!!\n");
2124 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2128 dwServicesReturned
= 0;
2129 *pcbBytesNeeded
= 0;
2131 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2136 &dwServicesReturned
);
2137 if (dwError
!= ERROR_SUCCESS
)
2142 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2143 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2145 /* Copy EnumDepenedentService to Buffer */
2146 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2148 lpService
= lpServicesArray
[dwServiceCount
];
2150 /* Copy status info */
2151 memcpy(&lpServicesPtr
->ServiceStatus
,
2153 sizeof(SERVICE_STATUS
));
2155 /* Copy display name */
2156 wcscpy(lpStr
, lpService
->lpDisplayName
);
2157 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2158 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2160 /* Copy service name */
2161 wcscpy(lpStr
, lpService
->lpServiceName
);
2162 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2163 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2168 *lpServicesReturned
= dwServicesReturned
;
2171 if (lpServicesArray
!= NULL
)
2172 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2174 RegCloseKey(hServicesKey
);
2176 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2183 DWORD
REnumServicesStatusW(
2184 handle_t BindingHandle
,
2185 SC_RPC_HANDLE hSCManager
,
2186 DWORD dwServiceType
,
2187 DWORD dwServiceState
,
2190 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2191 LPBOUNDED_DWORD_256K lpServicesReturned
,
2192 LPBOUNDED_DWORD_256K lpResumeHandle
)
2194 PMANAGER_HANDLE hManager
;
2196 DWORD dwError
= ERROR_SUCCESS
;
2197 PLIST_ENTRY ServiceEntry
;
2198 PSERVICE CurrentService
;
2200 DWORD dwRequiredSize
;
2201 DWORD dwServiceCount
;
2203 DWORD dwLastResumeCount
= 0;
2204 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2207 DPRINT("REnumServicesStatusW() called\n");
2210 return ERROR_SHUTDOWN_IN_PROGRESS
;
2212 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2213 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2215 DPRINT1("Invalid manager handle!\n");
2216 return ERROR_INVALID_HANDLE
;
2219 *pcbBytesNeeded
= 0;
2220 *lpServicesReturned
= 0;
2222 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2224 DPRINT("Not a valid Service Type!\n");
2225 return ERROR_INVALID_PARAMETER
;
2228 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2230 DPRINT("Not a valid Service State!\n");
2231 return ERROR_INVALID_PARAMETER
;
2234 /* Check access rights */
2235 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2236 SC_MANAGER_ENUMERATE_SERVICE
))
2238 DPRINT1("Insufficient access rights! 0x%lx\n",
2239 hManager
->Handle
.DesiredAccess
);
2240 return ERROR_ACCESS_DENIED
;
2243 if (lpResumeHandle
) dwLastResumeCount
= *lpResumeHandle
;
2245 /* FIXME: Lock the service list shared */
2247 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2248 if (lpService
== NULL
)
2250 dwError
= ERROR_SUCCESS
;
2257 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2258 ServiceEntry
!= &ServiceListHead
;
2259 ServiceEntry
= ServiceEntry
->Flink
)
2261 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2265 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2268 dwState
= SERVICE_ACTIVE
;
2269 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2270 dwState
= SERVICE_INACTIVE
;
2272 if ((dwState
& dwServiceState
) == 0)
2275 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2276 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2277 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2279 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2281 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2285 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2286 dwRequiredSize
+= dwSize
;
2288 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2291 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2292 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2295 ServiceEntry
!= &ServiceListHead
;
2296 ServiceEntry
= ServiceEntry
->Flink
)
2298 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2302 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2305 dwState
= SERVICE_ACTIVE
;
2306 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2307 dwState
= SERVICE_INACTIVE
;
2309 if ((dwState
& dwServiceState
) == 0)
2312 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2313 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2314 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2316 dwError
= ERROR_MORE_DATA
;
2319 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2321 if (lpResumeHandle
) *lpResumeHandle
= dwLastResumeCount
;
2322 *lpServicesReturned
= dwServiceCount
;
2323 *pcbBytesNeeded
= dwRequiredSize
;
2325 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2326 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2327 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2330 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2331 ServiceEntry
!= &ServiceListHead
;
2332 ServiceEntry
= ServiceEntry
->Flink
)
2334 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2338 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2341 dwState
= SERVICE_ACTIVE
;
2342 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2343 dwState
= SERVICE_INACTIVE
;
2345 if ((dwState
& dwServiceState
) == 0)
2348 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2349 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2350 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2352 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2355 /* Copy the service name */
2356 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2357 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2358 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2360 /* Copy the display name */
2361 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2362 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2363 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2365 /* Copy the status information */
2366 memcpy(&lpStatusPtr
->ServiceStatus
,
2367 &CurrentService
->Status
,
2368 sizeof(SERVICE_STATUS
));
2371 dwRequiredSize
+= dwSize
;
2374 if (dwError
!= ERROR_MORE_DATA
)
2376 *pcbBytesNeeded
= 0;
2377 if (lpResumeHandle
) *lpResumeHandle
= 0;
2381 /* FIXME: Unlock the service list */
2383 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2390 DWORD
ROpenSCManagerW(
2391 handle_t BindingHandle
,
2392 LPWSTR lpMachineName
,
2393 LPWSTR lpDatabaseName
,
2394 DWORD dwDesiredAccess
,
2395 LPSC_RPC_HANDLE lpScHandle
)
2400 DPRINT("ROpenSCManagerW() called\n");
2401 DPRINT("lpMachineName = %p\n", lpMachineName
);
2402 DPRINT("lpMachineName: %S\n", lpMachineName
);
2403 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2404 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2405 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2408 return ERROR_SHUTDOWN_IN_PROGRESS
;
2411 return ERROR_INVALID_PARAMETER
;
2413 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2415 if (dwError
!= ERROR_SUCCESS
)
2417 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2421 /* Check the desired access */
2422 dwError
= ScmCheckAccess(hHandle
,
2423 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2424 if (dwError
!= ERROR_SUCCESS
)
2426 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2427 HeapFree(GetProcessHeap(), 0, hHandle
);
2431 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2432 DPRINT("*hScm = %p\n", *lpScHandle
);
2434 DPRINT("ROpenSCManagerW() done\n");
2436 return ERROR_SUCCESS
;
2441 DWORD
ROpenServiceW(
2442 handle_t BindingHandle
,
2443 SC_RPC_HANDLE hSCManager
,
2444 LPWSTR lpServiceName
,
2445 DWORD dwDesiredAccess
,
2446 LPSC_RPC_HANDLE lpServiceHandle
)
2449 PMANAGER_HANDLE hManager
;
2453 DPRINT("ROpenServiceW() called\n");
2454 DPRINT("hSCManager = %p\n", hSCManager
);
2455 DPRINT("lpServiceName = %p\n", lpServiceName
);
2456 DPRINT("lpServiceName: %S\n", lpServiceName
);
2457 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2460 return ERROR_SHUTDOWN_IN_PROGRESS
;
2462 if (!lpServiceHandle
)
2463 return ERROR_INVALID_PARAMETER
;
2466 return ERROR_INVALID_ADDRESS
;
2468 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2469 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2471 DPRINT1("Invalid manager handle!\n");
2472 return ERROR_INVALID_HANDLE
;
2475 /* FIXME: Lock the service list */
2477 /* Get service database entry */
2478 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2479 if (lpService
== NULL
)
2481 DPRINT("Could not find a service!\n");
2482 return ERROR_SERVICE_DOES_NOT_EXIST
;
2485 /* Create a service handle */
2486 dwError
= ScmCreateServiceHandle(lpService
,
2488 if (dwError
!= ERROR_SUCCESS
)
2490 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2494 /* Check the desired access */
2495 dwError
= ScmCheckAccess(hHandle
,
2497 if (dwError
!= ERROR_SUCCESS
)
2499 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2500 HeapFree(GetProcessHeap(), 0, hHandle
);
2504 lpService
->dwRefCount
++;
2505 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2507 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2508 DPRINT("*hService = %p\n", *lpServiceHandle
);
2510 DPRINT("ROpenServiceW() done\n");
2512 return ERROR_SUCCESS
;
2517 DWORD
RQueryServiceConfigW(
2518 handle_t BindingHandle
,
2519 SC_RPC_HANDLE hService
,
2520 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2522 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2524 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2525 DWORD dwError
= ERROR_SUCCESS
;
2526 PSERVICE_HANDLE hSvc
;
2527 PSERVICE lpService
= NULL
;
2528 HKEY hServiceKey
= NULL
;
2529 LPWSTR lpImagePath
= NULL
;
2530 LPWSTR lpServiceStartName
= NULL
;
2531 DWORD dwRequiredSize
;
2532 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2533 WCHAR lpEmptyString
[] = {0,0};
2536 DPRINT("RQueryServiceConfigW() called\n");
2539 return ERROR_SHUTDOWN_IN_PROGRESS
;
2541 hSvc
= (PSERVICE_HANDLE
)hService
;
2542 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2544 DPRINT1("Invalid handle tag!\n");
2545 return ERROR_INVALID_HANDLE
;
2548 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2549 SERVICE_QUERY_CONFIG
))
2551 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2552 return ERROR_ACCESS_DENIED
;
2555 lpService
= hSvc
->ServiceEntry
;
2556 if (lpService
== NULL
)
2558 DPRINT1("lpService == NULL!\n");
2559 return ERROR_INVALID_HANDLE
;
2562 /* FIXME: Lock the service database shared */
2564 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2567 if (dwError
!= ERROR_SUCCESS
)
2570 dwError
= ScmReadString(hServiceKey
,
2573 if (dwError
!= ERROR_SUCCESS
)
2576 ScmReadString(hServiceKey
,
2578 &lpServiceStartName
);
2580 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2582 if (lpImagePath
!= NULL
)
2583 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2585 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2587 if (lpService
->lpGroup
!= NULL
)
2588 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2590 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2592 /* FIXME: Add Dependencies length*/
2594 if (lpServiceStartName
!= NULL
)
2595 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2597 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2599 if (lpService
->lpDisplayName
!= NULL
)
2600 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2602 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2604 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2606 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2610 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2611 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2612 lpConfig
->dwStartType
= lpService
->dwStartType
;
2613 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2614 lpConfig
->dwTagId
= lpService
->dwTag
;
2616 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2618 if (lpImagePath
!= NULL
)
2620 wcscpy(lpStr
, lpImagePath
);
2624 wcscpy(lpStr
, lpEmptyString
);
2627 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2628 lpStr
+= (wcslen(lpStr
) + 1);
2630 if (lpService
->lpGroup
!= NULL
)
2632 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2636 wcscpy(lpStr
, lpEmptyString
);
2639 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2640 lpStr
+= (wcslen(lpStr
) + 1);
2642 /* FIXME: Append Dependencies */
2643 wcscpy(lpStr
, lpEmptyString
);
2645 lpStr
+= (wcslen(lpStr
) + 1);
2646 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2648 if (lpServiceStartName
!= NULL
)
2650 wcscpy(lpStr
, lpServiceStartName
);
2654 wcscpy(lpStr
, lpEmptyString
);
2657 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2658 lpStr
+= (wcslen(lpStr
) + 1);
2660 if (lpService
->lpDisplayName
!= NULL
)
2662 wcscpy(lpStr
, lpService
->lpDisplayName
);
2666 wcscpy(lpStr
, lpEmptyString
);
2669 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2672 if (pcbBytesNeeded
!= NULL
)
2673 *pcbBytesNeeded
= dwRequiredSize
;
2676 if (lpImagePath
!= NULL
)
2677 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2679 if (lpServiceStartName
!= NULL
)
2680 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2682 if (hServiceKey
!= NULL
)
2683 RegCloseKey(hServiceKey
);
2685 /* FIXME: Unlock the service database */
2687 DPRINT("RQueryServiceConfigW() done\n");
2694 DWORD
RQueryServiceLockStatusW(
2695 handle_t BindingHandle
,
2696 SC_RPC_HANDLE hSCManager
,
2697 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2699 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2702 return ERROR_CALL_NOT_IMPLEMENTED
;
2707 DWORD
RStartServiceW(
2708 handle_t BindingHandle
,
2709 SC_RPC_HANDLE hService
,
2711 LPSTRING_PTRSW argv
)
2713 DWORD dwError
= ERROR_SUCCESS
;
2714 PSERVICE_HANDLE hSvc
;
2715 PSERVICE lpService
= NULL
;
2717 DPRINT("RStartServiceW() called\n");
2720 return ERROR_SHUTDOWN_IN_PROGRESS
;
2722 hSvc
= (PSERVICE_HANDLE
)hService
;
2723 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2725 DPRINT1("Invalid handle tag!\n");
2726 return ERROR_INVALID_HANDLE
;
2729 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2732 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2733 return ERROR_ACCESS_DENIED
;
2736 lpService
= hSvc
->ServiceEntry
;
2737 if (lpService
== NULL
)
2739 DPRINT1("lpService == NULL!\n");
2740 return ERROR_INVALID_HANDLE
;
2743 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2744 return ERROR_SERVICE_DISABLED
;
2746 if (lpService
->bDeleted
)
2747 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2754 /* Start the service */
2755 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2762 DWORD
RGetServiceDisplayNameW(
2763 handle_t BindingHandle
,
2764 SC_RPC_HANDLE hSCManager
,
2765 LPWSTR lpServiceName
,
2766 LPWSTR lpDisplayName
,
2769 // PMANAGER_HANDLE hManager;
2774 DPRINT("RGetServiceDisplayNameW() called\n");
2775 DPRINT("hSCManager = %p\n", hSCManager
);
2776 DPRINT("lpServiceName: %S\n", lpServiceName
);
2777 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2778 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2780 // hManager = (PMANAGER_HANDLE)hSCManager;
2781 // if (hManager->Handle.Tag != MANAGER_TAG)
2783 // DPRINT1("Invalid manager handle!\n");
2784 // return ERROR_INVALID_HANDLE;
2787 /* Get service database entry */
2788 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2789 if (lpService
== NULL
)
2791 DPRINT1("Could not find a service!\n");
2793 /* If the service could not be found and lpcchBuffer is 0, windows
2794 puts null in lpDisplayName and puts 1 in lpcchBuffer */
2795 if (*lpcchBuffer
== 0)
2798 *lpDisplayName
= '\0';
2801 return ERROR_SERVICE_DOES_NOT_EXIST
;
2804 if (!lpService
->lpDisplayName
)
2806 dwLength
= wcslen(lpService
->lpServiceName
);
2808 if (lpServiceName
!= NULL
&&
2809 *lpcchBuffer
> dwLength
)
2811 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2816 dwLength
= wcslen(lpService
->lpDisplayName
);
2818 if (lpDisplayName
!= NULL
&&
2819 *lpcchBuffer
> dwLength
)
2821 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2825 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2827 *lpcchBuffer
= dwLength
;
2834 DWORD
RGetServiceKeyNameW(
2835 handle_t BindingHandle
,
2836 SC_RPC_HANDLE hSCManager
,
2837 LPWSTR lpDisplayName
,
2838 LPWSTR lpServiceName
,
2841 // PMANAGER_HANDLE hManager;
2846 DPRINT("RGetServiceKeyNameW() called\n");
2847 DPRINT("hSCManager = %p\n", hSCManager
);
2848 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2849 DPRINT("lpServiceName: %p\n", lpServiceName
);
2850 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2852 // hManager = (PMANAGER_HANDLE)hSCManager;
2853 // if (hManager->Handle.Tag != MANAGER_TAG)
2855 // DPRINT1("Invalid manager handle!\n");
2856 // return ERROR_INVALID_HANDLE;
2859 /* Get service database entry */
2860 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2861 if (lpService
== NULL
)
2863 DPRINT1("Could not find a service!\n");
2865 /* If the service could not be found and lpcchBuffer is 0, windows
2866 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2867 if (*lpcchBuffer
== 0)
2870 *lpServiceName
= '\0';
2873 return ERROR_SERVICE_DOES_NOT_EXIST
;
2876 dwLength
= wcslen(lpService
->lpServiceName
);
2878 if (lpServiceName
!= NULL
&&
2879 *lpcchBuffer
> dwLength
)
2881 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2882 *lpcchBuffer
= dwLength
;
2883 return ERROR_SUCCESS
;
2886 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2888 *lpcchBuffer
= dwLength
* 2;
2895 DWORD
RI_ScSetServiceBitsA(
2896 handle_t BindingHandle
,
2897 SC_RPC_HANDLE hServiceStatus
,
2898 DWORD dwServiceBits
,
2900 int bUpdateImmediately
,
2904 return ERROR_CALL_NOT_IMPLEMENTED
;
2909 DWORD
RChangeServiceConfigA(
2910 handle_t BindingHandle
,
2911 SC_RPC_HANDLE hService
,
2912 DWORD dwServiceType
,
2914 DWORD dwErrorControl
,
2915 LPSTR lpBinaryPathName
,
2916 LPSTR lpLoadOrderGroup
,
2918 LPSTR lpDependencies
,
2920 LPSTR lpServiceStartName
,
2923 LPSTR lpDisplayName
)
2925 DWORD dwError
= ERROR_SUCCESS
;
2926 PSERVICE_HANDLE hSvc
;
2927 PSERVICE lpService
= NULL
;
2928 HKEY hServiceKey
= NULL
;
2929 LPWSTR lpDisplayNameW
= NULL
;
2930 // LPWSTR lpBinaryPathNameW = NULL;
2931 LPWSTR lpLoadOrderGroupW
= NULL
;
2932 LPWSTR lpDependenciesW
= NULL
;
2933 // LPWSTR lpPasswordW = NULL;
2935 DPRINT("RChangeServiceConfigA() called\n");
2936 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2937 DPRINT("dwStartType = %lu\n", dwStartType
);
2938 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2939 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2940 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2941 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2944 return ERROR_SHUTDOWN_IN_PROGRESS
;
2946 hSvc
= (PSERVICE_HANDLE
)hService
;
2947 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2949 DPRINT1("Invalid handle tag!\n");
2950 return ERROR_INVALID_HANDLE
;
2953 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2954 SERVICE_CHANGE_CONFIG
))
2956 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2957 return ERROR_ACCESS_DENIED
;
2960 lpService
= hSvc
->ServiceEntry
;
2961 if (lpService
== NULL
)
2963 DPRINT1("lpService == NULL!\n");
2964 return ERROR_INVALID_HANDLE
;
2967 /* FIXME: Lock database exclusively */
2969 if (lpService
->bDeleted
)
2971 /* FIXME: Unlock database */
2972 DPRINT1("The service has already been marked for delete!\n");
2973 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2976 /* Open the service key */
2977 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2980 if (dwError
!= ERROR_SUCCESS
)
2983 /* Write service data to the registry */
2985 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2987 /* Set the display name */
2988 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2990 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2991 if (lpDisplayNameW
== NULL
)
2993 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2997 MultiByteToWideChar(CP_ACP
,
3002 wcslen(lpDisplayNameW
) + 1);
3004 RegSetValueExW(hServiceKey
,
3008 (LPBYTE
)lpDisplayNameW
,
3009 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3011 /* Update lpService->lpDisplayName */
3012 if (lpService
->lpDisplayName
)
3013 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3015 lpService
->lpDisplayName
= lpDisplayNameW
;
3018 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3020 /* Set the service type */
3021 dwError
= RegSetValueExW(hServiceKey
,
3025 (LPBYTE
)&dwServiceType
,
3027 if (dwError
!= ERROR_SUCCESS
)
3030 lpService
->Status
.dwServiceType
= dwServiceType
;
3033 if (dwStartType
!= SERVICE_NO_CHANGE
)
3035 /* Set the start value */
3036 dwError
= RegSetValueExW(hServiceKey
,
3040 (LPBYTE
)&dwStartType
,
3042 if (dwError
!= ERROR_SUCCESS
)
3045 lpService
->dwStartType
= dwStartType
;
3048 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3050 /* Set the error control value */
3051 dwError
= RegSetValueExW(hServiceKey
,
3055 (LPBYTE
)&dwErrorControl
,
3057 if (dwError
!= ERROR_SUCCESS
)
3060 lpService
->dwErrorControl
= dwErrorControl
;
3064 /* FIXME: set the new ImagePath value */
3066 /* Set the image path */
3067 if (dwServiceType
& SERVICE_WIN32
)
3069 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3071 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3072 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, wcslen(lpBinaryPathNameW
)+1);
3073 dwError
= RegSetValueExW(hServiceKey
,
3077 (LPBYTE
)lpBinaryPathNameW
,
3078 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3079 if (dwError
!= ERROR_SUCCESS
)
3083 else if (dwServiceType
& SERVICE_DRIVER
)
3085 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3087 dwError
= RegSetValueExW(hServiceKey
,
3091 (LPBYTE
)lpImagePath
,
3092 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3093 if (dwError
!= ERROR_SUCCESS
)
3099 /* Set the group name */
3100 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3102 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3104 (strlen(lpLoadOrderGroup
)+1) * sizeof(WCHAR
));
3105 if (lpLoadOrderGroupW
== NULL
)
3107 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3111 MultiByteToWideChar(CP_ACP
,
3116 wcslen(lpLoadOrderGroupW
) + 1);
3118 dwError
= RegSetValueExW(hServiceKey
,
3122 (LPBYTE
)lpLoadOrderGroupW
,
3123 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3124 if (dwError
!= ERROR_SUCCESS
)
3127 /* FIXME: Update lpService->lpServiceGroup */
3129 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3132 if (lpdwTagId
!= NULL
)
3134 dwError
= ScmAssignNewTag(lpService
);
3135 if (dwError
!= ERROR_SUCCESS
)
3138 dwError
= RegSetValueExW(hServiceKey
,
3142 (LPBYTE
)&lpService
->dwTag
,
3144 if (dwError
!= ERROR_SUCCESS
)
3147 *lpdwTagId
= lpService
->dwTag
;
3150 /* Write dependencies */
3151 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3153 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3155 (strlen(lpDependencies
)+1) * sizeof(WCHAR
));
3156 if (lpDependenciesW
== NULL
)
3158 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3162 MultiByteToWideChar(CP_ACP
,
3167 wcslen(lpDependenciesW
)+1);
3169 dwError
= ScmWriteDependencies(hServiceKey
,
3170 (LPWSTR
)lpDependenciesW
,
3173 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3176 if (lpPassword
!= NULL
)
3178 /* FIXME: Write password */
3181 /* FIXME: Unlock database */
3184 if (hServiceKey
!= NULL
)
3185 RegCloseKey(hServiceKey
);
3187 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3194 DWORD
RCreateServiceA(
3195 handle_t BindingHandle
,
3196 SC_RPC_HANDLE hSCManager
,
3197 LPSTR lpServiceName
,
3198 LPSTR lpDisplayName
,
3199 DWORD dwDesiredAccess
,
3200 DWORD dwServiceType
,
3202 DWORD dwErrorControl
,
3203 LPSTR lpBinaryPathName
,
3204 LPSTR lpLoadOrderGroup
,
3206 LPBYTE lpDependencies
,
3208 LPSTR lpServiceStartName
,
3211 LPSC_RPC_HANDLE lpServiceHandle
)
3214 return ERROR_CALL_NOT_IMPLEMENTED
;
3219 DWORD
REnumDependentServicesA(
3220 handle_t BindingHandle
,
3221 SC_RPC_HANDLE hService
,
3222 DWORD dwServiceState
,
3225 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3226 LPBOUNDED_DWORD_256K lpServicesReturned
)
3228 DWORD dwError
= ERROR_SUCCESS
;
3229 DWORD dwServicesReturned
= 0;
3230 DWORD dwServiceCount
;
3231 HKEY hServicesKey
= NULL
;
3232 LPSC_RPC_HANDLE hSCObject
;
3233 PSERVICE_HANDLE hSvc
;
3234 PSERVICE lpService
= NULL
;
3235 PSERVICE
*lpServicesArray
= NULL
;
3236 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3239 *pcbBytesNeeded
= 0;
3240 *lpServicesReturned
= 0;
3242 DPRINT("REnumDependentServicesA() called\n");
3244 hSCObject
= &hService
;
3245 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3246 lpService
= hSvc
->ServiceEntry
;
3248 /* Check access rights */
3249 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3250 SC_MANAGER_ENUMERATE_SERVICE
))
3252 DPRINT1("Insufficient access rights! 0x%lx\n",
3253 hSvc
->Handle
.DesiredAccess
);
3254 return ERROR_ACCESS_DENIED
;
3257 /* Open the Services Reg key */
3258 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3259 L
"System\\CurrentControlSet\\Services",
3264 if (dwError
!= ERROR_SUCCESS
) return dwError
;
3266 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3267 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3268 are the same for both. Verified in WINXP. */
3270 /* First determine the bytes needed and get the number of dependent services*/
3271 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3276 &dwServicesReturned
);
3277 if (dwError
!= ERROR_SUCCESS
)
3280 /* If buffer size is less than the bytes needed or pointer is null*/
3281 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3283 dwError
= ERROR_MORE_DATA
;
3287 /* Allocate memory for array of service pointers */
3288 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3290 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3291 if (!lpServicesArray
)
3293 DPRINT1("Could not allocate a buffer!!\n");
3294 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3298 dwServicesReturned
= 0;
3299 *pcbBytesNeeded
= 0;
3301 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3306 &dwServicesReturned
);
3307 if (dwError
!= ERROR_SUCCESS
)
3312 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3313 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3315 /* Copy EnumDepenedentService to Buffer */
3316 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3318 lpService
= lpServicesArray
[dwServiceCount
];
3320 /* Copy the status info */
3321 memcpy(&lpServicesPtr
->ServiceStatus
,
3323 sizeof(SERVICE_STATUS
));
3325 /* Copy display name */
3326 WideCharToMultiByte(CP_ACP
,
3328 lpService
->lpDisplayName
,
3331 wcslen(lpService
->lpDisplayName
),
3334 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3335 lpStr
+= strlen(lpStr
) + 1;
3337 /* Copy service name */
3338 WideCharToMultiByte(CP_ACP
,
3340 lpService
->lpServiceName
,
3343 wcslen(lpService
->lpServiceName
),
3346 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3347 lpStr
+= strlen(lpStr
) + 1;
3352 *lpServicesReturned
= dwServicesReturned
;
3355 if (lpServicesArray
)
3356 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3358 RegCloseKey(hServicesKey
);
3360 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3367 DWORD
REnumServicesStatusA(
3368 handle_t BindingHandle
,
3369 SC_RPC_HANDLE hSCManager
,
3370 DWORD dwServiceType
,
3371 DWORD dwServiceState
,
3374 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3375 LPBOUNDED_DWORD_256K lpServicesReturned
,
3376 LPBOUNDED_DWORD_256K lpResumeHandle
)
3378 PMANAGER_HANDLE hManager
;
3380 DWORD dwError
= ERROR_SUCCESS
;
3381 PLIST_ENTRY ServiceEntry
;
3382 PSERVICE CurrentService
;
3384 DWORD dwRequiredSize
;
3385 DWORD dwServiceCount
;
3387 DWORD dwLastResumeCount
= 0;
3388 LPENUM_SERVICE_STATUSA lpStatusPtr
;
3391 DPRINT("REnumServicesStatusA() called\n");
3394 return ERROR_SHUTDOWN_IN_PROGRESS
;
3396 hManager
= (PMANAGER_HANDLE
)hSCManager
;
3397 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
3399 DPRINT1("Invalid manager handle!\n");
3400 return ERROR_INVALID_HANDLE
;
3403 *pcbBytesNeeded
= 0;
3404 *lpServicesReturned
= 0;
3406 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
3408 DPRINT1("Not a valid Service Type!\n");
3409 return ERROR_INVALID_PARAMETER
;
3412 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
3414 DPRINT1("Not a valid Service State!\n");
3415 return ERROR_INVALID_PARAMETER
;
3418 /* Check access rights */
3419 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
3420 SC_MANAGER_ENUMERATE_SERVICE
))
3422 DPRINT1("Insufficient access rights! 0x%lx\n",
3423 hManager
->Handle
.DesiredAccess
);
3424 return ERROR_ACCESS_DENIED
;
3427 if (lpResumeHandle
) dwLastResumeCount
= *lpResumeHandle
;
3429 /* FIXME: Lock the service list shared */
3431 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
3432 if (lpService
== NULL
)
3434 dwError
= ERROR_SUCCESS
;
3441 for (ServiceEntry
= &lpService
->ServiceListEntry
;
3442 ServiceEntry
!= &ServiceListHead
;
3443 ServiceEntry
= ServiceEntry
->Flink
)
3445 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
3449 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
3452 dwState
= SERVICE_ACTIVE
;
3453 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
3454 dwState
= SERVICE_INACTIVE
;
3456 if ((dwState
& dwServiceState
) == 0)
3459 dwSize
= sizeof(ENUM_SERVICE_STATUSA
) +
3460 wcslen(CurrentService
->lpServiceName
) + 1 +
3461 wcslen(CurrentService
->lpDisplayName
) + 1;
3463 if (dwRequiredSize
+ dwSize
> dwBufSize
)
3465 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
3469 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
3470 dwRequiredSize
+= dwSize
;
3472 dwLastResumeCount
= CurrentService
->dwResumeCount
;
3475 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
3476 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
3479 ServiceEntry
!= &ServiceListHead
;
3480 ServiceEntry
= ServiceEntry
->Flink
)
3482 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
3486 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
3489 dwState
= SERVICE_ACTIVE
;
3490 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
3491 dwState
= SERVICE_INACTIVE
;
3493 if ((dwState
& dwServiceState
) == 0)
3496 dwRequiredSize
+= sizeof(ENUM_SERVICE_STATUSA
) +
3497 wcslen(CurrentService
->lpServiceName
) + 1 +
3498 wcslen(CurrentService
->lpDisplayName
) + 1;
3500 dwError
= ERROR_MORE_DATA
;
3503 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
3505 if (lpResumeHandle
) *lpResumeHandle
= dwLastResumeCount
;
3506 *lpServicesReturned
= dwServiceCount
;
3507 *pcbBytesNeeded
= dwRequiredSize
;
3509 lpStatusPtr
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3510 lpStringPtr
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3511 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSA
));
3514 for (ServiceEntry
= &lpService
->ServiceListEntry
;
3515 ServiceEntry
!= &ServiceListHead
;
3516 ServiceEntry
= ServiceEntry
->Flink
)
3518 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
3522 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
3525 dwState
= SERVICE_ACTIVE
;
3526 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
3527 dwState
= SERVICE_INACTIVE
;
3529 if ((dwState
& dwServiceState
) == 0)
3532 dwSize
= sizeof(ENUM_SERVICE_STATUSA
) +
3533 wcslen(CurrentService
->lpServiceName
) + 1 +
3534 wcslen(CurrentService
->lpDisplayName
) + 1;
3536 if (dwRequiredSize
+ dwSize
> dwBufSize
)
3539 /* Copy the service name */
3540 WideCharToMultiByte(CP_ACP
,
3542 CurrentService
->lpServiceName
,
3545 wcslen(CurrentService
->lpServiceName
),
3548 lpStatusPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
3549 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
3551 /* Copy the display name */
3552 WideCharToMultiByte(CP_ACP
,
3554 CurrentService
->lpDisplayName
,
3557 wcslen(CurrentService
->lpDisplayName
),
3560 lpStatusPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
3561 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
3563 /* Copy the status information */
3564 memcpy(&lpStatusPtr
->ServiceStatus
,
3565 &CurrentService
->Status
,
3566 sizeof(SERVICE_STATUS
));
3569 dwRequiredSize
+= dwSize
;
3572 if (dwError
!= ERROR_MORE_DATA
)
3574 *pcbBytesNeeded
= 0;
3575 if (lpResumeHandle
) *lpResumeHandle
= 0;
3579 /* FIXME: Unlock the service list */
3581 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3588 DWORD
ROpenSCManagerA(
3589 handle_t BindingHandle
,
3590 LPSTR lpMachineName
,
3591 LPSTR lpDatabaseName
,
3592 DWORD dwDesiredAccess
,
3593 LPSC_RPC_HANDLE lpScHandle
)
3595 UNICODE_STRING MachineName
;
3596 UNICODE_STRING DatabaseName
;
3599 DPRINT("ROpenSCManagerA() called\n");
3602 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3606 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3609 dwError
= ROpenSCManagerW(BindingHandle
,
3610 lpMachineName
? MachineName
.Buffer
: NULL
,
3611 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3616 RtlFreeUnicodeString(&MachineName
);
3619 RtlFreeUnicodeString(&DatabaseName
);
3626 DWORD
ROpenServiceA(
3627 handle_t BindingHandle
,
3628 SC_RPC_HANDLE hSCManager
,
3629 LPSTR lpServiceName
,
3630 DWORD dwDesiredAccess
,
3631 LPSC_RPC_HANDLE lpServiceHandle
)
3633 UNICODE_STRING ServiceName
;
3636 DPRINT("ROpenServiceA() called\n");
3639 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3642 dwError
= ROpenServiceW(BindingHandle
,
3644 lpServiceName
? ServiceName
.Buffer
: NULL
,
3649 RtlFreeUnicodeString(&ServiceName
);
3656 DWORD
RQueryServiceConfigA(
3657 handle_t BindingHandle
,
3658 SC_RPC_HANDLE hService
,
3659 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3661 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3663 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3664 DWORD dwError
= ERROR_SUCCESS
;
3665 PSERVICE_HANDLE hSvc
;
3666 PSERVICE lpService
= NULL
;
3667 HKEY hServiceKey
= NULL
;
3668 LPWSTR lpImagePath
= NULL
;
3669 LPWSTR lpServiceStartName
= NULL
;
3670 DWORD dwRequiredSize
;
3671 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3672 CHAR lpEmptyString
[]={0,0};
3675 DPRINT("RQueryServiceConfigA() called\n");
3678 return ERROR_SHUTDOWN_IN_PROGRESS
;
3680 hSvc
= (PSERVICE_HANDLE
)hService
;
3681 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3683 DPRINT1("Invalid handle tag!\n");
3684 return ERROR_INVALID_HANDLE
;
3687 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3688 SERVICE_QUERY_CONFIG
))
3690 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3691 return ERROR_ACCESS_DENIED
;
3694 lpService
= hSvc
->ServiceEntry
;
3695 if (lpService
== NULL
)
3697 DPRINT1("lpService == NULL!\n");
3698 return ERROR_INVALID_HANDLE
;
3701 /* FIXME: Lock the service database shared */
3703 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3706 if (dwError
!= ERROR_SUCCESS
)
3709 dwError
= ScmReadString(hServiceKey
,
3712 if (dwError
!= ERROR_SUCCESS
)
3715 ScmReadString(hServiceKey
,
3717 &lpServiceStartName
);
3719 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3721 if (lpImagePath
!= NULL
)
3722 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3724 dwRequiredSize
+= 2;
3726 if (lpService
->lpGroup
!= NULL
)
3727 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3729 dwRequiredSize
+= 2;
3731 /* FIXME: Add Dependencies length*/
3732 dwRequiredSize
+= 2;
3734 if (lpServiceStartName
!= NULL
)
3735 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3737 dwRequiredSize
+= 2;
3739 if (lpService
->lpDisplayName
!= NULL
)
3740 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3742 dwRequiredSize
+= 2;
3744 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3746 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3750 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3751 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3752 lpConfig
->dwStartType
= lpService
->dwStartType
;
3753 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3754 lpConfig
->dwTagId
= lpService
->dwTag
;
3756 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3758 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3763 WideCharToMultiByte(CP_ACP
,
3768 wcslen(lpImagePath
),
3774 strcpy(lpStr
, lpEmptyString
);
3777 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3778 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3780 if (lpService
->lpGroup
)
3782 WideCharToMultiByte(CP_ACP
,
3784 lpService
->lpGroup
->lpGroupName
,
3787 wcslen(lpService
->lpGroup
->lpGroupName
),
3793 strcpy(lpStr
, lpEmptyString
);
3796 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3797 lpStr
+= (strlen(lpStr
) + 1);
3799 /* FIXME: Append Dependencies */
3800 strcpy(lpStr
, lpEmptyString
);
3802 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3803 lpStr
+= (strlen(lpStr
) + 1);
3805 if (lpServiceStartName
)
3807 WideCharToMultiByte(CP_ACP
,
3812 wcslen(lpServiceStartName
),
3818 strcpy(lpStr
, lpEmptyString
);
3821 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3822 lpStr
+= (strlen(lpStr
) + 1);
3824 if (lpService
->lpDisplayName
)
3826 WideCharToMultiByte(CP_ACP
,
3828 lpService
->lpDisplayName
,
3831 wcslen(lpService
->lpDisplayName
),
3837 strcpy(lpStr
, lpEmptyString
);
3840 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3843 if (pcbBytesNeeded
!= NULL
)
3844 *pcbBytesNeeded
= dwRequiredSize
;
3847 if (lpImagePath
!= NULL
)
3848 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3850 if (lpServiceStartName
!= NULL
)
3851 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3853 if (hServiceKey
!= NULL
)
3854 RegCloseKey(hServiceKey
);
3856 /* FIXME: Unlock the service database */
3858 DPRINT("RQueryServiceConfigA() done\n");
3865 DWORD
RQueryServiceLockStatusA(
3866 handle_t BindingHandle
,
3867 SC_RPC_HANDLE hSCManager
,
3868 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
3870 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3873 return ERROR_CALL_NOT_IMPLEMENTED
;
3878 DWORD
RStartServiceA(
3879 handle_t BindingHandle
,
3880 SC_RPC_HANDLE hService
,
3882 LPSTRING_PTRSA argv
)
3884 DWORD dwError
= ERROR_SUCCESS
;
3885 PSERVICE_HANDLE hSvc
;
3886 PSERVICE lpService
= NULL
;
3888 DPRINT1("RStartServiceA() called\n");
3891 return ERROR_SHUTDOWN_IN_PROGRESS
;
3893 hSvc
= (PSERVICE_HANDLE
)hService
;
3894 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3896 DPRINT1("Invalid handle tag!\n");
3897 return ERROR_INVALID_HANDLE
;
3900 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3903 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3904 return ERROR_ACCESS_DENIED
;
3907 lpService
= hSvc
->ServiceEntry
;
3908 if (lpService
== NULL
)
3910 DPRINT1("lpService == NULL!\n");
3911 return ERROR_INVALID_HANDLE
;
3914 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3915 return ERROR_SERVICE_DISABLED
;
3917 if (lpService
->bDeleted
)
3918 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3920 /* FIXME: Convert argument vector to Unicode */
3922 /* Start the service */
3923 dwError
= ScmStartService(lpService
, 0, NULL
);
3925 /* FIXME: Free argument vector */
3932 DWORD
RGetServiceDisplayNameA(
3933 handle_t BindingHandle
,
3934 SC_RPC_HANDLE hSCManager
,
3935 LPSTR lpServiceName
,
3936 LPSTR lpDisplayName
,
3937 LPBOUNDED_DWORD_4K lpcchBuffer
)
3939 // PMANAGER_HANDLE hManager;
3943 LPWSTR lpServiceNameW
;
3945 DPRINT("RGetServiceDisplayNameA() called\n");
3946 DPRINT("hSCManager = %p\n", hSCManager
);
3947 DPRINT("lpServiceName: %s\n", lpServiceName
);
3948 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3949 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3951 // hManager = (PMANAGER_HANDLE)hSCManager;
3952 // if (hManager->Handle.Tag != MANAGER_TAG)
3954 // DPRINT1("Invalid manager handle!\n");
3955 // return ERROR_INVALID_HANDLE;
3958 dwLength
= strlen(lpServiceName
) + 1;
3959 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
3961 dwLength
* sizeof(WCHAR
));
3962 if (!lpServiceNameW
)
3963 return ERROR_NOT_ENOUGH_MEMORY
;
3965 MultiByteToWideChar(CP_ACP
,
3968 strlen(lpServiceName
),
3972 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
3974 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3976 if (lpService
== NULL
)
3978 DPRINT1("Could not find a service!\n");
3980 /* If the service could not be found and lpcchBuffer is 0, windows
3981 puts null in lpDisplayName and puts 1 in lpcchBuffer */
3982 if (*lpcchBuffer
== 0)
3985 *lpDisplayName
= '\0';
3987 return ERROR_SERVICE_DOES_NOT_EXIST
;
3990 if (!lpService
->lpDisplayName
)
3992 dwLength
= wcslen(lpService
->lpServiceName
);
3993 if (lpServiceName
!= NULL
&&
3994 *lpcchBuffer
> dwLength
)
3996 WideCharToMultiByte(CP_ACP
,
3998 lpService
->lpServiceName
,
3999 wcslen(lpService
->lpServiceName
),
4004 return ERROR_SUCCESS
;
4009 dwLength
= wcslen(lpService
->lpDisplayName
);
4010 if (lpDisplayName
!= NULL
&&
4011 *lpcchBuffer
> dwLength
)
4013 WideCharToMultiByte(CP_ACP
,
4015 lpService
->lpDisplayName
,
4016 wcslen(lpService
->lpDisplayName
),
4021 return ERROR_SUCCESS
;
4025 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4027 *lpcchBuffer
= dwLength
* 2;
4034 DWORD
RGetServiceKeyNameA(
4035 handle_t BindingHandle
,
4036 SC_RPC_HANDLE hSCManager
,
4037 LPSTR lpDisplayName
,
4038 LPSTR lpServiceName
,
4039 LPBOUNDED_DWORD_4K lpcchBuffer
)
4044 LPWSTR lpDisplayNameW
;
4046 DPRINT("RGetServiceKeyNameA() called\n");
4047 DPRINT("hSCManager = %p\n", hSCManager
);
4048 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4049 DPRINT("lpServiceName: %p\n", lpServiceName
);
4050 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4052 dwLength
= strlen(lpDisplayName
) + 1;
4053 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4055 dwLength
* sizeof(WCHAR
));
4056 if (!lpDisplayNameW
)
4057 return ERROR_NOT_ENOUGH_MEMORY
;
4059 MultiByteToWideChar(CP_ACP
,
4062 strlen(lpDisplayName
),
4066 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4068 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4070 if (lpService
== NULL
)
4072 DPRINT1("Could not find the service!\n");
4074 /* If the service could not be found and lpcchBuffer is 0,
4075 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4076 if (*lpcchBuffer
== 0)
4079 *lpServiceName
= '\0';
4082 return ERROR_SERVICE_DOES_NOT_EXIST
;
4085 dwLength
= wcslen(lpService
->lpServiceName
);
4086 if (lpService
!= NULL
&&
4087 *lpcchBuffer
> dwLength
)
4089 WideCharToMultiByte(CP_ACP
,
4091 lpService
->lpServiceName
,
4092 wcslen(lpService
->lpServiceName
),
4097 return ERROR_SUCCESS
;
4100 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4102 *lpcchBuffer
= dwLength
* 2;
4109 DWORD
RI_ScGetCurrentGroupStateW(
4110 handle_t BindingHandle
,
4111 SC_RPC_HANDLE hSCManager
,
4112 LPWSTR lpLoadOrderGroup
,
4116 return ERROR_CALL_NOT_IMPLEMENTED
;
4121 DWORD
REnumServiceGroupW(
4122 handle_t BindingHandle
,
4123 SC_RPC_HANDLE hSCManager
,
4124 DWORD dwServiceType
,
4125 DWORD dwServiceState
,
4128 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4129 LPBOUNDED_DWORD_256K lpServicesReturned
,
4130 LPBOUNDED_DWORD_256K lpResumeIndex
,
4131 LPCWSTR pszGroupName
)
4134 return ERROR_CALL_NOT_IMPLEMENTED
;
4139 DWORD
RChangeServiceConfig2A(
4140 handle_t BindingHandle
,
4141 SC_RPC_HANDLE hService
,
4142 SC_RPC_CONFIG_INFOA Info
)
4145 return ERROR_CALL_NOT_IMPLEMENTED
;
4150 DWORD
RChangeServiceConfig2W(
4151 handle_t BindingHandle
,
4152 SC_RPC_HANDLE hService
,
4153 SC_RPC_CONFIG_INFOW Info
)
4155 DWORD dwError
= ERROR_SUCCESS
;
4156 PSERVICE_HANDLE hSvc
;
4157 PSERVICE lpService
= NULL
;
4158 HKEY hServiceKey
= NULL
;
4160 DPRINT("RChangeServiceConfig2W() called\n");
4161 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4164 return ERROR_SHUTDOWN_IN_PROGRESS
;
4166 hSvc
= (PSERVICE_HANDLE
)hService
;
4167 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4169 DPRINT1("Invalid handle tag!\n");
4170 return ERROR_INVALID_HANDLE
;
4173 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4174 SERVICE_CHANGE_CONFIG
))
4176 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4177 return ERROR_ACCESS_DENIED
;
4180 lpService
= hSvc
->ServiceEntry
;
4181 if (lpService
== NULL
)
4183 DPRINT1("lpService == NULL!\n");
4184 return ERROR_INVALID_HANDLE
;
4187 /* FIXME: Lock database exclusively */
4189 if (lpService
->bDeleted
)
4191 /* FIXME: Unlock database */
4192 DPRINT1("The service has already been marked for delete!\n");
4193 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4196 /* Open the service key */
4197 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4200 if (dwError
!= ERROR_SUCCESS
)
4203 if (Info
.dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4205 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4207 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)&Info
;
4208 lpServiceDescription
->lpDescription
= (LPWSTR
)(&Info
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4210 if (lpServiceDescription
!= NULL
&&
4211 lpServiceDescription
->lpDescription
!= NULL
)
4213 RegSetValueExW(hServiceKey
,
4217 (LPBYTE
)lpServiceDescription
->lpDescription
,
4218 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4220 if (dwError
!= ERROR_SUCCESS
)
4224 else if (Info
.dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4227 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4232 /* FIXME: Unlock database */
4233 if (hServiceKey
!= NULL
)
4234 RegCloseKey(hServiceKey
);
4236 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4243 DWORD
RQueryServiceConfig2A(
4244 handle_t BindingHandle
,
4245 SC_RPC_HANDLE hService
,
4249 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4251 DWORD dwError
= ERROR_SUCCESS
;
4252 PSERVICE_HANDLE hSvc
;
4253 PSERVICE lpService
= NULL
;
4254 HKEY hServiceKey
= NULL
;
4255 DWORD dwRequiredSize
;
4256 LPWSTR lpDescriptionW
= NULL
;
4257 LPSTR lpDescription
= NULL
;
4259 DPRINT("RQueryServiceConfig2W() called\n");
4262 return ERROR_INVALID_ADDRESS
;
4265 return ERROR_SHUTDOWN_IN_PROGRESS
;
4267 hSvc
= (PSERVICE_HANDLE
)hService
;
4268 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4270 DPRINT1("Invalid handle tag!\n");
4271 return ERROR_INVALID_HANDLE
;
4274 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4275 SERVICE_QUERY_CONFIG
))
4277 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4278 return ERROR_ACCESS_DENIED
;
4281 lpService
= hSvc
->ServiceEntry
;
4282 if (lpService
== NULL
)
4284 DPRINT1("lpService == NULL!\n");
4285 return ERROR_INVALID_HANDLE
;
4288 /* FIXME: Lock the service database shared */
4290 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4293 if (dwError
!= ERROR_SUCCESS
)
4296 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4298 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4301 dwError
= ScmReadString(hServiceKey
,
4304 if (dwError
!= ERROR_SUCCESS
)
4307 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONA
) + ((wcslen(lpDescriptionW
) + 1));
4309 if (cbBufSize
< dwRequiredSize
)
4311 *pcbBytesNeeded
= dwRequiredSize
;
4312 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4316 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4318 WideCharToMultiByte(CP_ACP
,
4323 wcslen(lpDescriptionW
),
4326 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4328 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4331 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4336 if (lpDescription
!= NULL
)
4337 HeapFree(GetProcessHeap(), 0, lpDescription
);
4339 if (hServiceKey
!= NULL
)
4340 RegCloseKey(hServiceKey
);
4342 /* FIXME: Unlock database */
4344 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4351 DWORD
RQueryServiceConfig2W(
4352 handle_t BindingHandle
,
4353 SC_RPC_HANDLE hService
,
4357 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4359 DWORD dwError
= ERROR_SUCCESS
;
4360 PSERVICE_HANDLE hSvc
;
4361 PSERVICE lpService
= NULL
;
4362 HKEY hServiceKey
= NULL
;
4363 DWORD dwRequiredSize
;
4364 LPWSTR lpDescription
= NULL
;
4366 DPRINT("RQueryServiceConfig2W() called\n");
4369 return ERROR_INVALID_ADDRESS
;
4372 return ERROR_SHUTDOWN_IN_PROGRESS
;
4374 hSvc
= (PSERVICE_HANDLE
)hService
;
4375 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4377 DPRINT1("Invalid handle tag!\n");
4378 return ERROR_INVALID_HANDLE
;
4381 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4382 SERVICE_QUERY_CONFIG
))
4384 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4385 return ERROR_ACCESS_DENIED
;
4388 lpService
= hSvc
->ServiceEntry
;
4389 if (lpService
== NULL
)
4391 DPRINT1("lpService == NULL!\n");
4392 return ERROR_INVALID_HANDLE
;
4395 /* FIXME: Lock the service database shared */
4397 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4400 if (dwError
!= ERROR_SUCCESS
)
4403 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4405 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4408 dwError
= ScmReadString(hServiceKey
,
4411 if (dwError
!= ERROR_SUCCESS
)
4414 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4416 if (cbBufSize
< dwRequiredSize
)
4418 *pcbBytesNeeded
= dwRequiredSize
;
4419 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4423 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4424 wcscpy(lpStr
, lpDescription
);
4425 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4427 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4430 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4435 if (lpDescription
!= NULL
)
4436 HeapFree(GetProcessHeap(), 0, lpDescription
);
4438 if (hServiceKey
!= NULL
)
4439 RegCloseKey(hServiceKey
);
4441 /* FIXME: Unlock database */
4443 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4450 DWORD
RQueryServiceStatusEx(
4451 handle_t BindingHandle
,
4452 SC_RPC_HANDLE hService
,
4453 SC_STATUS_TYPE InfoLevel
,
4456 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4458 LPSERVICE_STATUS_PROCESS lpStatus
;
4459 PSERVICE_HANDLE hSvc
;
4462 DPRINT("RQueryServiceStatusEx() called\n");
4465 return ERROR_SHUTDOWN_IN_PROGRESS
;
4467 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4468 return ERROR_INVALID_LEVEL
;
4470 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4472 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4473 return ERROR_INSUFFICIENT_BUFFER
;
4475 hSvc
= (PSERVICE_HANDLE
)hService
;
4476 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4478 DPRINT1("Invalid handle tag!\n");
4479 return ERROR_INVALID_HANDLE
;
4482 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4483 SERVICE_QUERY_STATUS
))
4485 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4486 return ERROR_ACCESS_DENIED
;
4489 lpService
= hSvc
->ServiceEntry
;
4490 if (lpService
== NULL
)
4492 DPRINT1("lpService == NULL!\n");
4493 return ERROR_INVALID_HANDLE
;
4496 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4498 /* Return service status information */
4499 RtlCopyMemory(lpStatus
,
4501 sizeof(SERVICE_STATUS
));
4503 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
4504 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4506 return ERROR_SUCCESS
;
4511 DWORD
REnumServicesStatusExA(
4512 handle_t BindingHandle
,
4513 SC_RPC_HANDLE hSCManager
,
4514 SC_ENUM_TYPE InfoLevel
,
4515 DWORD dwServiceType
,
4516 DWORD dwServiceState
,
4519 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4520 LPBOUNDED_DWORD_256K lpServicesReturned
,
4521 LPBOUNDED_DWORD_256K lpResumeIndex
,
4522 LPCSTR pszGroupName
)
4524 PMANAGER_HANDLE hManager
;
4526 DWORD dwError
= ERROR_SUCCESS
;
4527 PLIST_ENTRY ServiceEntry
;
4528 PSERVICE CurrentService
;
4530 DWORD dwRequiredSize
;
4531 DWORD dwServiceCount
;
4533 DWORD dwLastResumeCount
= 0;
4534 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtr
;
4536 LPWSTR pszGroupNameW
= NULL
;
4538 DPRINT("REnumServicesStatusExA() called\n");
4541 return ERROR_SHUTDOWN_IN_PROGRESS
;
4543 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
4544 return ERROR_INVALID_LEVEL
;
4546 hManager
= (PMANAGER_HANDLE
)hSCManager
;
4547 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
4549 DPRINT1("Invalid manager handle!\n");
4550 return ERROR_INVALID_HANDLE
;
4553 *pcbBytesNeeded
= 0;
4554 *lpServicesReturned
= 0;
4556 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
4558 DPRINT1("Not a valid Service Type!\n");
4559 return ERROR_INVALID_PARAMETER
;
4562 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
4564 DPRINT1("Not a valid Service State!\n");
4565 return ERROR_INVALID_PARAMETER
;
4568 /* Check access rights */
4569 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4570 SC_MANAGER_ENUMERATE_SERVICE
))
4572 DPRINT1("Insufficient access rights! 0x%lx\n",
4573 hManager
->Handle
.DesiredAccess
);
4574 return ERROR_ACCESS_DENIED
;
4577 if (lpResumeIndex
) dwLastResumeCount
= *lpResumeIndex
;
4579 /* FIXME: Lock the service list shared */
4581 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4582 if (lpService
== NULL
)
4584 dwError
= ERROR_SUCCESS
;
4593 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
4596 DPRINT1("Failed to allocate buffer!\n");
4597 return ERROR_NOT_ENOUGH_MEMORY
;
4599 MultiByteToWideChar(CP_ACP
,
4604 strlen(pszGroupName
) + 1);
4607 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4608 ServiceEntry
!= &ServiceListHead
;
4609 ServiceEntry
= ServiceEntry
->Flink
)
4611 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4615 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4618 dwState
= SERVICE_ACTIVE
;
4619 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4620 dwState
= SERVICE_INACTIVE
;
4622 if ((dwState
& dwServiceState
) == 0)
4627 if (*pszGroupNameW
== 0)
4629 if (CurrentService
->lpGroup
!= NULL
)
4634 if ((CurrentService
->lpGroup
== NULL
) ||
4635 _wcsicmp(pszGroupNameW
, CurrentService
->lpGroup
->lpGroupName
))
4640 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4641 (wcslen(CurrentService
->lpServiceName
) + 1) +
4642 (wcslen(CurrentService
->lpDisplayName
) + 1);
4644 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4646 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
4647 dwRequiredSize
+= dwSize
;
4649 dwLastResumeCount
= CurrentService
->dwResumeCount
;
4653 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
4659 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
4660 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
4663 ServiceEntry
!= &ServiceListHead
;
4664 ServiceEntry
= ServiceEntry
->Flink
)
4666 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4670 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4673 dwState
= SERVICE_ACTIVE
;
4674 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4675 dwState
= SERVICE_INACTIVE
;
4677 if ((dwState
& dwServiceState
) == 0)
4682 if (*pszGroupNameW
== 0)
4684 if (CurrentService
->lpGroup
!= NULL
)
4689 if ((CurrentService
->lpGroup
== NULL
) ||
4690 _wcsicmp(pszGroupNameW
, CurrentService
->lpGroup
->lpGroupName
))
4695 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4696 (wcslen(CurrentService
->lpServiceName
) + 1) +
4697 (wcslen(CurrentService
->lpDisplayName
) + 1));
4699 dwError
= ERROR_MORE_DATA
;
4702 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
4704 if (lpResumeIndex
) *lpResumeIndex
= dwLastResumeCount
;
4705 *lpServicesReturned
= dwServiceCount
;
4706 *pcbBytesNeeded
= dwRequiredSize
;
4708 /* If there was no services that matched */
4709 if (!dwServiceCount
)
4711 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
4715 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
4716 lpStringPtr
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
4717 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
4720 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4721 ServiceEntry
!= &ServiceListHead
;
4722 ServiceEntry
= ServiceEntry
->Flink
)
4724 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4728 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4731 dwState
= SERVICE_ACTIVE
;
4732 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4733 dwState
= SERVICE_INACTIVE
;
4735 if ((dwState
& dwServiceState
) == 0)
4740 if (*pszGroupNameW
== 0)
4742 if (CurrentService
->lpGroup
!= NULL
)
4747 if ((CurrentService
->lpGroup
== NULL
) ||
4748 _wcsicmp(pszGroupNameW
, CurrentService
->lpGroup
->lpGroupName
))
4753 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4754 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4755 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4757 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4759 /* Copy the service name */
4760 WideCharToMultiByte(CP_ACP
,
4762 CurrentService
->lpServiceName
,
4765 wcslen(CurrentService
->lpServiceName
),
4768 lpStatusPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4769 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
4771 /* Copy the display name */
4772 WideCharToMultiByte(CP_ACP
,
4774 CurrentService
->lpDisplayName
,
4777 wcslen(CurrentService
->lpDisplayName
),
4780 lpStatusPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4781 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
4783 /* Copy the status information */
4784 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
4785 &CurrentService
->Status
,
4786 sizeof(SERVICE_STATUS
));
4787 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
4788 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4791 dwRequiredSize
+= dwSize
;
4799 if (dwError
!= ERROR_MORE_DATA
)
4801 *pcbBytesNeeded
= 0;
4802 if (lpResumeIndex
) *lpResumeIndex
= 0;
4806 /* Unlock the service list */
4808 if (pszGroupNameW
) HeapFree(GetProcessHeap(),0,pszGroupNameW
);
4810 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
4817 DWORD
REnumServicesStatusExW(
4818 handle_t BindingHandle
,
4819 SC_RPC_HANDLE hSCManager
,
4820 SC_ENUM_TYPE InfoLevel
,
4821 DWORD dwServiceType
,
4822 DWORD dwServiceState
,
4825 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4826 LPBOUNDED_DWORD_256K lpServicesReturned
,
4827 LPBOUNDED_DWORD_256K lpResumeIndex
,
4828 LPCWSTR pszGroupName
)
4830 PMANAGER_HANDLE hManager
;
4832 DWORD dwError
= ERROR_SUCCESS
;
4833 PLIST_ENTRY ServiceEntry
;
4834 PSERVICE CurrentService
;
4836 DWORD dwRequiredSize
;
4837 DWORD dwServiceCount
;
4839 DWORD dwLastResumeCount
= 0;
4840 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
4843 DPRINT("REnumServicesStatusExW() called\n");
4846 return ERROR_SHUTDOWN_IN_PROGRESS
;
4848 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
4849 return ERROR_INVALID_LEVEL
;
4851 hManager
= (PMANAGER_HANDLE
)hSCManager
;
4852 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
4854 DPRINT1("Invalid manager handle!\n");
4855 return ERROR_INVALID_HANDLE
;
4858 *pcbBytesNeeded
= 0;
4859 *lpServicesReturned
= 0;
4861 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
4863 DPRINT1("Not a valid Service Type!\n");
4864 return ERROR_INVALID_PARAMETER
;
4867 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
4869 DPRINT1("Not a valid Service State!\n");
4870 return ERROR_INVALID_PARAMETER
;
4873 /* Check access rights */
4874 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4875 SC_MANAGER_ENUMERATE_SERVICE
))
4877 DPRINT1("Insufficient access rights! 0x%lx\n",
4878 hManager
->Handle
.DesiredAccess
);
4879 return ERROR_ACCESS_DENIED
;
4882 if (lpResumeIndex
) dwLastResumeCount
= *lpResumeIndex
;
4884 /* Lock the service list shared */
4886 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4887 if (lpService
== NULL
)
4889 dwError
= ERROR_SUCCESS
;
4896 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4897 ServiceEntry
!= &ServiceListHead
;
4898 ServiceEntry
= ServiceEntry
->Flink
)
4900 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4904 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4907 dwState
= SERVICE_ACTIVE
;
4908 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4909 dwState
= SERVICE_INACTIVE
;
4911 if ((dwState
& dwServiceState
) == 0)
4916 if (*pszGroupName
== 0)
4918 if (CurrentService
->lpGroup
!= NULL
)
4923 if ((CurrentService
->lpGroup
== NULL
) ||
4924 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4929 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4930 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4931 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4933 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4935 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
4936 dwRequiredSize
+= dwSize
;
4938 dwLastResumeCount
= CurrentService
->dwResumeCount
;
4942 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
4948 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
4949 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
4952 ServiceEntry
!= &ServiceListHead
;
4953 ServiceEntry
= ServiceEntry
->Flink
)
4955 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4959 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4962 dwState
= SERVICE_ACTIVE
;
4963 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4964 dwState
= SERVICE_INACTIVE
;
4966 if ((dwState
& dwServiceState
) == 0)
4971 if (*pszGroupName
== 0)
4973 if (CurrentService
->lpGroup
!= NULL
)
4978 if ((CurrentService
->lpGroup
== NULL
) ||
4979 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4984 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4985 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4986 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
4988 dwError
= ERROR_MORE_DATA
;
4991 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
4993 if (lpResumeIndex
) *lpResumeIndex
= dwLastResumeCount
;
4994 *lpServicesReturned
= dwServiceCount
;
4995 *pcbBytesNeeded
= dwRequiredSize
;
4997 /* If there was no services that matched */
4998 if (!dwServiceCount
)
5000 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5004 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5005 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5006 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5009 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5010 ServiceEntry
!= &ServiceListHead
;
5011 ServiceEntry
= ServiceEntry
->Flink
)
5013 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5017 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5020 dwState
= SERVICE_ACTIVE
;
5021 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5022 dwState
= SERVICE_INACTIVE
;
5024 if ((dwState
& dwServiceState
) == 0)
5029 if (*pszGroupName
== 0)
5031 if (CurrentService
->lpGroup
!= NULL
)
5036 if ((CurrentService
->lpGroup
== NULL
) ||
5037 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5042 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5043 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5044 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5046 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5048 /* Copy the service name */
5050 CurrentService
->lpServiceName
);
5051 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5052 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5054 /* Copy the display name */
5056 CurrentService
->lpDisplayName
);
5057 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5058 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5060 /* Copy the status information */
5061 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5062 &CurrentService
->Status
,
5063 sizeof(SERVICE_STATUS
));
5064 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
5065 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5068 dwRequiredSize
+= dwSize
;
5076 if (dwError
!= ERROR_MORE_DATA
)
5078 *pcbBytesNeeded
= 0;
5079 if (lpResumeIndex
) *lpResumeIndex
= 0;
5083 /* Unlock the service list */
5085 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5092 DWORD
RSendTSMessage(
5093 handle_t BindingHandle
)
5096 return ERROR_CALL_NOT_IMPLEMENTED
;
5101 DWORD
RCreateServiceWOW64A(
5102 handle_t BindingHandle
,
5103 LPSTR lpServiceName
,
5104 LPSTR lpDisplayName
,
5105 DWORD dwDesiredAccess
,
5106 DWORD dwServiceType
,
5108 DWORD dwErrorControl
,
5109 LPSTR lpBinaryPathName
,
5110 LPSTR lpLoadOrderGroup
,
5112 LPBYTE lpDependencies
,
5114 LPSTR lpServiceStartName
,
5117 LPSC_RPC_HANDLE lpServiceHandle
)
5120 return ERROR_CALL_NOT_IMPLEMENTED
;
5125 DWORD
RCreateServiceWOW64W(
5126 handle_t BindingHandle
,
5127 LPWSTR lpServiceName
,
5128 LPWSTR lpDisplayName
,
5129 DWORD dwDesiredAccess
,
5130 DWORD dwServiceType
,
5132 DWORD dwErrorControl
,
5133 LPWSTR lpBinaryPathName
,
5134 LPWSTR lpLoadOrderGroup
,
5136 LPBYTE lpDependencies
,
5138 LPWSTR lpServiceStartName
,
5141 LPSC_RPC_HANDLE lpServiceHandle
)
5144 return ERROR_CALL_NOT_IMPLEMENTED
;
5149 DWORD
RQueryServiceTagInfo(
5150 handle_t BindingHandle
)
5153 return ERROR_CALL_NOT_IMPLEMENTED
;
5158 DWORD
RNotifyServiceStatusChange(
5159 handle_t BindingHandle
,
5160 SC_RPC_HANDLE hService
,
5161 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5162 GUID
*pClientProcessGuid
,
5163 GUID
*pSCMProcessGuid
,
5164 PBOOL pfCreateRemoteQueue
,
5165 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5168 return ERROR_CALL_NOT_IMPLEMENTED
;
5173 DWORD
RGetNotifyResults(
5174 handle_t BindingHandle
,
5175 SC_NOTIFY_RPC_HANDLE hNotify
,
5176 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5179 return ERROR_CALL_NOT_IMPLEMENTED
;
5184 DWORD
RCloseNotifyHandle(
5185 handle_t BindingHandle
,
5186 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5190 return ERROR_CALL_NOT_IMPLEMENTED
;
5195 DWORD
RControlServiceExA(
5196 handle_t BindingHandle
,
5197 SC_RPC_HANDLE hService
,
5202 return ERROR_CALL_NOT_IMPLEMENTED
;
5207 DWORD
RControlServiceExW(
5208 handle_t BindingHandle
,
5209 SC_RPC_HANDLE hService
,
5214 return ERROR_CALL_NOT_IMPLEMENTED
;
5219 DWORD
RSendPnPMessage(
5220 handle_t BindingHandle
)
5223 return ERROR_CALL_NOT_IMPLEMENTED
;
5228 DWORD
RValidatePnPService(
5229 handle_t BindingHandle
)
5232 return ERROR_CALL_NOT_IMPLEMENTED
;
5237 DWORD
ROpenServiceStatusHandle(
5238 handle_t BindingHandle
)
5241 return ERROR_CALL_NOT_IMPLEMENTED
;
5247 handle_t BindingHandle
)
5250 return ERROR_CALL_NOT_IMPLEMENTED
;
5254 void __RPC_FAR
* __RPC_USER
midl_user_allocate(size_t len
)
5256 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5260 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5262 HeapFree(GetProcessHeap(), 0, ptr
);
5266 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5271 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5276 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)