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
= (void *)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 DWORD
RSetServiceStatus(
987 handle_t BindingHandle
,
988 SC_RPC_HANDLE hServiceStatus
,
989 LPSERVICE_STATUS lpServiceStatus
)
993 DPRINT("RSetServiceStatus() called\n");
996 return ERROR_SHUTDOWN_IN_PROGRESS
;
998 lpService
= ScmGetServiceEntryByClientHandle((ULONG
)hServiceStatus
);
999 if (lpService
== NULL
)
1001 DPRINT1("lpService == NULL!\n");
1002 return ERROR_INVALID_HANDLE
;
1005 RtlCopyMemory(&lpService
->Status
,
1007 sizeof(SERVICE_STATUS
));
1009 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1010 DPRINT("RSetServiceStatus() done\n");
1012 return ERROR_SUCCESS
;
1017 DWORD
RUnlockServiceDatabase(
1018 handle_t BindingHandle
,
1022 return ERROR_SUCCESS
;
1027 DWORD
RNotifyBootConfigStatus(
1028 handle_t BindingHandle
,
1029 SVCCTL_HANDLEW lpMachineName
,
1030 DWORD BootAcceptable
)
1033 return ERROR_CALL_NOT_IMPLEMENTED
;
1038 DWORD
RI_ScSetServiceBitsW(
1039 handle_t BindingHandle
,
1040 SC_RPC_HANDLE hServiceStatus
,
1041 DWORD dwServiceBits
,
1043 int bUpdateImmediately
,
1047 return ERROR_CALL_NOT_IMPLEMENTED
;
1052 DWORD
RChangeServiceConfigW(
1053 handle_t BindingHandle
,
1054 SC_RPC_HANDLE hService
,
1055 DWORD dwServiceType
,
1057 DWORD dwErrorControl
,
1058 LPWSTR lpBinaryPathName
,
1059 LPWSTR lpLoadOrderGroup
,
1061 LPBYTE lpDependencies
,
1063 LPWSTR lpServiceStartName
,
1066 LPWSTR lpDisplayName
)
1068 DWORD dwError
= ERROR_SUCCESS
;
1069 PSERVICE_HANDLE hSvc
;
1070 PSERVICE lpService
= NULL
;
1071 HKEY hServiceKey
= NULL
;
1072 LPWSTR lpDisplayNameW
= NULL
;
1074 DPRINT("RChangeServiceConfigW() called\n");
1075 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1076 DPRINT("dwStartType = %lu\n", dwStartType
);
1077 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1078 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1079 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1080 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1083 return ERROR_SHUTDOWN_IN_PROGRESS
;
1085 hSvc
= (PSERVICE_HANDLE
)hService
;
1086 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1088 DPRINT1("Invalid handle tag!\n");
1089 return ERROR_INVALID_HANDLE
;
1092 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1093 SERVICE_CHANGE_CONFIG
))
1095 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1096 return ERROR_ACCESS_DENIED
;
1099 lpService
= hSvc
->ServiceEntry
;
1100 if (lpService
== NULL
)
1102 DPRINT1("lpService == NULL!\n");
1103 return ERROR_INVALID_HANDLE
;
1106 /* FIXME: Lock database exclusively */
1108 if (lpService
->bDeleted
)
1110 /* FIXME: Unlock database */
1111 DPRINT1("The service has already been marked for delete!\n");
1112 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1115 /* Open the service key */
1116 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1119 if (dwError
!= ERROR_SUCCESS
)
1122 /* Write service data to the registry */
1123 /* Set the display name */
1124 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1126 RegSetValueExW(hServiceKey
,
1130 (LPBYTE
)lpDisplayName
,
1131 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1133 /* Update the display name */
1134 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1136 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1137 if (lpDisplayNameW
== NULL
)
1139 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1143 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1144 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1146 lpService
->lpDisplayName
= lpDisplayNameW
;
1149 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1151 /* Set the service type */
1152 dwError
= RegSetValueExW(hServiceKey
,
1156 (LPBYTE
)&dwServiceType
,
1158 if (dwError
!= ERROR_SUCCESS
)
1161 lpService
->Status
.dwServiceType
= dwServiceType
;
1164 if (dwStartType
!= SERVICE_NO_CHANGE
)
1166 /* Set the start value */
1167 dwError
= RegSetValueExW(hServiceKey
,
1171 (LPBYTE
)&dwStartType
,
1173 if (dwError
!= ERROR_SUCCESS
)
1176 lpService
->dwStartType
= dwStartType
;
1179 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1181 /* Set the error control value */
1182 dwError
= RegSetValueExW(hServiceKey
,
1186 (LPBYTE
)&dwErrorControl
,
1188 if (dwError
!= ERROR_SUCCESS
)
1191 lpService
->dwErrorControl
= dwErrorControl
;
1195 /* FIXME: set the new ImagePath value */
1197 /* Set the image path */
1198 if (dwServiceType
& SERVICE_WIN32
)
1200 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1202 dwError
= RegSetValueExW(hServiceKey
,
1206 (LPBYTE
)lpBinaryPathName
,
1207 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1208 if (dwError
!= ERROR_SUCCESS
)
1212 else if (dwServiceType
& SERVICE_DRIVER
)
1214 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1216 dwError
= RegSetValueExW(hServiceKey
,
1220 (LPBYTE
)lpImagePath
,
1221 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1222 if (dwError
!= ERROR_SUCCESS
)
1228 /* Set the group name */
1229 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1231 dwError
= RegSetValueExW(hServiceKey
,
1235 (LPBYTE
)lpLoadOrderGroup
,
1236 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1237 if (dwError
!= ERROR_SUCCESS
)
1239 /* FIXME: Update lpService->lpServiceGroup */
1242 if (lpdwTagId
!= NULL
)
1244 dwError
= ScmAssignNewTag(lpService
);
1245 if (dwError
!= ERROR_SUCCESS
)
1248 dwError
= RegSetValueExW(hServiceKey
,
1252 (LPBYTE
)&lpService
->dwTag
,
1254 if (dwError
!= ERROR_SUCCESS
)
1257 *lpdwTagId
= lpService
->dwTag
;
1260 /* Write dependencies */
1261 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1263 dwError
= ScmWriteDependencies(hServiceKey
,
1264 (LPWSTR
)lpDependencies
,
1266 if (dwError
!= ERROR_SUCCESS
)
1270 if (lpPassword
!= NULL
)
1272 /* FIXME: Write password */
1275 /* FIXME: Unlock database */
1278 if (hServiceKey
!= NULL
)
1279 RegCloseKey(hServiceKey
);
1281 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1287 /* Create a path suitable for the bootloader out of the full path */
1289 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1291 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1294 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1295 OBJECT_ATTRIBUTES ObjectAttributes
;
1297 HANDLE SymbolicLinkHandle
;
1299 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1301 ServiceNameLen
= wcslen(CanonName
);
1303 /* First check, if it's already good */
1304 if (ServiceNameLen
> 12 &&
1305 !wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1307 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1308 if (*RelativeName
== NULL
)
1310 DPRINT1("Error allocating memory for boot driver name!\n");
1311 return ERROR_NOT_ENOUGH_MEMORY
;
1315 wcscpy(*RelativeName
, CanonName
);
1317 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1318 return ERROR_SUCCESS
;
1321 /* If it has %SystemRoot% prefix, substitute it to \System*/
1322 if (ServiceNameLen
> 13 &&
1323 !wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1325 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1326 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1328 if (*RelativeName
== NULL
)
1330 DPRINT1("Error allocating memory for boot driver name!\n");
1331 return ERROR_NOT_ENOUGH_MEMORY
;
1335 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1336 wcscat(*RelativeName
, CanonName
+ 13);
1338 DPRINT1("Bootdriver name %S\n", *RelativeName
);
1339 return ERROR_SUCCESS
;
1342 /* Get buffer size needed for expanding env strings */
1343 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1345 if (BufferSize
<= 1)
1347 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1348 return ERROR_INVALID_ENVIRONMENT
;
1351 /* Allocate memory, since the size is known now */
1352 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1355 DPRINT1("Error allocating memory for boot driver name!\n");
1356 return ERROR_NOT_ENOUGH_MEMORY
;
1360 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1363 DPRINT1("Error during a call to ExpandEnvironmentStringsW()\n");
1364 LocalFree(Expanded
);
1365 return ERROR_NOT_ENOUGH_MEMORY
;
1368 /* Convert to NY-style path */
1369 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1371 DPRINT1("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1372 return ERROR_INVALID_ENVIRONMENT
;
1375 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1377 /* No need to keep the dos-path anymore */
1378 LocalFree(Expanded
);
1380 /* Copy it to the allocated place */
1381 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1384 DPRINT1("Error allocating memory for boot driver name!\n");
1385 return ERROR_NOT_ENOUGH_MEMORY
;
1388 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1389 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1390 Expanded
[ExpandedLen
] = 0;
1392 if (ServiceNameLen
> ExpandedLen
&&
1393 !wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1395 /* Only \SystemRoot\ is missing */
1396 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1397 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1398 if (*RelativeName
== NULL
)
1400 DPRINT1("Error allocating memory for boot driver name!\n");
1401 LocalFree(Expanded
);
1402 return ERROR_NOT_ENOUGH_MEMORY
;
1405 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1406 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1408 RtlFreeUnicodeString(&NtPathName
);
1409 return ERROR_SUCCESS
;
1412 /* The most complex case starts here */
1413 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1414 InitializeObjectAttributes(&ObjectAttributes
,
1416 OBJ_CASE_INSENSITIVE
,
1420 /* Open this symlink */
1421 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1423 if (NT_SUCCESS(Status
))
1425 LinkTarget
.Length
= 0;
1426 LinkTarget
.MaximumLength
= 0;
1428 DPRINT("Opened symbolic link object\n");
1430 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1431 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1433 /* Check if required buffer size is sane */
1434 if (BufferSize
> 0xFFFD)
1436 DPRINT1("Too large buffer required\n");
1439 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1440 LocalFree(Expanded
);
1441 return ERROR_NOT_ENOUGH_MEMORY
;
1444 /* Alloc the string */
1445 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1446 if (!LinkTarget
.Buffer
)
1448 DPRINT1("Unable to alloc buffer\n");
1449 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1450 LocalFree(Expanded
);
1451 return ERROR_NOT_ENOUGH_MEMORY
;
1454 /* Do a real query now */
1455 LinkTarget
.Length
= BufferSize
;
1456 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1458 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1459 if (NT_SUCCESS(Status
))
1461 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1463 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1464 if ((ServiceNameLen
> ExpandedLen
) &&
1465 !wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1467 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1468 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1470 if (*RelativeName
== NULL
)
1472 DPRINT1("Unable to alloc buffer\n");
1473 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1474 LocalFree(Expanded
);
1475 RtlFreeUnicodeString(&NtPathName
);
1476 return ERROR_NOT_ENOUGH_MEMORY
;
1479 /* Copy it over, substituting the first part
1481 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1482 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1485 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1486 LocalFree(Expanded
);
1487 RtlFreeUnicodeString(&NtPathName
);
1489 /* Return success */
1490 return ERROR_SUCCESS
;
1494 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1495 LocalFree(Expanded
);
1496 RtlFreeUnicodeString(&NtPathName
);
1497 return ERROR_INVALID_PARAMETER
;
1502 DPRINT1("Error, Status = %08X\n", Status
);
1503 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1504 LocalFree(Expanded
);
1505 RtlFreeUnicodeString(&NtPathName
);
1506 return ERROR_INVALID_PARAMETER
;
1511 DPRINT1("Error, Status = %08X\n", Status
);
1512 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1513 LocalFree(Expanded
);
1514 RtlFreeUnicodeString(&NtPathName
);
1515 return ERROR_INVALID_PARAMETER
;
1520 DPRINT1("Error, Status = %08X\n", Status
);
1521 LocalFree(Expanded
);
1522 return ERROR_INVALID_PARAMETER
;
1526 *RelativeName
= NULL
;
1527 return ERROR_INVALID_PARAMETER
;
1531 ScmCanonDriverImagePath(DWORD dwStartType
,
1532 wchar_t *lpServiceName
,
1533 wchar_t **lpCanonName
)
1535 DWORD ServiceNameLen
, Result
;
1536 UNICODE_STRING NtServiceName
;
1537 WCHAR
*RelativeName
;
1538 WCHAR
*SourceName
= lpServiceName
;
1540 /* Calculate the length of the service's name */
1541 ServiceNameLen
= wcslen(lpServiceName
);
1543 /* 12 is wcslen(L"\\SystemRoot\\") */
1544 if (ServiceNameLen
> 12 &&
1545 !wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1547 /* SystemRoot prefix is already included */
1549 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1551 if (*lpCanonName
== NULL
)
1553 DPRINT1("Error allocating memory for canonized service name!\n");
1554 return ERROR_NOT_ENOUGH_MEMORY
;
1557 /* If it's a boot-time driver, it must be systemroot relative */
1558 if (dwStartType
== SERVICE_BOOT_START
)
1562 wcscpy(*lpCanonName
, SourceName
);
1564 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1568 /* Check if it has %SystemRoot% (len=13) */
1569 if (ServiceNameLen
> 13 &&
1570 !wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1572 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1573 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1575 if (*lpCanonName
== NULL
)
1577 DPRINT1("Error allocating memory for canonized service name!\n");
1578 return ERROR_NOT_ENOUGH_MEMORY
;
1581 /* If it's a boot-time driver, it must be systemroot relative */
1582 if (dwStartType
== SERVICE_BOOT_START
)
1583 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1585 wcscat(*lpCanonName
, lpServiceName
+ 13);
1587 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1591 /* Check if it's a relative path name */
1592 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1594 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1596 if (*lpCanonName
== NULL
)
1598 DPRINT1("Error allocating memory for canonized service name!\n");
1599 return ERROR_NOT_ENOUGH_MEMORY
;
1602 /* Just copy it over without changing */
1603 wcscpy(*lpCanonName
, lpServiceName
);
1608 /* It seems to be a DOS path, convert it */
1609 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1611 DPRINT1("RtlDosPathNameToNtPathName_U() failed!\n");
1612 return ERROR_INVALID_PARAMETER
;
1615 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1617 if (*lpCanonName
== NULL
)
1619 DPRINT1("Error allocating memory for canonized service name!\n");
1620 RtlFreeUnicodeString(&NtServiceName
);
1621 return ERROR_NOT_ENOUGH_MEMORY
;
1624 /* Copy the string */
1625 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1627 /* The unicode string is not needed anymore */
1628 RtlFreeUnicodeString(&NtServiceName
);
1630 if (dwStartType
!= SERVICE_BOOT_START
)
1632 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1636 /* The service is boot-started, so must be relative */
1637 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1640 /* There is a problem, free name and return */
1641 LocalFree(*lpCanonName
);
1642 DPRINT1("Error converting named!\n");
1646 ASSERT(RelativeName
);
1648 /* Copy that string */
1649 wcscpy(*lpCanonName
, RelativeName
+ 12);
1651 /* Free the allocated buffer */
1652 LocalFree(RelativeName
);
1654 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1662 DWORD
RCreateServiceW(
1663 handle_t BindingHandle
,
1664 SC_RPC_HANDLE hSCManager
,
1665 LPWSTR lpServiceName
,
1666 LPWSTR lpDisplayName
,
1667 DWORD dwDesiredAccess
,
1668 DWORD dwServiceType
,
1670 DWORD dwErrorControl
,
1671 LPWSTR lpBinaryPathName
,
1672 LPWSTR lpLoadOrderGroup
,
1674 LPBYTE lpDependencies
,
1676 LPWSTR lpServiceStartName
,
1679 LPSC_RPC_HANDLE lpServiceHandle
)
1681 PMANAGER_HANDLE hManager
;
1682 DWORD dwError
= ERROR_SUCCESS
;
1683 PSERVICE lpService
= NULL
;
1684 SC_HANDLE hServiceHandle
= NULL
;
1685 LPWSTR lpImagePath
= NULL
;
1686 HKEY hServiceKey
= NULL
;
1688 DPRINT("RCreateServiceW() called\n");
1689 DPRINT("lpServiceName = %S\n", lpServiceName
);
1690 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1691 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1692 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1693 DPRINT("dwStartType = %lu\n", dwStartType
);
1694 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1695 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1696 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1699 return ERROR_SHUTDOWN_IN_PROGRESS
;
1701 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1702 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1704 DPRINT1("Invalid manager handle!\n");
1705 return ERROR_INVALID_HANDLE
;
1708 /* Check access rights */
1709 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1710 SC_MANAGER_CREATE_SERVICE
))
1712 DPRINT1("Insufficient access rights! 0x%lx\n",
1713 hManager
->Handle
.DesiredAccess
);
1714 return ERROR_ACCESS_DENIED
;
1717 if (wcslen(lpServiceName
) == 0)
1719 return ERROR_INVALID_NAME
;
1722 if (wcslen(lpBinaryPathName
) == 0)
1724 return ERROR_INVALID_PARAMETER
;
1727 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1728 (lpServiceStartName
))
1730 return ERROR_INVALID_PARAMETER
;
1733 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1734 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1735 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1737 return ERROR_INVALID_PARAMETER
;
1740 if (dwStartType
> SERVICE_DISABLED
)
1742 return ERROR_INVALID_PARAMETER
;
1745 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1748 /* check if it is marked for deletion */
1749 if (lpService
->bDeleted
)
1750 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1751 /* Return Error exist */
1752 return ERROR_SERVICE_EXISTS
;
1755 if (lpDisplayName
!= NULL
&&
1756 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1757 return ERROR_DUPLICATE_SERVICE_NAME
;
1759 if (dwServiceType
& SERVICE_DRIVER
)
1761 dwError
= ScmCanonDriverImagePath(dwStartType
,
1764 if (dwError
!= ERROR_SUCCESS
)
1769 if (dwStartType
== SERVICE_BOOT_START
||
1770 dwStartType
== SERVICE_SYSTEM_START
)
1772 return ERROR_INVALID_PARAMETER
;
1776 /* Allocate a new service entry */
1777 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1779 if (dwError
!= ERROR_SUCCESS
)
1782 /* Fill the new service entry */
1783 lpService
->Status
.dwServiceType
= dwServiceType
;
1784 lpService
->dwStartType
= dwStartType
;
1785 lpService
->dwErrorControl
= dwErrorControl
;
1787 /* Fill the display name */
1788 if (lpDisplayName
!= NULL
&&
1789 *lpDisplayName
!= 0 &&
1790 wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1792 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1793 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1794 if (lpService
->lpDisplayName
== NULL
)
1796 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1799 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1802 /* Assign the service to a group */
1803 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1805 dwError
= ScmSetServiceGroup(lpService
,
1807 if (dwError
!= ERROR_SUCCESS
)
1811 /* Assign a new tag */
1812 if (lpdwTagId
!= NULL
)
1814 dwError
= ScmAssignNewTag(lpService
);
1815 if (dwError
!= ERROR_SUCCESS
)
1819 /* Write service data to the registry */
1820 /* Create the service key */
1821 dwError
= ScmCreateServiceKey(lpServiceName
,
1824 if (dwError
!= ERROR_SUCCESS
)
1827 /* Set the display name */
1828 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1830 RegSetValueExW(hServiceKey
,
1834 (LPBYTE
)lpDisplayName
,
1835 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1838 /* Set the service type */
1839 dwError
= RegSetValueExW(hServiceKey
,
1843 (LPBYTE
)&dwServiceType
,
1845 if (dwError
!= ERROR_SUCCESS
)
1848 /* Set the start value */
1849 dwError
= RegSetValueExW(hServiceKey
,
1853 (LPBYTE
)&dwStartType
,
1855 if (dwError
!= ERROR_SUCCESS
)
1858 /* Set the error control value */
1859 dwError
= RegSetValueExW(hServiceKey
,
1863 (LPBYTE
)&dwErrorControl
,
1865 if (dwError
!= ERROR_SUCCESS
)
1868 /* Set the image path */
1869 if (dwServiceType
& SERVICE_WIN32
)
1871 dwError
= RegSetValueExW(hServiceKey
,
1875 (LPBYTE
)lpBinaryPathName
,
1876 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1877 if (dwError
!= ERROR_SUCCESS
)
1880 else if (dwServiceType
& SERVICE_DRIVER
)
1882 dwError
= RegSetValueExW(hServiceKey
,
1886 (LPBYTE
)lpImagePath
,
1887 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1888 if (dwError
!= ERROR_SUCCESS
)
1892 /* Set the group name */
1893 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1895 dwError
= RegSetValueExW(hServiceKey
,
1899 (LPBYTE
)lpLoadOrderGroup
,
1900 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1901 if (dwError
!= ERROR_SUCCESS
)
1905 if (lpdwTagId
!= NULL
)
1907 dwError
= RegSetValueExW(hServiceKey
,
1911 (LPBYTE
)&lpService
->dwTag
,
1913 if (dwError
!= ERROR_SUCCESS
)
1917 /* Write dependencies */
1918 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1920 dwError
= ScmWriteDependencies(hServiceKey
,
1921 (LPWSTR
)lpDependencies
,
1923 if (dwError
!= ERROR_SUCCESS
)
1927 /* If a non driver and NULL for lpServiceName, write ObjectName as LocalSystem */
1928 if ((dwServiceType
& SERVICE_WIN32
) && (!lpServiceName
))
1930 dwError
= RegSetValueExW(hServiceKey
,
1934 (LPBYTE
)L
"LocalSystem",
1936 if (dwError
!= ERROR_SUCCESS
)
1940 if (lpPassword
!= NULL
)
1942 /* FIXME: Write password */
1945 dwError
= ScmCreateServiceHandle(lpService
,
1947 if (dwError
!= ERROR_SUCCESS
)
1950 dwError
= ScmCheckAccess(hServiceHandle
,
1952 if (dwError
!= ERROR_SUCCESS
)
1955 lpService
->dwRefCount
= 1;
1956 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
1959 if (hServiceKey
!= NULL
)
1960 RegCloseKey(hServiceKey
);
1962 if (dwError
== ERROR_SUCCESS
)
1964 DPRINT("hService %p\n", hServiceHandle
);
1965 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
1967 if (lpdwTagId
!= NULL
)
1968 *lpdwTagId
= lpService
->dwTag
;
1972 /* Release the display name buffer */
1973 if (lpService
->lpServiceName
!= NULL
)
1974 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1978 /* Remove the service handle */
1979 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
1982 if (lpService
!= NULL
)
1984 /* FIXME: remove the service entry */
1988 if (lpImagePath
!= NULL
)
1989 HeapFree(GetProcessHeap(), 0, lpImagePath
);
1991 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
1998 DWORD
REnumDependentServicesW(
1999 handle_t BindingHandle
,
2000 SC_RPC_HANDLE hService
,
2001 DWORD dwServiceState
,
2004 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2005 LPBOUNDED_DWORD_256K lpServicesReturned
)
2007 DWORD dwError
= ERROR_SUCCESS
;
2008 DWORD dwServicesReturned
= 0;
2009 DWORD dwServiceCount
;
2010 HKEY hServicesKey
= NULL
;
2011 LPSC_RPC_HANDLE hSCObject
;
2012 PSERVICE_HANDLE hSvc
;
2013 PSERVICE lpService
= NULL
;
2014 PSERVICE
*lpServicesArray
= NULL
;
2015 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2018 *pcbBytesNeeded
= 0;
2019 *lpServicesReturned
= 0;
2021 DPRINT("REnumDependentServicesW() called\n");
2023 hSCObject
= &hService
;
2024 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
2025 lpService
= hSvc
->ServiceEntry
;
2027 /* Check access rights */
2028 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2029 SC_MANAGER_ENUMERATE_SERVICE
))
2031 DPRINT1("Insufficient access rights! 0x%lx\n",
2032 hSvc
->Handle
.DesiredAccess
);
2033 return ERROR_ACCESS_DENIED
;
2036 /* Open the Services Reg key */
2037 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2038 L
"System\\CurrentControlSet\\Services",
2042 if (dwError
!= ERROR_SUCCESS
)
2045 /* First determine the bytes needed and get the number of dependent services */
2046 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2051 &dwServicesReturned
);
2052 if (dwError
!= ERROR_SUCCESS
)
2055 /* If buffer size is less than the bytes needed or pointer is null */
2056 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2058 dwError
= ERROR_MORE_DATA
;
2062 /* Allocate memory for array of service pointers */
2063 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2065 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2066 if (!lpServicesArray
)
2068 DPRINT1("Could not allocate a buffer!!\n");
2069 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2073 dwServicesReturned
= 0;
2074 *pcbBytesNeeded
= 0;
2076 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2081 &dwServicesReturned
);
2082 if (dwError
!= ERROR_SUCCESS
)
2087 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2088 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2090 /* Copy EnumDepenedentService to Buffer */
2091 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2093 lpService
= lpServicesArray
[dwServiceCount
];
2095 /* Copy status info */
2096 memcpy(&lpServicesPtr
->ServiceStatus
,
2098 sizeof(SERVICE_STATUS
));
2100 /* Copy display name */
2101 wcscpy(lpStr
, lpService
->lpDisplayName
);
2102 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2103 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2105 /* Copy service name */
2106 wcscpy(lpStr
, lpService
->lpServiceName
);
2107 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2108 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2113 *lpServicesReturned
= dwServicesReturned
;
2116 if (lpServicesArray
!= NULL
)
2117 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2119 RegCloseKey(hServicesKey
);
2121 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2128 DWORD
REnumServicesStatusW(
2129 handle_t BindingHandle
,
2130 SC_RPC_HANDLE hSCManager
,
2131 DWORD dwServiceType
,
2132 DWORD dwServiceState
,
2135 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2136 LPBOUNDED_DWORD_256K lpServicesReturned
,
2137 LPBOUNDED_DWORD_256K lpResumeHandle
)
2139 PMANAGER_HANDLE hManager
;
2141 DWORD dwError
= ERROR_SUCCESS
;
2142 PLIST_ENTRY ServiceEntry
;
2143 PSERVICE CurrentService
;
2145 DWORD dwRequiredSize
;
2146 DWORD dwServiceCount
;
2148 DWORD dwLastResumeCount
;
2149 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2152 DPRINT("REnumServicesStatusW() called\n");
2155 return ERROR_SHUTDOWN_IN_PROGRESS
;
2157 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2158 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2160 DPRINT1("Invalid manager handle!\n");
2161 return ERROR_INVALID_HANDLE
;
2164 /* Check access rights */
2165 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2166 SC_MANAGER_ENUMERATE_SERVICE
))
2168 DPRINT1("Insufficient access rights! 0x%lx\n",
2169 hManager
->Handle
.DesiredAccess
);
2170 return ERROR_ACCESS_DENIED
;
2173 *pcbBytesNeeded
= 0;
2174 *lpServicesReturned
= 0;
2176 dwLastResumeCount
= *lpResumeHandle
;
2178 /* FIXME: Lock the service list shared */
2180 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2181 if (lpService
== NULL
)
2183 dwError
= ERROR_SUCCESS
;
2190 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2191 ServiceEntry
!= &ServiceListHead
;
2192 ServiceEntry
= ServiceEntry
->Flink
)
2194 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2198 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2201 dwState
= SERVICE_ACTIVE
;
2202 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2203 dwState
= SERVICE_INACTIVE
;
2205 if ((dwState
& dwServiceState
) == 0)
2208 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2209 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2210 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2212 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2214 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2218 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2219 dwRequiredSize
+= dwSize
;
2221 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2224 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2225 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2228 ServiceEntry
!= &ServiceListHead
;
2229 ServiceEntry
= ServiceEntry
->Flink
)
2231 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2235 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2238 dwState
= SERVICE_ACTIVE
;
2239 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2240 dwState
= SERVICE_INACTIVE
;
2242 if ((dwState
& dwServiceState
) == 0)
2245 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2246 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2247 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2249 dwError
= ERROR_MORE_DATA
;
2252 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2254 *lpResumeHandle
= dwLastResumeCount
;
2255 *lpServicesReturned
= dwServiceCount
;
2256 *pcbBytesNeeded
= dwRequiredSize
;
2258 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2259 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2260 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2263 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2264 ServiceEntry
!= &ServiceListHead
;
2265 ServiceEntry
= ServiceEntry
->Flink
)
2267 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2271 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2274 dwState
= SERVICE_ACTIVE
;
2275 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2276 dwState
= SERVICE_INACTIVE
;
2278 if ((dwState
& dwServiceState
) == 0)
2281 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2282 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2283 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2285 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2288 /* Copy the service name */
2289 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2290 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2291 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2293 /* Copy the display name */
2294 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2295 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2296 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2298 /* Copy the status information */
2299 memcpy(&lpStatusPtr
->ServiceStatus
,
2300 &CurrentService
->Status
,
2301 sizeof(SERVICE_STATUS
));
2304 dwRequiredSize
+= dwSize
;
2308 /* FIXME: Unlock the service list */
2310 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2317 DWORD
ROpenSCManagerW(
2318 handle_t BindingHandle
,
2319 LPWSTR lpMachineName
,
2320 LPWSTR lpDatabaseName
,
2321 DWORD dwDesiredAccess
,
2322 LPSC_RPC_HANDLE lpScHandle
)
2327 DPRINT("ROpenSCManagerW() called\n");
2328 DPRINT("lpMachineName = %p\n", lpMachineName
);
2329 DPRINT("lpMachineName: %S\n", lpMachineName
);
2330 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2331 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2332 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2335 return ERROR_SHUTDOWN_IN_PROGRESS
;
2338 return ERROR_INVALID_PARAMETER
;
2340 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2342 if (dwError
!= ERROR_SUCCESS
)
2344 DPRINT1("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2348 /* Check the desired access */
2349 dwError
= ScmCheckAccess(hHandle
,
2350 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2351 if (dwError
!= ERROR_SUCCESS
)
2353 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2354 HeapFree(GetProcessHeap(), 0, hHandle
);
2358 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2359 DPRINT("*hScm = %p\n", *lpScHandle
);
2361 DPRINT("ROpenSCManagerW() done\n");
2363 return ERROR_SUCCESS
;
2368 DWORD
ROpenServiceW(
2369 handle_t BindingHandle
,
2370 SC_RPC_HANDLE hSCManager
,
2371 LPWSTR lpServiceName
,
2372 DWORD dwDesiredAccess
,
2373 LPSC_RPC_HANDLE lpServiceHandle
)
2376 PMANAGER_HANDLE hManager
;
2380 DPRINT("ROpenServiceW() called\n");
2381 DPRINT("hSCManager = %p\n", hSCManager
);
2382 DPRINT("lpServiceName = %p\n", lpServiceName
);
2383 DPRINT("lpServiceName: %S\n", lpServiceName
);
2384 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2387 return ERROR_SHUTDOWN_IN_PROGRESS
;
2389 if (!lpServiceHandle
)
2390 return ERROR_INVALID_PARAMETER
;
2393 return ERROR_INVALID_ADDRESS
;
2395 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2396 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2398 DPRINT1("Invalid manager handle!\n");
2399 return ERROR_INVALID_HANDLE
;
2402 /* FIXME: Lock the service list */
2404 /* Get service database entry */
2405 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2406 if (lpService
== NULL
)
2408 DPRINT("Could not find a service!\n");
2409 return ERROR_SERVICE_DOES_NOT_EXIST
;
2412 /* Create a service handle */
2413 dwError
= ScmCreateServiceHandle(lpService
,
2415 if (dwError
!= ERROR_SUCCESS
)
2417 DPRINT1("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2421 /* Check the desired access */
2422 dwError
= ScmCheckAccess(hHandle
,
2424 if (dwError
!= ERROR_SUCCESS
)
2426 DPRINT1("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2427 HeapFree(GetProcessHeap(), 0, hHandle
);
2431 lpService
->dwRefCount
++;
2432 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2434 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2435 DPRINT("*hService = %p\n", *lpServiceHandle
);
2437 DPRINT("ROpenServiceW() done\n");
2439 return ERROR_SUCCESS
;
2444 DWORD
RQueryServiceConfigW(
2445 handle_t BindingHandle
,
2446 SC_RPC_HANDLE hService
,
2447 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2449 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2451 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2452 DWORD dwError
= ERROR_SUCCESS
;
2453 PSERVICE_HANDLE hSvc
;
2454 PSERVICE lpService
= NULL
;
2455 HKEY hServiceKey
= NULL
;
2456 LPWSTR lpImagePath
= NULL
;
2457 LPWSTR lpServiceStartName
= NULL
;
2458 DWORD dwRequiredSize
;
2459 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2460 WCHAR lpEmptyString
[] = {0,0};
2463 DPRINT("RQueryServiceConfigW() called\n");
2466 return ERROR_SHUTDOWN_IN_PROGRESS
;
2468 hSvc
= (PSERVICE_HANDLE
)hService
;
2469 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2471 DPRINT1("Invalid handle tag!\n");
2472 return ERROR_INVALID_HANDLE
;
2475 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2476 SERVICE_QUERY_CONFIG
))
2478 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2479 return ERROR_ACCESS_DENIED
;
2482 lpService
= hSvc
->ServiceEntry
;
2483 if (lpService
== NULL
)
2485 DPRINT1("lpService == NULL!\n");
2486 return ERROR_INVALID_HANDLE
;
2489 /* FIXME: Lock the service database shared */
2491 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2494 if (dwError
!= ERROR_SUCCESS
)
2497 dwError
= ScmReadString(hServiceKey
,
2500 if (dwError
!= ERROR_SUCCESS
)
2503 ScmReadString(hServiceKey
,
2505 &lpServiceStartName
);
2507 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2509 if (lpImagePath
!= NULL
)
2510 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2512 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2514 if (lpService
->lpGroup
!= NULL
)
2515 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2517 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2519 /* FIXME: Add Dependencies length*/
2521 if (lpServiceStartName
!= NULL
)
2522 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2524 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2526 if (lpService
->lpDisplayName
!= NULL
)
2527 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2529 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2531 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2533 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2537 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2538 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2539 lpConfig
->dwStartType
= lpService
->dwStartType
;
2540 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2541 lpConfig
->dwTagId
= lpService
->dwTag
;
2543 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2545 if (lpImagePath
!= NULL
)
2547 wcscpy(lpStr
, lpImagePath
);
2551 wcscpy(lpStr
, lpEmptyString
);
2554 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2555 lpStr
+= (wcslen(lpStr
) + 1);
2557 if (lpService
->lpGroup
!= NULL
)
2559 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2563 wcscpy(lpStr
, lpEmptyString
);
2566 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2567 lpStr
+= (wcslen(lpStr
) + 1);
2569 /* FIXME: Append Dependencies */
2570 wcscpy(lpStr
, lpEmptyString
);
2572 lpStr
+= (wcslen(lpStr
) + 1);
2573 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2575 if (lpServiceStartName
!= NULL
)
2577 wcscpy(lpStr
, lpServiceStartName
);
2581 wcscpy(lpStr
, lpEmptyString
);
2584 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2585 lpStr
+= (wcslen(lpStr
) + 1);
2587 if (lpService
->lpDisplayName
!= NULL
)
2589 wcscpy(lpStr
, lpService
->lpDisplayName
);
2593 wcscpy(lpStr
, lpEmptyString
);
2596 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2599 if (pcbBytesNeeded
!= NULL
)
2600 *pcbBytesNeeded
= dwRequiredSize
;
2603 if (lpImagePath
!= NULL
)
2604 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2606 if (lpServiceStartName
!= NULL
)
2607 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2609 if (hServiceKey
!= NULL
)
2610 RegCloseKey(hServiceKey
);
2612 /* FIXME: Unlock the service database */
2614 DPRINT("RQueryServiceConfigW() done\n");
2621 DWORD
RQueryServiceLockStatusW(
2622 handle_t BindingHandle
,
2623 SC_RPC_HANDLE hSCManager
,
2624 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2626 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2629 return ERROR_CALL_NOT_IMPLEMENTED
;
2634 DWORD
RStartServiceW(
2635 handle_t BindingHandle
,
2636 SC_RPC_HANDLE hService
,
2638 LPSTRING_PTRSW argv
)
2640 DWORD dwError
= ERROR_SUCCESS
;
2641 PSERVICE_HANDLE hSvc
;
2642 PSERVICE lpService
= NULL
;
2644 DPRINT("RStartServiceW() called\n");
2647 return ERROR_SHUTDOWN_IN_PROGRESS
;
2649 hSvc
= (PSERVICE_HANDLE
)hService
;
2650 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2652 DPRINT1("Invalid handle tag!\n");
2653 return ERROR_INVALID_HANDLE
;
2656 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2659 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2660 return ERROR_ACCESS_DENIED
;
2663 lpService
= hSvc
->ServiceEntry
;
2664 if (lpService
== NULL
)
2666 DPRINT1("lpService == NULL!\n");
2667 return ERROR_INVALID_HANDLE
;
2670 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2671 return ERROR_SERVICE_DISABLED
;
2673 if (lpService
->bDeleted
)
2674 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2681 /* Start the service */
2682 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2689 DWORD
RGetServiceDisplayNameW(
2690 handle_t BindingHandle
,
2691 SC_RPC_HANDLE hSCManager
,
2692 LPWSTR lpServiceName
,
2693 LPWSTR lpDisplayName
,
2696 // PMANAGER_HANDLE hManager;
2701 DPRINT("RGetServiceDisplayNameW() called\n");
2702 DPRINT("hSCManager = %p\n", hSCManager
);
2703 DPRINT("lpServiceName: %S\n", lpServiceName
);
2704 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2705 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2707 // hManager = (PMANAGER_HANDLE)hSCManager;
2708 // if (hManager->Handle.Tag != MANAGER_TAG)
2710 // DPRINT1("Invalid manager handle!\n");
2711 // return ERROR_INVALID_HANDLE;
2714 /* Get service database entry */
2715 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2716 if (lpService
== NULL
)
2718 DPRINT1("Could not find a service!\n");
2720 /* If the service could not be found and lpcchBuffer is 0, windows
2721 puts null in lpDisplayName and puts 1 in lpcchBuffer */
2722 if (*lpcchBuffer
== 0)
2725 *lpDisplayName
= '\0';
2728 return ERROR_SERVICE_DOES_NOT_EXIST
;
2731 if (!lpService
->lpDisplayName
)
2733 dwLength
= wcslen(lpService
->lpServiceName
);
2735 if (lpServiceName
!= NULL
&&
2736 *lpcchBuffer
> dwLength
)
2738 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2743 dwLength
= wcslen(lpService
->lpDisplayName
);
2745 if (lpDisplayName
!= NULL
&&
2746 *lpcchBuffer
> dwLength
)
2748 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2752 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2754 *lpcchBuffer
= dwLength
;
2761 DWORD
RGetServiceKeyNameW(
2762 handle_t BindingHandle
,
2763 SC_RPC_HANDLE hSCManager
,
2764 LPWSTR lpDisplayName
,
2765 LPWSTR lpServiceName
,
2768 // PMANAGER_HANDLE hManager;
2773 DPRINT("RGetServiceKeyNameW() called\n");
2774 DPRINT("hSCManager = %p\n", hSCManager
);
2775 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2776 DPRINT("lpServiceName: %p\n", lpServiceName
);
2777 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2779 // hManager = (PMANAGER_HANDLE)hSCManager;
2780 // if (hManager->Handle.Tag != MANAGER_TAG)
2782 // DPRINT1("Invalid manager handle!\n");
2783 // return ERROR_INVALID_HANDLE;
2786 /* Get service database entry */
2787 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2788 if (lpService
== NULL
)
2790 DPRINT1("Could not find a service!\n");
2792 /* If the service could not be found and lpcchBuffer is 0, windows
2793 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2794 if (*lpcchBuffer
== 0)
2797 *lpServiceName
= '\0';
2800 return ERROR_SERVICE_DOES_NOT_EXIST
;
2803 dwLength
= wcslen(lpService
->lpServiceName
);
2805 if (lpServiceName
!= NULL
&&
2806 *lpcchBuffer
> dwLength
)
2808 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2809 *lpcchBuffer
= dwLength
;
2810 return ERROR_SUCCESS
;
2813 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2815 *lpcchBuffer
= dwLength
* 2;
2822 DWORD
RI_ScSetServiceBitsA(
2823 handle_t BindingHandle
,
2824 SC_RPC_HANDLE hServiceStatus
,
2825 DWORD dwServiceBits
,
2827 int bUpdateImmediately
,
2831 return ERROR_CALL_NOT_IMPLEMENTED
;
2836 DWORD
RChangeServiceConfigA(
2837 handle_t BindingHandle
,
2838 SC_RPC_HANDLE hService
,
2839 DWORD dwServiceType
,
2841 DWORD dwErrorControl
,
2842 LPSTR lpBinaryPathName
,
2843 LPSTR lpLoadOrderGroup
,
2845 LPSTR lpDependencies
,
2847 LPSTR lpServiceStartName
,
2850 LPSTR lpDisplayName
)
2852 DWORD dwError
= ERROR_SUCCESS
;
2853 PSERVICE_HANDLE hSvc
;
2854 PSERVICE lpService
= NULL
;
2855 HKEY hServiceKey
= NULL
;
2856 LPWSTR lpDisplayNameW
= NULL
;
2857 // LPWSTR lpBinaryPathNameW = NULL;
2858 LPWSTR lpLoadOrderGroupW
= NULL
;
2859 LPWSTR lpDependenciesW
= NULL
;
2860 // LPWSTR lpPasswordW = NULL;
2862 DPRINT("RChangeServiceConfigA() called\n");
2863 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2864 DPRINT("dwStartType = %lu\n", dwStartType
);
2865 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2866 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2867 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2868 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2871 return ERROR_SHUTDOWN_IN_PROGRESS
;
2873 hSvc
= (PSERVICE_HANDLE
)hService
;
2874 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2876 DPRINT1("Invalid handle tag!\n");
2877 return ERROR_INVALID_HANDLE
;
2880 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2881 SERVICE_CHANGE_CONFIG
))
2883 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2884 return ERROR_ACCESS_DENIED
;
2887 lpService
= hSvc
->ServiceEntry
;
2888 if (lpService
== NULL
)
2890 DPRINT1("lpService == NULL!\n");
2891 return ERROR_INVALID_HANDLE
;
2894 /* FIXME: Lock database exclusively */
2896 if (lpService
->bDeleted
)
2898 /* FIXME: Unlock database */
2899 DPRINT1("The service has already been marked for delete!\n");
2900 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2903 /* Open the service key */
2904 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
2907 if (dwError
!= ERROR_SUCCESS
)
2910 /* Write service data to the registry */
2912 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
2914 /* Set the display name */
2915 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
2917 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
2918 if (lpDisplayNameW
== NULL
)
2920 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2924 MultiByteToWideChar(CP_ACP
,
2929 wcslen(lpDisplayNameW
) + 1);
2931 RegSetValueExW(hServiceKey
,
2935 (LPBYTE
)lpDisplayNameW
,
2936 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
2938 /* Update lpService->lpDisplayName */
2939 if (lpService
->lpDisplayName
)
2940 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2942 lpService
->lpDisplayName
= lpDisplayNameW
;
2945 if (dwServiceType
!= SERVICE_NO_CHANGE
)
2947 /* Set the service type */
2948 dwError
= RegSetValueExW(hServiceKey
,
2952 (LPBYTE
)&dwServiceType
,
2954 if (dwError
!= ERROR_SUCCESS
)
2957 lpService
->Status
.dwServiceType
= dwServiceType
;
2960 if (dwStartType
!= SERVICE_NO_CHANGE
)
2962 /* Set the start value */
2963 dwError
= RegSetValueExW(hServiceKey
,
2967 (LPBYTE
)&dwStartType
,
2969 if (dwError
!= ERROR_SUCCESS
)
2972 lpService
->dwStartType
= dwStartType
;
2975 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
2977 /* Set the error control value */
2978 dwError
= RegSetValueExW(hServiceKey
,
2982 (LPBYTE
)&dwErrorControl
,
2984 if (dwError
!= ERROR_SUCCESS
)
2987 lpService
->dwErrorControl
= dwErrorControl
;
2991 /* FIXME: set the new ImagePath value */
2993 /* Set the image path */
2994 if (dwServiceType
& SERVICE_WIN32
)
2996 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
2998 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
2999 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, wcslen(lpBinaryPathNameW
)+1);
3000 dwError
= RegSetValueExW(hServiceKey
,
3004 (LPBYTE
)lpBinaryPathNameW
,
3005 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3006 if (dwError
!= ERROR_SUCCESS
)
3010 else if (dwServiceType
& SERVICE_DRIVER
)
3012 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3014 dwError
= RegSetValueExW(hServiceKey
,
3018 (LPBYTE
)lpImagePath
,
3019 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3020 if (dwError
!= ERROR_SUCCESS
)
3026 /* Set the group name */
3027 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3029 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3031 (strlen(lpLoadOrderGroup
)+1) * sizeof(WCHAR
));
3032 if (lpLoadOrderGroupW
== NULL
)
3034 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3038 MultiByteToWideChar(CP_ACP
,
3043 wcslen(lpLoadOrderGroupW
) + 1);
3045 dwError
= RegSetValueExW(hServiceKey
,
3049 (LPBYTE
)lpLoadOrderGroupW
,
3050 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3051 if (dwError
!= ERROR_SUCCESS
)
3054 /* FIXME: Update lpService->lpServiceGroup */
3056 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3059 if (lpdwTagId
!= NULL
)
3061 dwError
= ScmAssignNewTag(lpService
);
3062 if (dwError
!= ERROR_SUCCESS
)
3065 dwError
= RegSetValueExW(hServiceKey
,
3069 (LPBYTE
)&lpService
->dwTag
,
3071 if (dwError
!= ERROR_SUCCESS
)
3074 *lpdwTagId
= lpService
->dwTag
;
3077 /* Write dependencies */
3078 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3080 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3082 (strlen(lpDependencies
)+1) * sizeof(WCHAR
));
3083 if (lpDependenciesW
== NULL
)
3085 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3089 MultiByteToWideChar(CP_ACP
,
3094 wcslen(lpDependenciesW
)+1);
3096 dwError
= ScmWriteDependencies(hServiceKey
,
3097 (LPWSTR
)lpDependenciesW
,
3100 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3103 if (lpPassword
!= NULL
)
3105 /* FIXME: Write password */
3108 /* FIXME: Unlock database */
3111 if (hServiceKey
!= NULL
)
3112 RegCloseKey(hServiceKey
);
3114 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3121 DWORD
RCreateServiceA(
3122 handle_t BindingHandle
,
3123 SC_RPC_HANDLE hSCManager
,
3124 LPSTR lpServiceName
,
3125 LPSTR lpDisplayName
,
3126 DWORD dwDesiredAccess
,
3127 DWORD dwServiceType
,
3129 DWORD dwErrorControl
,
3130 LPSTR lpBinaryPathName
,
3131 LPSTR lpLoadOrderGroup
,
3133 LPBYTE lpDependencies
,
3135 LPSTR lpServiceStartName
,
3138 LPSC_RPC_HANDLE lpServiceHandle
)
3141 return ERROR_CALL_NOT_IMPLEMENTED
;
3146 DWORD
REnumDependentServicesA(
3147 handle_t BindingHandle
,
3148 SC_RPC_HANDLE hService
,
3149 DWORD dwServiceState
,
3152 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3153 LPBOUNDED_DWORD_256K lpServicesReturned
)
3155 DWORD dwError
= ERROR_SUCCESS
;
3156 DWORD dwServicesReturned
= 0;
3157 DWORD dwServiceCount
;
3158 HKEY hServicesKey
= NULL
;
3159 LPSC_RPC_HANDLE hSCObject
;
3160 PSERVICE_HANDLE hSvc
;
3161 PSERVICE lpService
= NULL
;
3162 PSERVICE
*lpServicesArray
= NULL
;
3163 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3166 *pcbBytesNeeded
= 0;
3167 *lpServicesReturned
= 0;
3169 DPRINT("REnumDependentServicesA() called\n");
3171 hSCObject
= &hService
;
3172 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3173 lpService
= hSvc
->ServiceEntry
;
3175 /* Check access rights */
3176 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3177 SC_MANAGER_ENUMERATE_SERVICE
))
3179 DPRINT1("Insufficient access rights! 0x%lx\n",
3180 hSvc
->Handle
.DesiredAccess
);
3181 return ERROR_ACCESS_DENIED
;
3184 /* Open the Services Reg key */
3185 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3186 L
"System\\CurrentControlSet\\Services",
3191 if (dwError
!= ERROR_SUCCESS
) return dwError
;
3193 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3194 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3195 are the same for both. Verified in WINXP. */
3197 /* First determine the bytes needed and get the number of dependent services*/
3198 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3203 &dwServicesReturned
);
3204 if (dwError
!= ERROR_SUCCESS
)
3207 /* If buffer size is less than the bytes needed or pointer is null*/
3208 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3210 dwError
= ERROR_MORE_DATA
;
3214 /* Allocate memory for array of service pointers */
3215 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3217 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3218 if (!lpServicesArray
)
3220 DPRINT1("Could not allocate a buffer!!\n");
3221 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3225 dwServicesReturned
= 0;
3226 *pcbBytesNeeded
= 0;
3228 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3233 &dwServicesReturned
);
3234 if (dwError
!= ERROR_SUCCESS
)
3239 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3240 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3242 /* Copy EnumDepenedentService to Buffer */
3243 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3245 lpService
= lpServicesArray
[dwServiceCount
];
3247 /* Copy the status info */
3248 memcpy(&lpServicesPtr
->ServiceStatus
,
3250 sizeof(SERVICE_STATUS
));
3252 /* Copy display name */
3253 WideCharToMultiByte(CP_ACP
,
3255 lpService
->lpDisplayName
,
3258 wcslen(lpService
->lpDisplayName
),
3261 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3262 lpStr
+= strlen(lpStr
) + 1;
3264 /* Copy service name */
3265 WideCharToMultiByte(CP_ACP
,
3267 lpService
->lpServiceName
,
3270 wcslen(lpService
->lpServiceName
),
3273 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3274 lpStr
+= strlen(lpStr
) + 1;
3279 *lpServicesReturned
= dwServicesReturned
;
3282 if (lpServicesArray
)
3283 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3285 RegCloseKey(hServicesKey
);
3287 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3294 DWORD
REnumServicesStatusA(
3295 handle_t BindingHandle
,
3296 SC_RPC_HANDLE hSCManager
,
3297 DWORD dwServiceType
,
3298 DWORD dwServiceState
,
3301 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3302 LPBOUNDED_DWORD_256K lpServicesReturned
,
3303 LPBOUNDED_DWORD_256K lpResumeHandle
)
3306 return ERROR_CALL_NOT_IMPLEMENTED
;
3311 DWORD
ROpenSCManagerA(
3312 handle_t BindingHandle
,
3313 LPSTR lpMachineName
,
3314 LPSTR lpDatabaseName
,
3315 DWORD dwDesiredAccess
,
3316 LPSC_RPC_HANDLE lpScHandle
)
3318 UNICODE_STRING MachineName
;
3319 UNICODE_STRING DatabaseName
;
3322 DPRINT("ROpenSCManagerA() called\n");
3325 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3329 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3332 dwError
= ROpenSCManagerW(BindingHandle
,
3333 lpMachineName
? MachineName
.Buffer
: NULL
,
3334 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3339 RtlFreeUnicodeString(&MachineName
);
3342 RtlFreeUnicodeString(&DatabaseName
);
3349 DWORD
ROpenServiceA(
3350 handle_t BindingHandle
,
3351 SC_RPC_HANDLE hSCManager
,
3352 LPSTR lpServiceName
,
3353 DWORD dwDesiredAccess
,
3354 LPSC_RPC_HANDLE lpServiceHandle
)
3356 UNICODE_STRING ServiceName
;
3359 DPRINT("ROpenServiceA() called\n");
3362 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3365 dwError
= ROpenServiceW(BindingHandle
,
3367 lpServiceName
? ServiceName
.Buffer
: NULL
,
3372 RtlFreeUnicodeString(&ServiceName
);
3379 DWORD
RQueryServiceConfigA(
3380 handle_t BindingHandle
,
3381 SC_RPC_HANDLE hService
,
3382 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3384 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3386 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3387 DWORD dwError
= ERROR_SUCCESS
;
3388 PSERVICE_HANDLE hSvc
;
3389 PSERVICE lpService
= NULL
;
3390 HKEY hServiceKey
= NULL
;
3391 LPWSTR lpImagePath
= NULL
;
3392 LPWSTR lpServiceStartName
= NULL
;
3393 DWORD dwRequiredSize
;
3394 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3395 CHAR lpEmptyString
[]={0,0};
3398 DPRINT("RQueryServiceConfigA() called\n");
3401 return ERROR_SHUTDOWN_IN_PROGRESS
;
3403 hSvc
= (PSERVICE_HANDLE
)hService
;
3404 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3406 DPRINT1("Invalid handle tag!\n");
3407 return ERROR_INVALID_HANDLE
;
3410 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3411 SERVICE_QUERY_CONFIG
))
3413 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3414 return ERROR_ACCESS_DENIED
;
3417 lpService
= hSvc
->ServiceEntry
;
3418 if (lpService
== NULL
)
3420 DPRINT1("lpService == NULL!\n");
3421 return ERROR_INVALID_HANDLE
;
3424 /* FIXME: Lock the service database shared */
3426 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3429 if (dwError
!= ERROR_SUCCESS
)
3432 dwError
= ScmReadString(hServiceKey
,
3435 if (dwError
!= ERROR_SUCCESS
)
3438 ScmReadString(hServiceKey
,
3440 &lpServiceStartName
);
3442 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3444 if (lpImagePath
!= NULL
)
3445 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3447 dwRequiredSize
+= 2;
3449 if (lpService
->lpGroup
!= NULL
)
3450 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3452 dwRequiredSize
+= 2;
3454 /* FIXME: Add Dependencies length*/
3455 dwRequiredSize
+= 2;
3457 if (lpServiceStartName
!= NULL
)
3458 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3460 dwRequiredSize
+= 2;
3462 if (lpService
->lpDisplayName
!= NULL
)
3463 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3465 dwRequiredSize
+= 2;
3467 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3469 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3473 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3474 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3475 lpConfig
->dwStartType
= lpService
->dwStartType
;
3476 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3477 lpConfig
->dwTagId
= lpService
->dwTag
;
3479 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3481 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3486 WideCharToMultiByte(CP_ACP
,
3491 wcslen(lpImagePath
),
3497 strcpy(lpStr
, lpEmptyString
);
3500 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3501 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3503 if (lpService
->lpGroup
)
3505 WideCharToMultiByte(CP_ACP
,
3507 lpService
->lpGroup
->lpGroupName
,
3510 wcslen(lpService
->lpGroup
->lpGroupName
),
3516 strcpy(lpStr
, lpEmptyString
);
3519 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3520 lpStr
+= (strlen(lpStr
) + 1);
3522 /* FIXME: Append Dependencies */
3523 strcpy(lpStr
, lpEmptyString
);
3525 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3526 lpStr
+= (strlen(lpStr
) + 1);
3528 if (lpServiceStartName
)
3530 WideCharToMultiByte(CP_ACP
,
3535 wcslen(lpServiceStartName
),
3541 strcpy(lpStr
, lpEmptyString
);
3544 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3545 lpStr
+= (strlen(lpStr
) + 1);
3547 if (lpService
->lpDisplayName
)
3549 WideCharToMultiByte(CP_ACP
,
3551 lpService
->lpDisplayName
,
3554 wcslen(lpService
->lpDisplayName
),
3560 strcpy(lpStr
, lpEmptyString
);
3563 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3566 if (pcbBytesNeeded
!= NULL
)
3567 *pcbBytesNeeded
= dwRequiredSize
;
3570 if (lpImagePath
!= NULL
)
3571 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3573 if (lpServiceStartName
!= NULL
)
3574 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3576 if (hServiceKey
!= NULL
)
3577 RegCloseKey(hServiceKey
);
3579 /* FIXME: Unlock the service database */
3581 DPRINT("RQueryServiceConfigA() done\n");
3588 DWORD
RQueryServiceLockStatusA(
3589 handle_t BindingHandle
,
3590 SC_RPC_HANDLE hSCManager
,
3591 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
3593 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3596 return ERROR_CALL_NOT_IMPLEMENTED
;
3601 DWORD
RStartServiceA(
3602 handle_t BindingHandle
,
3603 SC_RPC_HANDLE hService
,
3605 LPSTRING_PTRSA argv
)
3607 DWORD dwError
= ERROR_SUCCESS
;
3608 PSERVICE_HANDLE hSvc
;
3609 PSERVICE lpService
= NULL
;
3611 DPRINT1("RStartServiceA() called\n");
3614 return ERROR_SHUTDOWN_IN_PROGRESS
;
3616 hSvc
= (PSERVICE_HANDLE
)hService
;
3617 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3619 DPRINT1("Invalid handle tag!\n");
3620 return ERROR_INVALID_HANDLE
;
3623 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3626 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3627 return ERROR_ACCESS_DENIED
;
3630 lpService
= hSvc
->ServiceEntry
;
3631 if (lpService
== NULL
)
3633 DPRINT1("lpService == NULL!\n");
3634 return ERROR_INVALID_HANDLE
;
3637 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3638 return ERROR_SERVICE_DISABLED
;
3640 if (lpService
->bDeleted
)
3641 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3643 /* FIXME: Convert argument vector to Unicode */
3645 /* Start the service */
3646 dwError
= ScmStartService(lpService
, 0, NULL
);
3648 /* FIXME: Free argument vector */
3655 DWORD
RGetServiceDisplayNameA(
3656 handle_t BindingHandle
,
3657 SC_RPC_HANDLE hSCManager
,
3658 LPSTR lpServiceName
,
3659 LPSTR lpDisplayName
,
3660 LPBOUNDED_DWORD_4K lpcchBuffer
)
3662 // PMANAGER_HANDLE hManager;
3666 LPWSTR lpServiceNameW
;
3668 DPRINT("RGetServiceDisplayNameA() called\n");
3669 DPRINT("hSCManager = %p\n", hSCManager
);
3670 DPRINT("lpServiceName: %s\n", lpServiceName
);
3671 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
3672 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3674 // hManager = (PMANAGER_HANDLE)hSCManager;
3675 // if (hManager->Handle.Tag != MANAGER_TAG)
3677 // DPRINT1("Invalid manager handle!\n");
3678 // return ERROR_INVALID_HANDLE;
3681 dwLength
= strlen(lpServiceName
) + 1;
3682 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
3684 dwLength
* sizeof(WCHAR
));
3685 if (!lpServiceNameW
)
3686 return ERROR_NOT_ENOUGH_MEMORY
;
3688 MultiByteToWideChar(CP_ACP
,
3691 strlen(lpServiceName
),
3695 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
3697 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3699 if (lpService
== NULL
)
3701 DPRINT1("Could not find a service!\n");
3703 /* If the service could not be found and lpcchBuffer is 0, windows
3704 puts null in lpDisplayName and puts 1 in lpcchBuffer */
3705 if (*lpcchBuffer
== 0)
3708 *lpDisplayName
= '\0';
3710 return ERROR_SERVICE_DOES_NOT_EXIST
;
3713 if (!lpService
->lpDisplayName
)
3715 dwLength
= wcslen(lpService
->lpServiceName
);
3716 if (lpServiceName
!= NULL
&&
3717 *lpcchBuffer
> dwLength
)
3719 WideCharToMultiByte(CP_ACP
,
3721 lpService
->lpServiceName
,
3722 wcslen(lpService
->lpServiceName
),
3727 return ERROR_SUCCESS
;
3732 dwLength
= wcslen(lpService
->lpDisplayName
);
3733 if (lpDisplayName
!= NULL
&&
3734 *lpcchBuffer
> dwLength
)
3736 WideCharToMultiByte(CP_ACP
,
3738 lpService
->lpDisplayName
,
3739 wcslen(lpService
->lpDisplayName
),
3744 return ERROR_SUCCESS
;
3748 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3750 *lpcchBuffer
= dwLength
* 2;
3757 DWORD
RGetServiceKeyNameA(
3758 handle_t BindingHandle
,
3759 SC_RPC_HANDLE hSCManager
,
3760 LPSTR lpDisplayName
,
3761 LPSTR lpServiceName
,
3762 LPBOUNDED_DWORD_4K lpcchBuffer
)
3767 LPWSTR lpDisplayNameW
;
3769 DPRINT("RGetServiceKeyNameA() called\n");
3770 DPRINT("hSCManager = %p\n", hSCManager
);
3771 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
3772 DPRINT("lpServiceName: %p\n", lpServiceName
);
3773 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
3775 dwLength
= strlen(lpDisplayName
) + 1;
3776 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3778 dwLength
* sizeof(WCHAR
));
3779 if (!lpDisplayNameW
)
3780 return ERROR_NOT_ENOUGH_MEMORY
;
3782 MultiByteToWideChar(CP_ACP
,
3785 strlen(lpDisplayName
),
3789 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
3791 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3793 if (lpService
== NULL
)
3795 DPRINT1("Could not find the service!\n");
3797 /* If the service could not be found and lpcchBuffer is 0,
3798 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
3799 if (*lpcchBuffer
== 0)
3802 *lpServiceName
= '\0';
3805 return ERROR_SERVICE_DOES_NOT_EXIST
;
3808 dwLength
= wcslen(lpService
->lpServiceName
);
3809 if (lpService
!= NULL
&&
3810 *lpcchBuffer
> dwLength
)
3812 WideCharToMultiByte(CP_ACP
,
3814 lpService
->lpServiceName
,
3815 wcslen(lpService
->lpServiceName
),
3820 return ERROR_SUCCESS
;
3823 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3825 *lpcchBuffer
= dwLength
* 2;
3832 DWORD
RI_ScGetCurrentGroupStateW(
3833 handle_t BindingHandle
,
3834 SC_RPC_HANDLE hSCManager
,
3835 LPWSTR lpLoadOrderGroup
,
3839 return ERROR_CALL_NOT_IMPLEMENTED
;
3844 DWORD
REnumServiceGroupW(
3845 handle_t BindingHandle
,
3846 SC_RPC_HANDLE hSCManager
,
3847 DWORD dwServiceType
,
3848 DWORD dwServiceState
,
3851 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3852 LPBOUNDED_DWORD_256K lpServicesReturned
,
3853 LPBOUNDED_DWORD_256K lpResumeIndex
,
3854 LPCWSTR pszGroupName
)
3857 return ERROR_CALL_NOT_IMPLEMENTED
;
3862 DWORD
RChangeServiceConfig2A(
3863 handle_t BindingHandle
,
3864 SC_RPC_HANDLE hService
,
3865 SC_RPC_CONFIG_INFOA Info
)
3868 return ERROR_CALL_NOT_IMPLEMENTED
;
3873 DWORD
RChangeServiceConfig2W(
3874 handle_t BindingHandle
,
3875 SC_RPC_HANDLE hService
,
3876 SC_RPC_CONFIG_INFOW Info
)
3878 DWORD dwError
= ERROR_SUCCESS
;
3879 PSERVICE_HANDLE hSvc
;
3880 PSERVICE lpService
= NULL
;
3881 HKEY hServiceKey
= NULL
;
3883 DPRINT("RChangeServiceConfig2W() called\n");
3884 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
3887 return ERROR_SHUTDOWN_IN_PROGRESS
;
3889 hSvc
= (PSERVICE_HANDLE
)hService
;
3890 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3892 DPRINT1("Invalid handle tag!\n");
3893 return ERROR_INVALID_HANDLE
;
3896 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3897 SERVICE_CHANGE_CONFIG
))
3899 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3900 return ERROR_ACCESS_DENIED
;
3903 lpService
= hSvc
->ServiceEntry
;
3904 if (lpService
== NULL
)
3906 DPRINT1("lpService == NULL!\n");
3907 return ERROR_INVALID_HANDLE
;
3910 /* FIXME: Lock database exclusively */
3912 if (lpService
->bDeleted
)
3914 /* FIXME: Unlock database */
3915 DPRINT1("The service has already been marked for delete!\n");
3916 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3919 /* Open the service key */
3920 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3923 if (dwError
!= ERROR_SUCCESS
)
3926 if (Info
.dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
3928 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
3930 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)&Info
;
3931 lpServiceDescription
->lpDescription
= (LPWSTR
)(&Info
+ sizeof(LPSERVICE_DESCRIPTIONW
));
3933 if (lpServiceDescription
!= NULL
&&
3934 lpServiceDescription
->lpDescription
!= NULL
)
3936 RegSetValueExW(hServiceKey
,
3940 (LPBYTE
)lpServiceDescription
->lpDescription
,
3941 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
3943 if (dwError
!= ERROR_SUCCESS
)
3947 else if (Info
.dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
3950 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
3955 /* FIXME: Unlock database */
3956 if (hServiceKey
!= NULL
)
3957 RegCloseKey(hServiceKey
);
3959 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
3966 DWORD
RQueryServiceConfig2A(
3967 handle_t BindingHandle
,
3968 SC_RPC_HANDLE hService
,
3972 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3974 DWORD dwError
= ERROR_SUCCESS
;
3975 PSERVICE_HANDLE hSvc
;
3976 PSERVICE lpService
= NULL
;
3977 HKEY hServiceKey
= NULL
;
3978 DWORD dwRequiredSize
;
3979 LPWSTR lpDescriptionW
= NULL
;
3980 LPSTR lpDescription
= NULL
;
3982 DPRINT("RQueryServiceConfig2W() called\n");
3985 return ERROR_INVALID_ADDRESS
;
3988 return ERROR_SHUTDOWN_IN_PROGRESS
;
3990 hSvc
= (PSERVICE_HANDLE
)hService
;
3991 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3993 DPRINT1("Invalid handle tag!\n");
3994 return ERROR_INVALID_HANDLE
;
3997 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3998 SERVICE_QUERY_CONFIG
))
4000 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4001 return ERROR_ACCESS_DENIED
;
4004 lpService
= hSvc
->ServiceEntry
;
4005 if (lpService
== NULL
)
4007 DPRINT1("lpService == NULL!\n");
4008 return ERROR_INVALID_HANDLE
;
4011 /* FIXME: Lock the service database shared */
4013 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4016 if (dwError
!= ERROR_SUCCESS
)
4019 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4021 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4024 dwError
= ScmReadString(hServiceKey
,
4027 if (dwError
!= ERROR_SUCCESS
)
4030 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONA
) + ((wcslen(lpDescriptionW
) + 1));
4032 if (cbBufSize
< dwRequiredSize
)
4034 *pcbBytesNeeded
= dwRequiredSize
;
4035 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4039 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4041 WideCharToMultiByte(CP_ACP
,
4046 wcslen(lpDescriptionW
),
4049 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4051 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4054 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4059 if (lpDescription
!= NULL
)
4060 HeapFree(GetProcessHeap(), 0, lpDescription
);
4062 if (hServiceKey
!= NULL
)
4063 RegCloseKey(hServiceKey
);
4065 /* FIXME: Unlock database */
4067 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4074 DWORD
RQueryServiceConfig2W(
4075 handle_t BindingHandle
,
4076 SC_RPC_HANDLE hService
,
4080 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4082 DWORD dwError
= ERROR_SUCCESS
;
4083 PSERVICE_HANDLE hSvc
;
4084 PSERVICE lpService
= NULL
;
4085 HKEY hServiceKey
= NULL
;
4086 DWORD dwRequiredSize
;
4087 LPWSTR lpDescription
= NULL
;
4089 DPRINT("RQueryServiceConfig2W() called\n");
4092 return ERROR_INVALID_ADDRESS
;
4095 return ERROR_SHUTDOWN_IN_PROGRESS
;
4097 hSvc
= (PSERVICE_HANDLE
)hService
;
4098 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4100 DPRINT1("Invalid handle tag!\n");
4101 return ERROR_INVALID_HANDLE
;
4104 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4105 SERVICE_QUERY_CONFIG
))
4107 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4108 return ERROR_ACCESS_DENIED
;
4111 lpService
= hSvc
->ServiceEntry
;
4112 if (lpService
== NULL
)
4114 DPRINT1("lpService == NULL!\n");
4115 return ERROR_INVALID_HANDLE
;
4118 /* FIXME: Lock the service database shared */
4120 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4123 if (dwError
!= ERROR_SUCCESS
)
4126 if (dwInfoLevel
& SERVICE_CONFIG_DESCRIPTION
)
4128 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4131 dwError
= ScmReadString(hServiceKey
,
4134 if (dwError
!= ERROR_SUCCESS
)
4137 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4139 if (cbBufSize
< dwRequiredSize
)
4141 *pcbBytesNeeded
= dwRequiredSize
;
4142 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4146 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4147 wcscpy(lpStr
, lpDescription
);
4148 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4150 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4153 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4158 if (lpDescription
!= NULL
)
4159 HeapFree(GetProcessHeap(), 0, lpDescription
);
4161 if (hServiceKey
!= NULL
)
4162 RegCloseKey(hServiceKey
);
4164 /* FIXME: Unlock database */
4166 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4173 DWORD
RQueryServiceStatusEx(
4174 handle_t BindingHandle
,
4175 SC_RPC_HANDLE hService
,
4176 SC_STATUS_TYPE InfoLevel
,
4179 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4181 LPSERVICE_STATUS_PROCESS lpStatus
;
4182 PSERVICE_HANDLE hSvc
;
4185 DPRINT("RQueryServiceStatusEx() called\n");
4188 return ERROR_SHUTDOWN_IN_PROGRESS
;
4190 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4191 return ERROR_INVALID_LEVEL
;
4193 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4195 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4196 return ERROR_INSUFFICIENT_BUFFER
;
4198 hSvc
= (PSERVICE_HANDLE
)hService
;
4199 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4201 DPRINT1("Invalid handle tag!\n");
4202 return ERROR_INVALID_HANDLE
;
4205 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4206 SERVICE_QUERY_STATUS
))
4208 DPRINT1("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4209 return ERROR_ACCESS_DENIED
;
4212 lpService
= hSvc
->ServiceEntry
;
4213 if (lpService
== NULL
)
4215 DPRINT1("lpService == NULL!\n");
4216 return ERROR_INVALID_HANDLE
;
4219 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4221 /* Return service status information */
4222 RtlCopyMemory(lpStatus
,
4224 sizeof(SERVICE_STATUS
));
4226 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
4227 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4229 return ERROR_SUCCESS
;
4234 DWORD
REnumServicesStatusExA(
4235 handle_t BindingHandle
,
4236 SC_RPC_HANDLE hSCManager
,
4237 SC_ENUM_TYPE InfoLevel
,
4238 DWORD dwServiceType
,
4239 DWORD dwServiceState
,
4242 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4243 LPBOUNDED_DWORD_256K lpServicesReturned
,
4244 LPBOUNDED_DWORD_256K lpResumeIndex
,
4245 LPCSTR pszGroupName
)
4248 *pcbBytesNeeded
= 0;
4249 *lpServicesReturned
= 0;
4250 return ERROR_CALL_NOT_IMPLEMENTED
;
4255 DWORD
REnumServicesStatusExW(
4256 handle_t BindingHandle
,
4257 SC_RPC_HANDLE hSCManager
,
4258 SC_ENUM_TYPE InfoLevel
,
4259 DWORD dwServiceType
,
4260 DWORD dwServiceState
,
4263 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4264 LPBOUNDED_DWORD_256K lpServicesReturned
,
4265 LPBOUNDED_DWORD_256K lpResumeIndex
,
4266 LPCWSTR pszGroupName
)
4268 PMANAGER_HANDLE hManager
;
4270 DWORD dwError
= ERROR_SUCCESS
;
4271 PLIST_ENTRY ServiceEntry
;
4272 PSERVICE CurrentService
;
4274 DWORD dwRequiredSize
;
4275 DWORD dwServiceCount
;
4277 DWORD dwLastResumeCount
;
4278 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
4281 DPRINT("REnumServicesStatusExW() called\n");
4284 return ERROR_SHUTDOWN_IN_PROGRESS
;
4286 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
4287 return ERROR_INVALID_LEVEL
;
4289 hManager
= (PMANAGER_HANDLE
)hSCManager
;
4290 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
4292 DPRINT1("Invalid manager handle!\n");
4293 return ERROR_INVALID_HANDLE
;
4296 /* Check access rights */
4297 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4298 SC_MANAGER_ENUMERATE_SERVICE
))
4300 DPRINT1("Insufficient access rights! 0x%lx\n",
4301 hManager
->Handle
.DesiredAccess
);
4302 return ERROR_ACCESS_DENIED
;
4305 *pcbBytesNeeded
= 0;
4306 *lpServicesReturned
= 0;
4308 dwLastResumeCount
= *lpResumeIndex
;
4310 /* Lock the service list shared */
4312 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4313 if (lpService
== NULL
)
4315 dwError
= ERROR_SUCCESS
;
4322 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4323 ServiceEntry
!= &ServiceListHead
;
4324 ServiceEntry
= ServiceEntry
->Flink
)
4326 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4330 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4333 dwState
= SERVICE_ACTIVE
;
4334 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4335 dwState
= SERVICE_INACTIVE
;
4337 if ((dwState
& dwServiceState
) == 0)
4342 if (*pszGroupName
== 0)
4344 if (CurrentService
->lpGroup
!= NULL
)
4349 if ((CurrentService
->lpGroup
== NULL
) ||
4350 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4355 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4356 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4357 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4359 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4361 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
4362 dwRequiredSize
+= dwSize
;
4364 dwLastResumeCount
= CurrentService
->dwResumeCount
;
4368 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
4374 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
4375 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
4378 ServiceEntry
!= &ServiceListHead
;
4379 ServiceEntry
= ServiceEntry
->Flink
)
4381 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4385 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4388 dwState
= SERVICE_ACTIVE
;
4389 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4390 dwState
= SERVICE_INACTIVE
;
4392 if ((dwState
& dwServiceState
) == 0)
4397 if (*pszGroupName
== 0)
4399 if (CurrentService
->lpGroup
!= NULL
)
4404 if ((CurrentService
->lpGroup
== NULL
) ||
4405 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4410 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4411 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4412 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
4414 dwError
= ERROR_MORE_DATA
;
4417 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
4419 *lpResumeIndex
= dwLastResumeCount
;
4420 *lpServicesReturned
= dwServiceCount
;
4421 *pcbBytesNeeded
= dwRequiredSize
;
4423 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
4424 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
4425 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4428 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4429 ServiceEntry
!= &ServiceListHead
;
4430 ServiceEntry
= ServiceEntry
->Flink
)
4432 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4436 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4439 dwState
= SERVICE_ACTIVE
;
4440 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4441 dwState
= SERVICE_INACTIVE
;
4443 if ((dwState
& dwServiceState
) == 0)
4448 if (*pszGroupName
== 0)
4450 if (CurrentService
->lpGroup
!= NULL
)
4455 if ((CurrentService
->lpGroup
== NULL
) ||
4456 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4461 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4462 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4463 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4465 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4467 /* Copy the service name */
4469 CurrentService
->lpServiceName
);
4470 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4471 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
4473 /* Copy the display name */
4475 CurrentService
->lpDisplayName
);
4476 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
4477 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
4479 /* Copy the status information */
4480 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
4481 &CurrentService
->Status
,
4482 sizeof(SERVICE_STATUS
));
4483 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
4484 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4487 dwRequiredSize
+= dwSize
;
4497 /* Unlock the service list */
4499 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
4506 DWORD
RSendTSMessage(
4507 handle_t BindingHandle
)
4510 return ERROR_CALL_NOT_IMPLEMENTED
;
4515 DWORD
RCreateServiceWOW64A(
4516 handle_t BindingHandle
,
4517 LPSTR lpServiceName
,
4518 LPSTR lpDisplayName
,
4519 DWORD dwDesiredAccess
,
4520 DWORD dwServiceType
,
4522 DWORD dwErrorControl
,
4523 LPSTR lpBinaryPathName
,
4524 LPSTR lpLoadOrderGroup
,
4526 LPBYTE lpDependencies
,
4528 LPSTR lpServiceStartName
,
4531 LPSC_RPC_HANDLE lpServiceHandle
)
4534 return ERROR_CALL_NOT_IMPLEMENTED
;
4539 DWORD
RCreateServiceWOW64W(
4540 handle_t BindingHandle
,
4541 LPWSTR lpServiceName
,
4542 LPWSTR lpDisplayName
,
4543 DWORD dwDesiredAccess
,
4544 DWORD dwServiceType
,
4546 DWORD dwErrorControl
,
4547 LPWSTR lpBinaryPathName
,
4548 LPWSTR lpLoadOrderGroup
,
4550 LPBYTE lpDependencies
,
4552 LPWSTR lpServiceStartName
,
4555 LPSC_RPC_HANDLE lpServiceHandle
)
4558 return ERROR_CALL_NOT_IMPLEMENTED
;
4563 DWORD
RQueryServiceTagInfo(
4564 handle_t BindingHandle
)
4567 return ERROR_CALL_NOT_IMPLEMENTED
;
4572 DWORD
RNotifyServiceStatusChange(
4573 handle_t BindingHandle
,
4574 SC_RPC_HANDLE hService
,
4575 SC_RPC_NOTIFY_PARAMS NotifyParams
,
4576 GUID
*pClientProcessGuid
,
4577 GUID
*pSCMProcessGuid
,
4578 PBOOL pfCreateRemoteQueue
,
4579 LPSC_NOTIFY_RPC_HANDLE phNotify
)
4582 return ERROR_CALL_NOT_IMPLEMENTED
;
4587 DWORD
RGetNotifyResults(
4588 handle_t BindingHandle
,
4589 SC_NOTIFY_RPC_HANDLE hNotify
,
4590 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
4593 return ERROR_CALL_NOT_IMPLEMENTED
;
4598 DWORD
RCloseNotifyHandle(
4599 handle_t BindingHandle
,
4600 LPSC_NOTIFY_RPC_HANDLE phNotify
,
4604 return ERROR_CALL_NOT_IMPLEMENTED
;
4609 DWORD
RControlServiceExA(
4610 handle_t BindingHandle
,
4611 SC_RPC_HANDLE hService
,
4616 return ERROR_CALL_NOT_IMPLEMENTED
;
4621 DWORD
RControlServiceExW(
4622 handle_t BindingHandle
,
4623 SC_RPC_HANDLE hService
,
4628 return ERROR_CALL_NOT_IMPLEMENTED
;
4633 DWORD
RSendPnPMessage(
4634 handle_t BindingHandle
)
4637 return ERROR_CALL_NOT_IMPLEMENTED
;
4642 DWORD
RValidatePnPService(
4643 handle_t BindingHandle
)
4646 return ERROR_CALL_NOT_IMPLEMENTED
;
4651 DWORD
ROpenServiceStatusHandle(
4652 handle_t BindingHandle
)
4655 return ERROR_CALL_NOT_IMPLEMENTED
;
4661 handle_t BindingHandle
)
4664 return ERROR_CALL_NOT_IMPLEMENTED
;
4668 void __RPC_FAR
* __RPC_USER
midl_user_allocate(size_t len
)
4670 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
4674 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
4676 HeapFree(GetProcessHeap(), 0, ptr
);
4680 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
4685 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
4690 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)