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 DPRINT("Database %S, does not exist\n",lpDatabaseName
);
157 return ERROR_DATABASE_DOES_NOT_EXIST
;
159 else if (_wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
161 DPRINT("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 DPRINT("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 DPRINT("This should not happen at this point, report to Developer\n");
345 return ERROR_NOT_FOUND
;
348 /* Determine state the service is in */
349 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
350 dwCurrentServiceState
= SERVICE_INACTIVE
;
352 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
353 if ((dwCurrentServiceState
== dwServiceState
) ||
354 (dwServiceState
== SERVICE_STATE_ALL
))
356 /* Calculate the required size */
357 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
358 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
359 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
361 /* Add the size for service name and display name pointers */
362 dwRequiredSize
+= (2 * sizeof(PVOID
));
364 /* increase the BytesNeeded size */
365 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
367 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
370 /* Recursive call to check for its dependencies */
371 Int_EnumDependentServicesW(hServicesKey
,
378 /* If the lpServices is valid set the service pointer */
380 lpServices
[*lpServicesReturned
] = lpCurrentService
;
382 *lpServicesReturned
= *lpServicesReturned
+ 1;
386 dwDependServiceStrPtr
+= (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
389 else if (*pcbBytesNeeded
)
391 dwError
= ERROR_SUCCESS
;
394 RegCloseKey(hServiceEnumKey
);
402 DWORD
RCloseServiceHandle(
403 LPSC_RPC_HANDLE hSCObject
)
405 PMANAGER_HANDLE hManager
;
406 PSERVICE_HANDLE hService
;
410 DWORD pcbBytesNeeded
= 0;
411 DWORD dwServicesReturned
= 0;
413 DPRINT("RCloseServiceHandle() called\n");
415 DPRINT("hSCObject = %p\n", *hSCObject
);
418 return ERROR_INVALID_HANDLE
;
420 hManager
= (PMANAGER_HANDLE
)*hSCObject
;
421 hService
= (PSERVICE_HANDLE
)*hSCObject
;
422 if (hManager
->Handle
.Tag
== MANAGER_TAG
)
424 DPRINT("Found manager handle\n");
426 hManager
->Handle
.RefCount
--;
427 if (hManager
->Handle
.RefCount
== 0)
429 /* FIXME: add handle cleanup code */
431 HeapFree(GetProcessHeap(), 0, hManager
);
435 DPRINT("RCloseServiceHandle() done\n");
436 return ERROR_SUCCESS
;
438 else if (hService
->Handle
.Tag
== SERVICE_TAG
)
440 DPRINT("Found service handle\n");
442 /* Get the pointer to the service record */
443 lpService
= hService
->ServiceEntry
;
445 ASSERT(hService
->Handle
.RefCount
> 0);
447 hService
->Handle
.RefCount
--;
448 if (hService
->Handle
.RefCount
== 0)
450 /* FIXME: add handle cleanup code */
452 /* Free the handle */
453 HeapFree(GetProcessHeap(), 0, hService
);
457 ASSERT(lpService
->dwRefCount
> 0);
459 lpService
->dwRefCount
--;
460 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
461 lpService
->dwRefCount
);
463 if (lpService
->dwRefCount
== 0)
465 /* If this service has been marked for deletion */
466 if (lpService
->bDeleted
)
468 /* Open the Services Reg key */
469 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
470 L
"System\\CurrentControlSet\\Services",
472 KEY_SET_VALUE
| KEY_READ
,
474 if (dwError
!= ERROR_SUCCESS
)
476 DPRINT("Failed to open services key\n");
480 /* Call the internal function with NULL, just to get bytes we need */
481 Int_EnumDependentServicesW(hServicesKey
,
486 &dwServicesReturned
);
488 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
491 DPRINT("Deletion failed due to running dependencies.\n");
492 RegCloseKey(hServicesKey
);
493 return ERROR_SUCCESS
;
496 /* There are no references and no runnning dependencies,
497 it is now safe to delete the service */
499 /* Delete the Service Key */
500 dwError
= RegDeleteKeyW(hServicesKey
,
501 lpService
->lpServiceName
);
503 RegCloseKey(hServicesKey
);
505 if (dwError
!= ERROR_SUCCESS
)
507 DPRINT("Failed to Delete the Service Registry key\n");
511 /* Delete the Service */
512 ScmDeleteServiceRecord(lpService
);
516 DPRINT("RCloseServiceHandle() done\n");
517 return ERROR_SUCCESS
;
520 DPRINT("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
522 return ERROR_INVALID_HANDLE
;
527 DWORD
RControlService(
528 SC_RPC_HANDLE hService
,
530 LPSERVICE_STATUS lpServiceStatus
)
532 PSERVICE_HANDLE hSvc
;
534 ACCESS_MASK DesiredAccess
;
535 DWORD dwError
= ERROR_SUCCESS
;
536 DWORD pcbBytesNeeded
= 0;
537 DWORD dwServicesReturned
= 0;
538 HKEY hServicesKey
= NULL
;
540 DPRINT("RControlService() called\n");
543 return ERROR_SHUTDOWN_IN_PROGRESS
;
545 /* Check the service handle */
546 hSvc
= (PSERVICE_HANDLE
)hService
;
547 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
549 DPRINT("Invalid handle tag!\n");
550 return ERROR_INVALID_HANDLE
;
553 /* Check the service entry point */
554 lpService
= hSvc
->ServiceEntry
;
555 if (lpService
== NULL
)
557 DPRINT("lpService == NULL!\n");
558 return ERROR_INVALID_HANDLE
;
561 /* Check access rights */
564 case SERVICE_CONTROL_STOP
:
565 DesiredAccess
= SERVICE_STOP
;
568 case SERVICE_CONTROL_PAUSE
:
569 case SERVICE_CONTROL_CONTINUE
:
570 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
573 case SERVICE_INTERROGATE
:
574 DesiredAccess
= SERVICE_INTERROGATE
;
578 if (dwControl
>= 128 && dwControl
<= 255)
579 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
581 DesiredAccess
= SERVICE_QUERY_CONFIG
|
582 SERVICE_CHANGE_CONFIG
|
583 SERVICE_QUERY_STATUS
|
585 SERVICE_PAUSE_CONTINUE
;
589 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
591 return ERROR_ACCESS_DENIED
;
593 if (dwControl
== SERVICE_CONTROL_STOP
)
595 /* Check if the service has dependencies running as windows
596 doesn't stop a service that does */
598 /* Open the Services Reg key */
599 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
600 L
"System\\CurrentControlSet\\Services",
604 if (dwError
!= ERROR_SUCCESS
)
606 DPRINT("Failed to open services key\n");
610 /* Call the internal function with NULL, just to get bytes we need */
611 Int_EnumDependentServicesW(hServicesKey
,
616 &dwServicesReturned
);
618 RegCloseKey(hServicesKey
);
620 /* If pcbBytesNeeded is not zero then there are services running that
621 are dependent on this service */
622 if (pcbBytesNeeded
!= 0)
624 DPRINT("Service has running dependencies. Failed to stop service.\n");
625 return ERROR_DEPENDENT_SERVICES_RUNNING
;
629 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
631 /* Send control code to the driver */
632 dwError
= ScmControlDriver(lpService
,
638 /* Send control code to the service */
639 dwError
= ScmControlService(lpService
,
642 /* Return service status information */
643 RtlCopyMemory(lpServiceStatus
,
645 sizeof(SERVICE_STATUS
));
648 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
649 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
651 if (dwError
== ERROR_SUCCESS
&&
652 dwControl
== SERVICE_CONTROL_STOP
&&
653 lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
)
655 lpService
->ProcessId
= 0; /* FIXME */
656 lpService
->ThreadId
= 0;
665 DWORD
RDeleteService(
666 SC_RPC_HANDLE hService
)
668 PSERVICE_HANDLE hSvc
;
672 DPRINT("RDeleteService() called\n");
675 return ERROR_SHUTDOWN_IN_PROGRESS
;
677 hSvc
= (PSERVICE_HANDLE
)hService
;
678 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
679 return ERROR_INVALID_HANDLE
;
681 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
683 return ERROR_ACCESS_DENIED
;
685 lpService
= hSvc
->ServiceEntry
;
686 if (lpService
== NULL
)
688 DPRINT("lpService == NULL!\n");
689 return ERROR_INVALID_HANDLE
;
692 /* FIXME: Acquire service database lock exclusively */
694 if (lpService
->bDeleted
)
696 DPRINT("The service has already been marked for delete!\n");
697 return ERROR_SERVICE_MARKED_FOR_DELETE
;
700 /* Mark service for delete */
701 lpService
->bDeleted
= TRUE
;
703 dwError
= ScmMarkServiceForDelete(lpService
);
705 /* FIXME: Release service database lock */
707 DPRINT("RDeleteService() done\n");
714 DWORD
RLockServiceDatabase(
715 SC_RPC_HANDLE hSCManager
,
716 LPSC_RPC_LOCK lpLock
)
718 PMANAGER_HANDLE hMgr
;
720 DPRINT("RLockServiceDatabase() called\n");
724 hMgr
= (PMANAGER_HANDLE
)hSCManager
;
725 if (!hMgr
|| hMgr
->Handle
.Tag
!= MANAGER_TAG
)
726 return ERROR_INVALID_HANDLE
;
728 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
730 return ERROR_ACCESS_DENIED
;
732 // return ScmLockDatabase(0, hMgr->0xC, hLock);
734 /* FIXME: Lock the database */
735 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
737 return ERROR_SUCCESS
;
742 DWORD
RQueryServiceObjectSecurity(
743 SC_RPC_HANDLE hService
,
744 SECURITY_INFORMATION dwSecurityInformation
,
745 LPBYTE lpSecurityDescriptor
,
747 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
749 PSERVICE_HANDLE hSvc
;
751 ULONG DesiredAccess
= 0;
757 SECURITY_DESCRIPTOR ObjectDescriptor
;
759 DPRINT("RQueryServiceObjectSecurity() called\n");
761 hSvc
= (PSERVICE_HANDLE
)hService
;
762 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
764 DPRINT("Invalid handle tag!\n");
765 return ERROR_INVALID_HANDLE
;
768 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
||
769 GROUP_SECURITY_INFORMATION
||
770 OWNER_SECURITY_INFORMATION
))
771 DesiredAccess
|= READ_CONTROL
;
773 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
774 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
776 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
779 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
780 return ERROR_ACCESS_DENIED
;
783 lpService
= hSvc
->ServiceEntry
;
784 if (lpService
== NULL
)
786 DPRINT("lpService == NULL!\n");
787 return ERROR_INVALID_HANDLE
;
790 /* FIXME: Lock the service list */
793 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
795 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
796 dwSecurityInformation
,
797 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
801 /* FIXME: Unlock the service list */
803 if (NT_SUCCESS(Status
))
805 *pcbBytesNeeded
= dwBytesNeeded
;
806 dwError
= STATUS_SUCCESS
;
808 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
810 *pcbBytesNeeded
= dwBytesNeeded
;
811 dwError
= ERROR_INSUFFICIENT_BUFFER
;
813 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
815 dwError
= ERROR_GEN_FAILURE
;
819 dwError
= RtlNtStatusToDosError(Status
);
827 DWORD
RSetServiceObjectSecurity(
828 SC_RPC_HANDLE hService
,
829 DWORD dwSecurityInformation
,
830 LPBYTE lpSecurityDescriptor
,
831 DWORD dwSecuityDescriptorSize
)
833 PSERVICE_HANDLE hSvc
;
835 ULONG DesiredAccess
= 0;
836 /* HANDLE hToken = NULL; */
838 /* NTSTATUS Status; */
841 DPRINT("RSetServiceObjectSecurity() called\n");
843 hSvc
= (PSERVICE_HANDLE
)hService
;
844 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
846 DPRINT("Invalid handle tag!\n");
847 return ERROR_INVALID_HANDLE
;
850 if (dwSecurityInformation
== 0 ||
851 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
852 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
853 return ERROR_INVALID_PARAMETER
;
855 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
856 return ERROR_INVALID_PARAMETER
;
858 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
859 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
861 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
862 DesiredAccess
|= WRITE_DAC
;
864 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
865 DesiredAccess
|= WRITE_OWNER
;
867 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
868 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
869 return ERROR_INVALID_PARAMETER
;
871 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
872 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
873 return ERROR_INVALID_PARAMETER
;
875 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
878 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
879 return ERROR_ACCESS_DENIED
;
882 lpService
= hSvc
->ServiceEntry
;
883 if (lpService
== NULL
)
885 DPRINT("lpService == NULL!\n");
886 return ERROR_INVALID_HANDLE
;
889 if (lpService
->bDeleted
)
890 return ERROR_SERVICE_MARKED_FOR_DELETE
;
893 RpcImpersonateClient(NULL
);
895 Status
= NtOpenThreadToken(NtCurrentThread(),
899 if (!NT_SUCCESS(Status
))
900 return RtlNtStatusToDosError(Status
);
904 /* FIXME: Lock service database */
906 Status
= RtlSetSecurityObject(dwSecurityInformation
,
907 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
908 &lpService
->lpSecurityDescriptor
,
911 if (!NT_SUCCESS(Status
))
913 dwError
= RtlNtStatusToDosError(Status
);
918 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
919 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
921 if (dwError
!= ERROR_SUCCESS
)
925 dwError
= ERROR_SUCCESS
;
926 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
927 // lpService->lpSecurityDescriptor);
929 RegFlushKey(hServiceKey
);
930 RegCloseKey(hServiceKey
);
939 /* FIXME: Unlock service database */
941 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
948 DWORD
RQueryServiceStatus(
949 SC_RPC_HANDLE hService
,
950 LPSERVICE_STATUS lpServiceStatus
)
952 PSERVICE_HANDLE hSvc
;
955 DPRINT("RQueryServiceStatus() called\n");
958 return ERROR_SHUTDOWN_IN_PROGRESS
;
960 hSvc
= (PSERVICE_HANDLE
)hService
;
961 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
963 DPRINT("Invalid handle tag!\n");
964 return ERROR_INVALID_HANDLE
;
967 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
968 SERVICE_QUERY_STATUS
))
970 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
971 return ERROR_ACCESS_DENIED
;
974 lpService
= hSvc
->ServiceEntry
;
975 if (lpService
== NULL
)
977 DPRINT("lpService == NULL!\n");
978 return ERROR_INVALID_HANDLE
;
981 ScmLockDatabaseShared();
983 /* Return service status information */
984 RtlCopyMemory(lpServiceStatus
,
986 sizeof(SERVICE_STATUS
));
990 return ERROR_SUCCESS
;
995 ScmIsValidServiceState(DWORD dwCurrentState
)
997 switch (dwCurrentState
)
999 case SERVICE_STOPPED
:
1000 case SERVICE_START_PENDING
:
1001 case SERVICE_STOP_PENDING
:
1002 case SERVICE_RUNNING
:
1003 case SERVICE_CONTINUE_PENDING
:
1004 case SERVICE_PAUSE_PENDING
:
1005 case SERVICE_PAUSED
:
1015 DWORD
RSetServiceStatus(
1016 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1017 LPSERVICE_STATUS lpServiceStatus
)
1021 DPRINT("RSetServiceStatus() called\n");
1022 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1023 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1024 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1025 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1026 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1027 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1028 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1029 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1031 if (hServiceStatus
== 0)
1033 DPRINT("hServiceStatus == NULL!\n");
1034 return ERROR_INVALID_HANDLE
;
1037 lpService
= (PSERVICE
)hServiceStatus
;
1038 if (lpService
== NULL
)
1040 DPRINT("lpService == NULL!\n");
1041 return ERROR_INVALID_HANDLE
;
1044 /* Check current state */
1045 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1047 DPRINT("Invalid service state!\n");
1048 return ERROR_INVALID_DATA
;
1051 /* Check service type */
1052 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1053 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1055 DPRINT("Invalid service type!\n");
1056 return ERROR_INVALID_DATA
;
1059 /* Check accepted controls */
1060 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1062 DPRINT("Invalid controls accepted!\n");
1063 return ERROR_INVALID_DATA
;
1066 ScmLockDatabaseExclusive();
1068 RtlCopyMemory(&lpService
->Status
,
1070 sizeof(SERVICE_STATUS
));
1072 ScmUnlockDatabase();
1074 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1075 DPRINT("RSetServiceStatus() done\n");
1077 return ERROR_SUCCESS
;
1082 DWORD
RUnlockServiceDatabase(
1086 return ERROR_SUCCESS
;
1091 DWORD
RNotifyBootConfigStatus(
1092 SVCCTL_HANDLEW lpMachineName
,
1093 DWORD BootAcceptable
)
1096 return ERROR_CALL_NOT_IMPLEMENTED
;
1101 DWORD
RI_ScSetServiceBitsW(
1102 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1103 DWORD dwServiceBits
,
1105 int bUpdateImmediately
,
1109 return ERROR_CALL_NOT_IMPLEMENTED
;
1114 DWORD
RChangeServiceConfigW(
1115 SC_RPC_HANDLE hService
,
1116 DWORD dwServiceType
,
1118 DWORD dwErrorControl
,
1119 LPWSTR lpBinaryPathName
,
1120 LPWSTR lpLoadOrderGroup
,
1122 LPBYTE lpDependencies
,
1124 LPWSTR lpServiceStartName
,
1127 LPWSTR lpDisplayName
)
1129 DWORD dwError
= ERROR_SUCCESS
;
1130 PSERVICE_HANDLE hSvc
;
1131 PSERVICE lpService
= NULL
;
1132 HKEY hServiceKey
= NULL
;
1133 LPWSTR lpDisplayNameW
= NULL
;
1135 DPRINT("RChangeServiceConfigW() called\n");
1136 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1137 DPRINT("dwStartType = %lu\n", dwStartType
);
1138 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1139 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1140 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1141 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1144 return ERROR_SHUTDOWN_IN_PROGRESS
;
1146 hSvc
= (PSERVICE_HANDLE
)hService
;
1147 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
1149 DPRINT("Invalid handle tag!\n");
1150 return ERROR_INVALID_HANDLE
;
1153 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1154 SERVICE_CHANGE_CONFIG
))
1156 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1157 return ERROR_ACCESS_DENIED
;
1160 lpService
= hSvc
->ServiceEntry
;
1161 if (lpService
== NULL
)
1163 DPRINT("lpService == NULL!\n");
1164 return ERROR_INVALID_HANDLE
;
1167 /* FIXME: Lock database exclusively */
1169 if (lpService
->bDeleted
)
1171 /* FIXME: Unlock database */
1172 DPRINT("The service has already been marked for delete!\n");
1173 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1176 /* Open the service key */
1177 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1180 if (dwError
!= ERROR_SUCCESS
)
1183 /* Write service data to the registry */
1184 /* Set the display name */
1185 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1187 RegSetValueExW(hServiceKey
,
1191 (LPBYTE
)lpDisplayName
,
1192 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1194 /* Update the display name */
1195 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1197 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1198 if (lpDisplayNameW
== NULL
)
1200 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1204 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1205 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1207 lpService
->lpDisplayName
= lpDisplayNameW
;
1210 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1212 /* Set the service type */
1213 dwError
= RegSetValueExW(hServiceKey
,
1217 (LPBYTE
)&dwServiceType
,
1219 if (dwError
!= ERROR_SUCCESS
)
1222 lpService
->Status
.dwServiceType
= dwServiceType
;
1225 if (dwStartType
!= SERVICE_NO_CHANGE
)
1227 /* Set the start value */
1228 dwError
= RegSetValueExW(hServiceKey
,
1232 (LPBYTE
)&dwStartType
,
1234 if (dwError
!= ERROR_SUCCESS
)
1237 lpService
->dwStartType
= dwStartType
;
1240 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1242 /* Set the error control value */
1243 dwError
= RegSetValueExW(hServiceKey
,
1247 (LPBYTE
)&dwErrorControl
,
1249 if (dwError
!= ERROR_SUCCESS
)
1252 lpService
->dwErrorControl
= dwErrorControl
;
1256 /* FIXME: set the new ImagePath value */
1258 /* Set the image path */
1259 if (dwServiceType
& SERVICE_WIN32
)
1261 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1263 dwError
= RegSetValueExW(hServiceKey
,
1267 (LPBYTE
)lpBinaryPathName
,
1268 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1269 if (dwError
!= ERROR_SUCCESS
)
1273 else if (dwServiceType
& SERVICE_DRIVER
)
1275 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1277 dwError
= RegSetValueExW(hServiceKey
,
1281 (LPBYTE
)lpImagePath
,
1282 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1283 if (dwError
!= ERROR_SUCCESS
)
1289 /* Set the group name */
1290 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1292 dwError
= RegSetValueExW(hServiceKey
,
1296 (LPBYTE
)lpLoadOrderGroup
,
1297 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1298 if (dwError
!= ERROR_SUCCESS
)
1301 dwError
= ScmSetServiceGroup(lpService
,
1303 if (dwError
!= ERROR_SUCCESS
)
1307 if (lpdwTagId
!= NULL
)
1309 dwError
= ScmAssignNewTag(lpService
);
1310 if (dwError
!= ERROR_SUCCESS
)
1313 dwError
= RegSetValueExW(hServiceKey
,
1317 (LPBYTE
)&lpService
->dwTag
,
1319 if (dwError
!= ERROR_SUCCESS
)
1322 *lpdwTagId
= lpService
->dwTag
;
1325 /* Write dependencies */
1326 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1328 dwError
= ScmWriteDependencies(hServiceKey
,
1329 (LPWSTR
)lpDependencies
,
1331 if (dwError
!= ERROR_SUCCESS
)
1335 if (lpPassword
!= NULL
)
1337 /* FIXME: Write password */
1340 /* FIXME: Unlock database */
1343 if (hServiceKey
!= NULL
)
1344 RegCloseKey(hServiceKey
);
1346 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1352 /* Create a path suitable for the bootloader out of the full path */
1354 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1356 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1359 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1360 OBJECT_ATTRIBUTES ObjectAttributes
;
1362 HANDLE SymbolicLinkHandle
;
1364 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1366 ServiceNameLen
= wcslen(CanonName
);
1368 /* First check, if it's already good */
1369 if (ServiceNameLen
> 12 &&
1370 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1372 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1373 if (*RelativeName
== NULL
)
1375 DPRINT("Error allocating memory for boot driver name!\n");
1376 return ERROR_NOT_ENOUGH_MEMORY
;
1380 wcscpy(*RelativeName
, CanonName
);
1382 DPRINT("Bootdriver name %S\n", *RelativeName
);
1383 return ERROR_SUCCESS
;
1386 /* If it has %SystemRoot% prefix, substitute it to \System*/
1387 if (ServiceNameLen
> 13 &&
1388 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1390 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1391 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1393 if (*RelativeName
== NULL
)
1395 DPRINT("Error allocating memory for boot driver name!\n");
1396 return ERROR_NOT_ENOUGH_MEMORY
;
1400 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1401 wcscat(*RelativeName
, CanonName
+ 13);
1403 DPRINT("Bootdriver name %S\n", *RelativeName
);
1404 return ERROR_SUCCESS
;
1407 /* Get buffer size needed for expanding env strings */
1408 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1410 if (BufferSize
<= 1)
1412 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1413 return ERROR_INVALID_ENVIRONMENT
;
1416 /* Allocate memory, since the size is known now */
1417 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1420 DPRINT("Error allocating memory for boot driver name!\n");
1421 return ERROR_NOT_ENOUGH_MEMORY
;
1425 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1428 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1429 LocalFree(Expanded
);
1430 return ERROR_NOT_ENOUGH_MEMORY
;
1433 /* Convert to NY-style path */
1434 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1436 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1437 return ERROR_INVALID_ENVIRONMENT
;
1440 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1442 /* No need to keep the dos-path anymore */
1443 LocalFree(Expanded
);
1445 /* Copy it to the allocated place */
1446 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1449 DPRINT("Error allocating memory for boot driver name!\n");
1450 return ERROR_NOT_ENOUGH_MEMORY
;
1453 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1454 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1455 Expanded
[ExpandedLen
] = 0;
1457 if (ServiceNameLen
> ExpandedLen
&&
1458 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1460 /* Only \SystemRoot\ is missing */
1461 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1462 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1463 if (*RelativeName
== NULL
)
1465 DPRINT("Error allocating memory for boot driver name!\n");
1466 LocalFree(Expanded
);
1467 return ERROR_NOT_ENOUGH_MEMORY
;
1470 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1471 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1473 RtlFreeUnicodeString(&NtPathName
);
1474 return ERROR_SUCCESS
;
1477 /* The most complex case starts here */
1478 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1479 InitializeObjectAttributes(&ObjectAttributes
,
1481 OBJ_CASE_INSENSITIVE
,
1485 /* Open this symlink */
1486 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1488 if (NT_SUCCESS(Status
))
1490 LinkTarget
.Length
= 0;
1491 LinkTarget
.MaximumLength
= 0;
1493 DPRINT("Opened symbolic link object\n");
1495 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1496 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1498 /* Check if required buffer size is sane */
1499 if (BufferSize
> 0xFFFD)
1501 DPRINT("Too large buffer required\n");
1504 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1505 LocalFree(Expanded
);
1506 return ERROR_NOT_ENOUGH_MEMORY
;
1509 /* Alloc the string */
1510 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1511 if (!LinkTarget
.Buffer
)
1513 DPRINT("Unable to alloc buffer\n");
1514 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1515 LocalFree(Expanded
);
1516 return ERROR_NOT_ENOUGH_MEMORY
;
1519 /* Do a real query now */
1520 LinkTarget
.Length
= BufferSize
;
1521 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1523 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1524 if (NT_SUCCESS(Status
))
1526 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1528 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1529 if ((ServiceNameLen
> ExpandedLen
) &&
1530 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1532 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1533 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1535 if (*RelativeName
== NULL
)
1537 DPRINT("Unable to alloc buffer\n");
1538 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1539 LocalFree(Expanded
);
1540 RtlFreeUnicodeString(&NtPathName
);
1541 return ERROR_NOT_ENOUGH_MEMORY
;
1544 /* Copy it over, substituting the first part
1546 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1547 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1550 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1551 LocalFree(Expanded
);
1552 RtlFreeUnicodeString(&NtPathName
);
1554 /* Return success */
1555 return ERROR_SUCCESS
;
1559 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1560 LocalFree(Expanded
);
1561 RtlFreeUnicodeString(&NtPathName
);
1562 return ERROR_INVALID_PARAMETER
;
1567 DPRINT("Error, Status = %08X\n", Status
);
1568 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1569 LocalFree(Expanded
);
1570 RtlFreeUnicodeString(&NtPathName
);
1571 return ERROR_INVALID_PARAMETER
;
1576 DPRINT("Error, Status = %08X\n", Status
);
1577 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1578 LocalFree(Expanded
);
1579 RtlFreeUnicodeString(&NtPathName
);
1580 return ERROR_INVALID_PARAMETER
;
1585 DPRINT("Error, Status = %08X\n", Status
);
1586 LocalFree(Expanded
);
1587 return ERROR_INVALID_PARAMETER
;
1591 *RelativeName
= NULL
;
1592 return ERROR_INVALID_PARAMETER
;
1596 ScmCanonDriverImagePath(DWORD dwStartType
,
1597 const wchar_t *lpServiceName
,
1598 wchar_t **lpCanonName
)
1600 DWORD ServiceNameLen
, Result
;
1601 UNICODE_STRING NtServiceName
;
1602 WCHAR
*RelativeName
;
1603 const WCHAR
*SourceName
= lpServiceName
;
1605 /* Calculate the length of the service's name */
1606 ServiceNameLen
= wcslen(lpServiceName
);
1608 /* 12 is wcslen(L"\\SystemRoot\\") */
1609 if (ServiceNameLen
> 12 &&
1610 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1612 /* SystemRoot prefix is already included */
1614 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1616 if (*lpCanonName
== NULL
)
1618 DPRINT("Error allocating memory for canonized service name!\n");
1619 return ERROR_NOT_ENOUGH_MEMORY
;
1622 /* If it's a boot-time driver, it must be systemroot relative */
1623 if (dwStartType
== SERVICE_BOOT_START
)
1627 wcscpy(*lpCanonName
, SourceName
);
1629 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1633 /* Check if it has %SystemRoot% (len=13) */
1634 if (ServiceNameLen
> 13 &&
1635 !_wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1637 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1638 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1640 if (*lpCanonName
== NULL
)
1642 DPRINT("Error allocating memory for canonized service name!\n");
1643 return ERROR_NOT_ENOUGH_MEMORY
;
1646 /* If it's a boot-time driver, it must be systemroot relative */
1647 if (dwStartType
== SERVICE_BOOT_START
)
1648 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1650 wcscat(*lpCanonName
, lpServiceName
+ 13);
1652 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1656 /* Check if it's a relative path name */
1657 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1659 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1661 if (*lpCanonName
== NULL
)
1663 DPRINT("Error allocating memory for canonized service name!\n");
1664 return ERROR_NOT_ENOUGH_MEMORY
;
1667 /* Just copy it over without changing */
1668 wcscpy(*lpCanonName
, lpServiceName
);
1673 /* It seems to be a DOS path, convert it */
1674 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1676 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
1677 return ERROR_INVALID_PARAMETER
;
1680 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1682 if (*lpCanonName
== NULL
)
1684 DPRINT("Error allocating memory for canonized service name!\n");
1685 RtlFreeUnicodeString(&NtServiceName
);
1686 return ERROR_NOT_ENOUGH_MEMORY
;
1689 /* Copy the string */
1690 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1692 /* The unicode string is not needed anymore */
1693 RtlFreeUnicodeString(&NtServiceName
);
1695 if (dwStartType
!= SERVICE_BOOT_START
)
1697 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1701 /* The service is boot-started, so must be relative */
1702 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1705 /* There is a problem, free name and return */
1706 LocalFree(*lpCanonName
);
1707 DPRINT("Error converting named!\n");
1711 ASSERT(RelativeName
);
1713 /* Copy that string */
1714 wcscpy(*lpCanonName
, RelativeName
+ 12);
1716 /* Free the allocated buffer */
1717 LocalFree(RelativeName
);
1719 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1727 DWORD
RCreateServiceW(
1728 SC_RPC_HANDLE hSCManager
,
1729 LPCWSTR lpServiceName
,
1730 LPCWSTR lpDisplayName
,
1731 DWORD dwDesiredAccess
,
1732 DWORD dwServiceType
,
1734 DWORD dwErrorControl
,
1735 LPCWSTR lpBinaryPathName
,
1736 LPCWSTR lpLoadOrderGroup
,
1738 LPBYTE lpDependencies
,
1740 LPCWSTR lpServiceStartName
,
1743 LPSC_RPC_HANDLE lpServiceHandle
)
1745 PMANAGER_HANDLE hManager
;
1746 DWORD dwError
= ERROR_SUCCESS
;
1747 PSERVICE lpService
= NULL
;
1748 SC_HANDLE hServiceHandle
= NULL
;
1749 LPWSTR lpImagePath
= NULL
;
1750 HKEY hServiceKey
= NULL
;
1751 LPWSTR lpObjectName
;
1753 DPRINT("RCreateServiceW() called\n");
1754 DPRINT("lpServiceName = %S\n", lpServiceName
);
1755 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1756 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1757 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1758 DPRINT("dwStartType = %lu\n", dwStartType
);
1759 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1760 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1761 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1764 return ERROR_SHUTDOWN_IN_PROGRESS
;
1766 hManager
= (PMANAGER_HANDLE
)hSCManager
;
1767 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
1769 DPRINT("Invalid manager handle!\n");
1770 return ERROR_INVALID_HANDLE
;
1773 /* Check access rights */
1774 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1775 SC_MANAGER_CREATE_SERVICE
))
1777 DPRINT("Insufficient access rights! 0x%lx\n",
1778 hManager
->Handle
.DesiredAccess
);
1779 return ERROR_ACCESS_DENIED
;
1782 if (wcslen(lpServiceName
) == 0)
1784 return ERROR_INVALID_NAME
;
1787 if (wcslen(lpBinaryPathName
) == 0)
1789 return ERROR_INVALID_PARAMETER
;
1792 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1793 (lpServiceStartName
))
1795 return ERROR_INVALID_PARAMETER
;
1798 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1799 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1800 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1802 return ERROR_INVALID_PARAMETER
;
1805 if (dwStartType
> SERVICE_DISABLED
)
1807 return ERROR_INVALID_PARAMETER
;
1810 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1813 /* check if it is marked for deletion */
1814 if (lpService
->bDeleted
)
1815 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1816 /* Return Error exist */
1817 return ERROR_SERVICE_EXISTS
;
1820 if (lpDisplayName
!= NULL
&&
1821 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1822 return ERROR_DUPLICATE_SERVICE_NAME
;
1824 if (dwServiceType
& SERVICE_DRIVER
)
1826 dwError
= ScmCanonDriverImagePath(dwStartType
,
1829 if (dwError
!= ERROR_SUCCESS
)
1834 if (dwStartType
== SERVICE_BOOT_START
||
1835 dwStartType
== SERVICE_SYSTEM_START
)
1837 return ERROR_INVALID_PARAMETER
;
1841 /* Allocate a new service entry */
1842 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1844 if (dwError
!= ERROR_SUCCESS
)
1847 /* Fill the new service entry */
1848 lpService
->Status
.dwServiceType
= dwServiceType
;
1849 lpService
->dwStartType
= dwStartType
;
1850 lpService
->dwErrorControl
= dwErrorControl
;
1852 /* Fill the display name */
1853 if (lpDisplayName
!= NULL
&&
1854 *lpDisplayName
!= 0 &&
1855 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1857 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1858 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1859 if (lpService
->lpDisplayName
== NULL
)
1861 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1864 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1867 /* Assign the service to a group */
1868 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1870 dwError
= ScmSetServiceGroup(lpService
,
1872 if (dwError
!= ERROR_SUCCESS
)
1876 /* Assign a new tag */
1877 if (lpdwTagId
!= NULL
)
1879 dwError
= ScmAssignNewTag(lpService
);
1880 if (dwError
!= ERROR_SUCCESS
)
1884 /* Write service data to the registry */
1885 /* Create the service key */
1886 dwError
= ScmCreateServiceKey(lpServiceName
,
1889 if (dwError
!= ERROR_SUCCESS
)
1892 /* Set the display name */
1893 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1895 RegSetValueExW(hServiceKey
,
1899 (LPBYTE
)lpDisplayName
,
1900 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1903 /* Set the service type */
1904 dwError
= RegSetValueExW(hServiceKey
,
1908 (LPBYTE
)&dwServiceType
,
1910 if (dwError
!= ERROR_SUCCESS
)
1913 /* Set the start value */
1914 dwError
= RegSetValueExW(hServiceKey
,
1918 (LPBYTE
)&dwStartType
,
1920 if (dwError
!= ERROR_SUCCESS
)
1923 /* Set the error control value */
1924 dwError
= RegSetValueExW(hServiceKey
,
1928 (LPBYTE
)&dwErrorControl
,
1930 if (dwError
!= ERROR_SUCCESS
)
1933 /* Set the image path */
1934 if (dwServiceType
& SERVICE_WIN32
)
1936 dwError
= RegSetValueExW(hServiceKey
,
1940 (LPBYTE
)lpBinaryPathName
,
1941 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1942 if (dwError
!= ERROR_SUCCESS
)
1945 else if (dwServiceType
& SERVICE_DRIVER
)
1947 dwError
= RegSetValueExW(hServiceKey
,
1951 (LPBYTE
)lpImagePath
,
1952 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
1953 if (dwError
!= ERROR_SUCCESS
)
1957 /* Set the group name */
1958 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1960 dwError
= RegSetValueExW(hServiceKey
,
1964 (LPBYTE
)lpLoadOrderGroup
,
1965 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1966 if (dwError
!= ERROR_SUCCESS
)
1970 if (lpdwTagId
!= NULL
)
1972 dwError
= RegSetValueExW(hServiceKey
,
1976 (LPBYTE
)&lpService
->dwTag
,
1978 if (dwError
!= ERROR_SUCCESS
)
1982 /* Write dependencies */
1983 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1985 dwError
= ScmWriteDependencies(hServiceKey
,
1986 (LPWSTR
)lpDependencies
,
1988 if (dwError
!= ERROR_SUCCESS
)
1992 /* Write service start name */
1993 if (dwServiceType
& SERVICE_WIN32
)
1995 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
1996 dwError
= RegSetValueExW(hServiceKey
,
2000 (LPBYTE
)lpObjectName
,
2001 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
2002 if (dwError
!= ERROR_SUCCESS
)
2006 if (lpPassword
!= NULL
)
2008 /* FIXME: Write password */
2011 dwError
= ScmCreateServiceHandle(lpService
,
2013 if (dwError
!= ERROR_SUCCESS
)
2016 dwError
= ScmCheckAccess(hServiceHandle
,
2018 if (dwError
!= ERROR_SUCCESS
)
2021 lpService
->dwRefCount
= 1;
2022 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2025 if (hServiceKey
!= NULL
)
2026 RegCloseKey(hServiceKey
);
2028 if (dwError
== ERROR_SUCCESS
)
2030 DPRINT("hService %p\n", hServiceHandle
);
2031 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2033 if (lpdwTagId
!= NULL
)
2034 *lpdwTagId
= lpService
->dwTag
;
2038 /* Release the display name buffer */
2039 if (lpService
->lpServiceName
!= NULL
)
2040 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2044 /* Remove the service handle */
2045 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2048 if (lpService
!= NULL
)
2050 /* FIXME: remove the service entry */
2054 if (lpImagePath
!= NULL
)
2055 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2057 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2064 DWORD
REnumDependentServicesW(
2065 SC_RPC_HANDLE hService
,
2066 DWORD dwServiceState
,
2069 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2070 LPBOUNDED_DWORD_256K lpServicesReturned
)
2072 DWORD dwError
= ERROR_SUCCESS
;
2073 DWORD dwServicesReturned
= 0;
2074 DWORD dwServiceCount
;
2075 HKEY hServicesKey
= NULL
;
2076 LPSC_RPC_HANDLE hSCObject
;
2077 PSERVICE_HANDLE hSvc
;
2078 PSERVICE lpService
= NULL
;
2079 PSERVICE
*lpServicesArray
= NULL
;
2080 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2083 *pcbBytesNeeded
= 0;
2084 *lpServicesReturned
= 0;
2086 DPRINT("REnumDependentServicesW() called\n");
2088 hSCObject
= &hService
;
2089 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
2090 lpService
= hSvc
->ServiceEntry
;
2092 /* Check access rights */
2093 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2094 SC_MANAGER_ENUMERATE_SERVICE
))
2096 DPRINT("Insufficient access rights! 0x%lx\n",
2097 hSvc
->Handle
.DesiredAccess
);
2098 return ERROR_ACCESS_DENIED
;
2101 /* Open the Services Reg key */
2102 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2103 L
"System\\CurrentControlSet\\Services",
2107 if (dwError
!= ERROR_SUCCESS
)
2110 /* First determine the bytes needed and get the number of dependent services */
2111 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2116 &dwServicesReturned
);
2117 if (dwError
!= ERROR_SUCCESS
)
2120 /* If buffer size is less than the bytes needed or pointer is null */
2121 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2123 dwError
= ERROR_MORE_DATA
;
2127 /* Allocate memory for array of service pointers */
2128 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2130 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2131 if (!lpServicesArray
)
2133 DPRINT("Could not allocate a buffer!!\n");
2134 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2138 dwServicesReturned
= 0;
2139 *pcbBytesNeeded
= 0;
2141 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2146 &dwServicesReturned
);
2147 if (dwError
!= ERROR_SUCCESS
)
2152 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2153 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2155 /* Copy EnumDepenedentService to Buffer */
2156 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2158 lpService
= lpServicesArray
[dwServiceCount
];
2160 /* Copy status info */
2161 memcpy(&lpServicesPtr
->ServiceStatus
,
2163 sizeof(SERVICE_STATUS
));
2165 /* Copy display name */
2166 wcscpy(lpStr
, lpService
->lpDisplayName
);
2167 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2168 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2170 /* Copy service name */
2171 wcscpy(lpStr
, lpService
->lpServiceName
);
2172 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2173 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2178 *lpServicesReturned
= dwServicesReturned
;
2181 if (lpServicesArray
!= NULL
)
2182 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2184 RegCloseKey(hServicesKey
);
2186 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2193 DWORD
REnumServicesStatusW(
2194 SC_RPC_HANDLE hSCManager
,
2195 DWORD dwServiceType
,
2196 DWORD dwServiceState
,
2199 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2200 LPBOUNDED_DWORD_256K lpServicesReturned
,
2201 LPBOUNDED_DWORD_256K lpResumeHandle
)
2203 PMANAGER_HANDLE hManager
;
2205 DWORD dwError
= ERROR_SUCCESS
;
2206 PLIST_ENTRY ServiceEntry
;
2207 PSERVICE CurrentService
;
2209 DWORD dwRequiredSize
;
2210 DWORD dwServiceCount
;
2212 DWORD dwLastResumeCount
= 0;
2213 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2216 DPRINT("REnumServicesStatusW() called\n");
2219 return ERROR_SHUTDOWN_IN_PROGRESS
;
2221 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2222 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2224 DPRINT("Invalid manager handle!\n");
2225 return ERROR_INVALID_HANDLE
;
2228 *pcbBytesNeeded
= 0;
2229 *lpServicesReturned
= 0;
2231 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2233 DPRINT("Not a valid Service Type!\n");
2234 return ERROR_INVALID_PARAMETER
;
2237 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2239 DPRINT("Not a valid Service State!\n");
2240 return ERROR_INVALID_PARAMETER
;
2243 /* Check access rights */
2244 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2245 SC_MANAGER_ENUMERATE_SERVICE
))
2247 DPRINT("Insufficient access rights! 0x%lx\n",
2248 hManager
->Handle
.DesiredAccess
);
2249 return ERROR_ACCESS_DENIED
;
2253 dwLastResumeCount
= *lpResumeHandle
;
2255 /* FIXME: Lock the service list shared */
2257 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2258 if (lpService
== NULL
)
2260 dwError
= ERROR_SUCCESS
;
2267 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2268 ServiceEntry
!= &ServiceListHead
;
2269 ServiceEntry
= ServiceEntry
->Flink
)
2271 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2275 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2278 dwState
= SERVICE_ACTIVE
;
2279 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2280 dwState
= SERVICE_INACTIVE
;
2282 if ((dwState
& dwServiceState
) == 0)
2285 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2286 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2287 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2289 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2291 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2295 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2296 dwRequiredSize
+= dwSize
;
2298 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2301 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2302 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2305 ServiceEntry
!= &ServiceListHead
;
2306 ServiceEntry
= ServiceEntry
->Flink
)
2308 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2312 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2315 dwState
= SERVICE_ACTIVE
;
2316 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2317 dwState
= SERVICE_INACTIVE
;
2319 if ((dwState
& dwServiceState
) == 0)
2322 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2323 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2324 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2326 dwError
= ERROR_MORE_DATA
;
2329 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2332 *lpResumeHandle
= dwLastResumeCount
;
2334 *lpServicesReturned
= dwServiceCount
;
2335 *pcbBytesNeeded
= dwRequiredSize
;
2337 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2338 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2339 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2342 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2343 ServiceEntry
!= &ServiceListHead
;
2344 ServiceEntry
= ServiceEntry
->Flink
)
2346 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2350 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2353 dwState
= SERVICE_ACTIVE
;
2354 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2355 dwState
= SERVICE_INACTIVE
;
2357 if ((dwState
& dwServiceState
) == 0)
2360 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2361 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2362 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2364 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2367 /* Copy the service name */
2368 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2369 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2370 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2372 /* Copy the display name */
2373 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2374 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2375 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2377 /* Copy the status information */
2378 memcpy(&lpStatusPtr
->ServiceStatus
,
2379 &CurrentService
->Status
,
2380 sizeof(SERVICE_STATUS
));
2383 dwRequiredSize
+= dwSize
;
2388 *pcbBytesNeeded
= 0;
2389 if (lpResumeHandle
) *lpResumeHandle
= 0;
2393 /* FIXME: Unlock the service list */
2395 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2402 DWORD
ROpenSCManagerW(
2403 LPWSTR lpMachineName
,
2404 LPWSTR lpDatabaseName
,
2405 DWORD dwDesiredAccess
,
2406 LPSC_RPC_HANDLE lpScHandle
)
2411 DPRINT("ROpenSCManagerW() called\n");
2412 DPRINT("lpMachineName = %p\n", lpMachineName
);
2413 DPRINT("lpMachineName: %S\n", lpMachineName
);
2414 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2415 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2416 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2419 return ERROR_SHUTDOWN_IN_PROGRESS
;
2422 return ERROR_INVALID_PARAMETER
;
2424 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2426 if (dwError
!= ERROR_SUCCESS
)
2428 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2432 /* Check the desired access */
2433 dwError
= ScmCheckAccess(hHandle
,
2434 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2435 if (dwError
!= ERROR_SUCCESS
)
2437 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2438 HeapFree(GetProcessHeap(), 0, hHandle
);
2442 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2443 DPRINT("*hScm = %p\n", *lpScHandle
);
2445 DPRINT("ROpenSCManagerW() done\n");
2447 return ERROR_SUCCESS
;
2452 DWORD
ROpenServiceW(
2453 SC_RPC_HANDLE hSCManager
,
2454 LPWSTR lpServiceName
,
2455 DWORD dwDesiredAccess
,
2456 LPSC_RPC_HANDLE lpServiceHandle
)
2459 PMANAGER_HANDLE hManager
;
2463 DPRINT("ROpenServiceW() called\n");
2464 DPRINT("hSCManager = %p\n", hSCManager
);
2465 DPRINT("lpServiceName = %p\n", lpServiceName
);
2466 DPRINT("lpServiceName: %S\n", lpServiceName
);
2467 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2470 return ERROR_SHUTDOWN_IN_PROGRESS
;
2472 hManager
= (PMANAGER_HANDLE
)hSCManager
;
2473 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
2475 DPRINT("Invalid manager handle!\n");
2476 return ERROR_INVALID_HANDLE
;
2479 if (!lpServiceHandle
)
2480 return ERROR_INVALID_PARAMETER
;
2483 return ERROR_INVALID_ADDRESS
;
2485 /* FIXME: Lock the service list */
2487 /* Get service database entry */
2488 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2489 if (lpService
== NULL
)
2491 DPRINT("Could not find a service!\n");
2492 return ERROR_SERVICE_DOES_NOT_EXIST
;
2495 /* Create a service handle */
2496 dwError
= ScmCreateServiceHandle(lpService
,
2498 if (dwError
!= ERROR_SUCCESS
)
2500 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2504 /* Check the desired access */
2505 dwError
= ScmCheckAccess(hHandle
,
2507 if (dwError
!= ERROR_SUCCESS
)
2509 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2510 HeapFree(GetProcessHeap(), 0, hHandle
);
2514 lpService
->dwRefCount
++;
2515 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2517 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2518 DPRINT("*hService = %p\n", *lpServiceHandle
);
2520 DPRINT("ROpenServiceW() done\n");
2522 return ERROR_SUCCESS
;
2527 DWORD
RQueryServiceConfigW(
2528 SC_RPC_HANDLE hService
,
2529 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2531 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2533 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2534 DWORD dwError
= ERROR_SUCCESS
;
2535 PSERVICE_HANDLE hSvc
;
2536 PSERVICE lpService
= NULL
;
2537 HKEY hServiceKey
= NULL
;
2538 LPWSTR lpImagePath
= NULL
;
2539 LPWSTR lpServiceStartName
= NULL
;
2540 LPWSTR lpDependencies
= NULL
;
2541 DWORD dwDependenciesLength
= 0;
2542 DWORD dwRequiredSize
;
2543 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2544 WCHAR lpEmptyString
[] = {0,0};
2547 DPRINT("RQueryServiceConfigW() called\n");
2550 return ERROR_SHUTDOWN_IN_PROGRESS
;
2552 hSvc
= (PSERVICE_HANDLE
)hService
;
2553 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2555 DPRINT("Invalid handle tag!\n");
2556 return ERROR_INVALID_HANDLE
;
2559 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2560 SERVICE_QUERY_CONFIG
))
2562 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2563 return ERROR_ACCESS_DENIED
;
2566 lpService
= hSvc
->ServiceEntry
;
2567 if (lpService
== NULL
)
2569 DPRINT("lpService == NULL!\n");
2570 return ERROR_INVALID_HANDLE
;
2573 /* FIXME: Lock the service database shared */
2575 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2578 if (dwError
!= ERROR_SUCCESS
)
2581 /* Read the image path */
2582 dwError
= ScmReadString(hServiceKey
,
2585 if (dwError
!= ERROR_SUCCESS
)
2588 /* Read the service start name */
2589 ScmReadString(hServiceKey
,
2591 &lpServiceStartName
);
2593 /* Read the dependencies */
2594 ScmReadDependencies(hServiceKey
,
2596 &dwDependenciesLength
);
2598 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2600 if (lpImagePath
!= NULL
)
2601 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2603 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2605 if (lpService
->lpGroup
!= NULL
)
2606 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2608 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2610 if (lpDependencies
!= NULL
)
2611 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2613 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2615 if (lpServiceStartName
!= NULL
)
2616 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2618 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2620 if (lpService
->lpDisplayName
!= NULL
)
2621 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2623 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2625 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2627 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2631 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2632 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2633 lpConfig
->dwStartType
= lpService
->dwStartType
;
2634 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2635 lpConfig
->dwTagId
= lpService
->dwTag
;
2637 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2639 /* Append the image path */
2640 if (lpImagePath
!= NULL
)
2642 wcscpy(lpStr
, lpImagePath
);
2646 wcscpy(lpStr
, lpEmptyString
);
2649 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2650 lpStr
+= (wcslen(lpStr
) + 1);
2652 /* Append the group name */
2653 if (lpService
->lpGroup
!= NULL
)
2655 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2659 wcscpy(lpStr
, lpEmptyString
);
2662 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2663 lpStr
+= (wcslen(lpStr
) + 1);
2665 /* Append Dependencies */
2666 if (lpDependencies
!= NULL
)
2670 dwDependenciesLength
* sizeof(WCHAR
));
2674 wcscpy(lpStr
, lpEmptyString
);
2677 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2678 if (lpDependencies
!= NULL
)
2679 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2681 lpStr
+= (wcslen(lpStr
) + 1);
2683 /* Append the service start name */
2684 if (lpServiceStartName
!= NULL
)
2686 wcscpy(lpStr
, lpServiceStartName
);
2690 wcscpy(lpStr
, lpEmptyString
);
2693 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2694 lpStr
+= (wcslen(lpStr
) + 1);
2696 /* Append the display name */
2697 if (lpService
->lpDisplayName
!= NULL
)
2699 wcscpy(lpStr
, lpService
->lpDisplayName
);
2703 wcscpy(lpStr
, lpEmptyString
);
2706 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2709 if (pcbBytesNeeded
!= NULL
)
2710 *pcbBytesNeeded
= dwRequiredSize
;
2713 if (lpImagePath
!= NULL
)
2714 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2716 if (lpServiceStartName
!= NULL
)
2717 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2719 if (lpDependencies
!= NULL
)
2720 HeapFree(GetProcessHeap(), 0, lpDependencies
);
2722 if (hServiceKey
!= NULL
)
2723 RegCloseKey(hServiceKey
);
2725 /* FIXME: Unlock the service database */
2727 DPRINT("RQueryServiceConfigW() done\n");
2734 DWORD
RQueryServiceLockStatusW(
2735 SC_RPC_HANDLE hSCManager
,
2736 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2738 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2741 return ERROR_CALL_NOT_IMPLEMENTED
;
2746 DWORD
RStartServiceW(
2747 SC_RPC_HANDLE hService
,
2749 LPSTRING_PTRSW argv
)
2751 DWORD dwError
= ERROR_SUCCESS
;
2752 PSERVICE_HANDLE hSvc
;
2753 PSERVICE lpService
= NULL
;
2755 DPRINT("RStartServiceW() called\n");
2758 return ERROR_SHUTDOWN_IN_PROGRESS
;
2760 hSvc
= (PSERVICE_HANDLE
)hService
;
2761 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2763 DPRINT("Invalid handle tag!\n");
2764 return ERROR_INVALID_HANDLE
;
2767 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2770 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2771 return ERROR_ACCESS_DENIED
;
2774 lpService
= hSvc
->ServiceEntry
;
2775 if (lpService
== NULL
)
2777 DPRINT("lpService == NULL!\n");
2778 return ERROR_INVALID_HANDLE
;
2781 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2782 return ERROR_SERVICE_DISABLED
;
2784 if (lpService
->bDeleted
)
2785 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2792 /* Start the service */
2793 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2800 DWORD
RGetServiceDisplayNameW(
2801 SC_RPC_HANDLE hSCManager
,
2802 LPCWSTR lpServiceName
,
2803 LPWSTR lpDisplayName
,
2806 // PMANAGER_HANDLE hManager;
2811 DPRINT("RGetServiceDisplayNameW() called\n");
2812 DPRINT("hSCManager = %p\n", hSCManager
);
2813 DPRINT("lpServiceName: %S\n", lpServiceName
);
2814 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
2815 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2817 // hManager = (PMANAGER_HANDLE)hSCManager;
2818 // if (hManager->Handle.Tag != MANAGER_TAG)
2820 // DPRINT("Invalid manager handle!\n");
2821 // return ERROR_INVALID_HANDLE;
2824 /* Get service database entry */
2825 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2826 if (lpService
== NULL
)
2828 DPRINT("Could not find a service!\n");
2830 /* If the service could not be found and lpcchBuffer is less than 2, windows
2831 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2832 if (*lpcchBuffer
< 2)
2835 if (lpDisplayName
!= NULL
)
2837 *lpDisplayName
= '\0';
2841 return ERROR_SERVICE_DOES_NOT_EXIST
;
2844 if (!lpService
->lpDisplayName
)
2846 dwLength
= wcslen(lpService
->lpServiceName
);
2848 if (lpDisplayName
!= NULL
&&
2849 *lpcchBuffer
> dwLength
)
2851 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2856 dwLength
= wcslen(lpService
->lpDisplayName
);
2858 if (lpDisplayName
!= NULL
&&
2859 *lpcchBuffer
> dwLength
)
2861 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2865 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2867 *lpcchBuffer
= dwLength
;
2874 DWORD
RGetServiceKeyNameW(
2875 SC_RPC_HANDLE hSCManager
,
2876 LPCWSTR lpDisplayName
,
2877 LPWSTR lpServiceName
,
2880 // PMANAGER_HANDLE hManager;
2885 DPRINT("RGetServiceKeyNameW() called\n");
2886 DPRINT("hSCManager = %p\n", hSCManager
);
2887 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2888 DPRINT("lpServiceName: %p\n", lpServiceName
);
2889 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2891 // hManager = (PMANAGER_HANDLE)hSCManager;
2892 // if (hManager->Handle.Tag != MANAGER_TAG)
2894 // DPRINT("Invalid manager handle!\n");
2895 // return ERROR_INVALID_HANDLE;
2898 /* Get service database entry */
2899 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2900 if (lpService
== NULL
)
2902 DPRINT("Could not find a service!\n");
2904 /* If the service could not be found and lpcchBuffer is less than 2, windows
2905 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2906 if (*lpcchBuffer
< 2)
2909 if (lpServiceName
!= NULL
)
2911 *lpServiceName
= '\0';
2915 return ERROR_SERVICE_DOES_NOT_EXIST
;
2918 dwLength
= wcslen(lpService
->lpServiceName
);
2920 if (lpServiceName
!= NULL
&&
2921 *lpcchBuffer
> dwLength
)
2923 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2924 *lpcchBuffer
= dwLength
;
2925 return ERROR_SUCCESS
;
2928 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2930 *lpcchBuffer
= dwLength
;
2937 DWORD
RI_ScSetServiceBitsA(
2938 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
2939 DWORD dwServiceBits
,
2941 int bUpdateImmediately
,
2945 return ERROR_CALL_NOT_IMPLEMENTED
;
2950 DWORD
RChangeServiceConfigA(
2951 SC_RPC_HANDLE hService
,
2952 DWORD dwServiceType
,
2954 DWORD dwErrorControl
,
2955 LPSTR lpBinaryPathName
,
2956 LPSTR lpLoadOrderGroup
,
2958 LPSTR lpDependencies
,
2960 LPSTR lpServiceStartName
,
2963 LPSTR lpDisplayName
)
2965 DWORD dwError
= ERROR_SUCCESS
;
2966 PSERVICE_HANDLE hSvc
;
2967 PSERVICE lpService
= NULL
;
2968 HKEY hServiceKey
= NULL
;
2969 LPWSTR lpDisplayNameW
= NULL
;
2970 // LPWSTR lpBinaryPathNameW = NULL;
2971 LPWSTR lpLoadOrderGroupW
= NULL
;
2972 LPWSTR lpDependenciesW
= NULL
;
2973 // LPWSTR lpPasswordW = NULL;
2975 DPRINT("RChangeServiceConfigA() called\n");
2976 DPRINT("dwServiceType = %lu\n", dwServiceType
);
2977 DPRINT("dwStartType = %lu\n", dwStartType
);
2978 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
2979 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
2980 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
2981 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
2984 return ERROR_SHUTDOWN_IN_PROGRESS
;
2986 hSvc
= (PSERVICE_HANDLE
)hService
;
2987 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
2989 DPRINT("Invalid handle tag!\n");
2990 return ERROR_INVALID_HANDLE
;
2993 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2994 SERVICE_CHANGE_CONFIG
))
2996 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2997 return ERROR_ACCESS_DENIED
;
3000 lpService
= hSvc
->ServiceEntry
;
3001 if (lpService
== NULL
)
3003 DPRINT("lpService == NULL!\n");
3004 return ERROR_INVALID_HANDLE
;
3007 /* FIXME: Lock database exclusively */
3009 if (lpService
->bDeleted
)
3011 /* FIXME: Unlock database */
3012 DPRINT("The service has already been marked for delete!\n");
3013 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3016 /* Open the service key */
3017 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3020 if (dwError
!= ERROR_SUCCESS
)
3023 /* Write service data to the registry */
3025 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3027 /* Set the display name */
3028 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3030 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3031 if (lpDisplayNameW
== NULL
)
3033 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3037 MultiByteToWideChar(CP_ACP
,
3042 strlen(lpDisplayName
) + 1);
3044 RegSetValueExW(hServiceKey
,
3048 (LPBYTE
)lpDisplayNameW
,
3049 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3051 /* Update lpService->lpDisplayName */
3052 if (lpService
->lpDisplayName
)
3053 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3055 lpService
->lpDisplayName
= lpDisplayNameW
;
3058 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3060 /* Set the service type */
3061 dwError
= RegSetValueExW(hServiceKey
,
3065 (LPBYTE
)&dwServiceType
,
3067 if (dwError
!= ERROR_SUCCESS
)
3070 lpService
->Status
.dwServiceType
= dwServiceType
;
3073 if (dwStartType
!= SERVICE_NO_CHANGE
)
3075 /* Set the start value */
3076 dwError
= RegSetValueExW(hServiceKey
,
3080 (LPBYTE
)&dwStartType
,
3082 if (dwError
!= ERROR_SUCCESS
)
3085 lpService
->dwStartType
= dwStartType
;
3088 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3090 /* Set the error control value */
3091 dwError
= RegSetValueExW(hServiceKey
,
3095 (LPBYTE
)&dwErrorControl
,
3097 if (dwError
!= ERROR_SUCCESS
)
3100 lpService
->dwErrorControl
= dwErrorControl
;
3104 /* FIXME: set the new ImagePath value */
3106 /* Set the image path */
3107 if (dwServiceType
& SERVICE_WIN32
)
3109 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3111 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3112 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, strlen(lpBinaryPathName
)+1);
3113 dwError
= RegSetValueExW(hServiceKey
,
3117 (LPBYTE
)lpBinaryPathNameW
,
3118 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3119 if (dwError
!= ERROR_SUCCESS
)
3123 else if (dwServiceType
& SERVICE_DRIVER
)
3125 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3127 dwError
= RegSetValueExW(hServiceKey
,
3131 (LPBYTE
)lpImagePath
,
3132 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3133 if (dwError
!= ERROR_SUCCESS
)
3139 /* Set the group name */
3140 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3142 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3144 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3145 if (lpLoadOrderGroupW
== NULL
)
3147 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3151 MultiByteToWideChar(CP_ACP
,
3156 strlen(lpLoadOrderGroup
) + 1);
3158 dwError
= RegSetValueExW(hServiceKey
,
3162 (LPBYTE
)lpLoadOrderGroupW
,
3163 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3164 if (dwError
!= ERROR_SUCCESS
)
3166 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3170 dwError
= ScmSetServiceGroup(lpService
,
3173 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3175 if (dwError
!= ERROR_SUCCESS
)
3179 if (lpdwTagId
!= NULL
)
3181 dwError
= ScmAssignNewTag(lpService
);
3182 if (dwError
!= ERROR_SUCCESS
)
3185 dwError
= RegSetValueExW(hServiceKey
,
3189 (LPBYTE
)&lpService
->dwTag
,
3191 if (dwError
!= ERROR_SUCCESS
)
3194 *lpdwTagId
= lpService
->dwTag
;
3197 /* Write dependencies */
3198 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3200 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3202 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3203 if (lpDependenciesW
== NULL
)
3205 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3209 MultiByteToWideChar(CP_ACP
,
3214 strlen(lpDependencies
) + 1);
3216 dwError
= ScmWriteDependencies(hServiceKey
,
3217 (LPWSTR
)lpDependenciesW
,
3220 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3223 if (lpPassword
!= NULL
)
3225 /* FIXME: Write password */
3228 /* FIXME: Unlock database */
3231 if (hServiceKey
!= NULL
)
3232 RegCloseKey(hServiceKey
);
3234 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3241 DWORD
RCreateServiceA(
3242 SC_RPC_HANDLE hSCManager
,
3243 LPSTR lpServiceName
,
3244 LPSTR lpDisplayName
,
3245 DWORD dwDesiredAccess
,
3246 DWORD dwServiceType
,
3248 DWORD dwErrorControl
,
3249 LPSTR lpBinaryPathName
,
3250 LPSTR lpLoadOrderGroup
,
3252 LPBYTE lpDependencies
,
3254 LPSTR lpServiceStartName
,
3257 LPSC_RPC_HANDLE lpServiceHandle
)
3259 DWORD dwError
= ERROR_SUCCESS
;
3260 LPWSTR lpServiceNameW
= NULL
;
3261 LPWSTR lpDisplayNameW
= NULL
;
3262 LPWSTR lpBinaryPathNameW
= NULL
;
3263 LPWSTR lpLoadOrderGroupW
= NULL
;
3264 LPWSTR lpDependenciesW
= NULL
;
3265 LPWSTR lpServiceStartNameW
= NULL
;
3266 DWORD dwDependenciesLength
= 0;
3273 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3274 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3275 if (!lpServiceNameW
)
3277 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3280 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3285 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3286 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3287 if (!lpDisplayNameW
)
3289 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3292 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3295 if (lpBinaryPathName
)
3297 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3298 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3299 if (!lpBinaryPathNameW
)
3301 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3304 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3307 if (lpLoadOrderGroup
)
3309 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3310 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3311 if (!lpLoadOrderGroupW
)
3313 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3316 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3321 lpStr
= (LPSTR
)lpDependencies
;
3324 dwLength
= strlen(lpStr
) + 1;
3325 dwDependenciesLength
+= dwLength
;
3326 lpStr
= lpStr
+ dwLength
;
3328 dwDependenciesLength
++;
3330 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3331 if (!lpDependenciesW
)
3333 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3336 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3339 if (lpServiceStartName
)
3341 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3342 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3343 if (!lpServiceStartNameW
)
3345 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3348 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3351 dwError
= RCreateServiceW(hSCManager
,
3361 (LPBYTE
)lpDependenciesW
,
3362 dwDependenciesLength
,
3363 lpServiceStartNameW
,
3369 if (lpServiceNameW
!=NULL
)
3370 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3372 if (lpDisplayNameW
!= NULL
)
3373 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3375 if (lpBinaryPathNameW
!= NULL
)
3376 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3378 if (lpLoadOrderGroupW
!= NULL
)
3379 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3381 if (lpDependenciesW
!= NULL
)
3382 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3384 if (lpServiceStartNameW
!= NULL
)
3385 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3392 DWORD
REnumDependentServicesA(
3393 SC_RPC_HANDLE hService
,
3394 DWORD dwServiceState
,
3397 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3398 LPBOUNDED_DWORD_256K lpServicesReturned
)
3400 DWORD dwError
= ERROR_SUCCESS
;
3401 DWORD dwServicesReturned
= 0;
3402 DWORD dwServiceCount
;
3403 HKEY hServicesKey
= NULL
;
3404 LPSC_RPC_HANDLE hSCObject
;
3405 PSERVICE_HANDLE hSvc
;
3406 PSERVICE lpService
= NULL
;
3407 PSERVICE
*lpServicesArray
= NULL
;
3408 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3411 *pcbBytesNeeded
= 0;
3412 *lpServicesReturned
= 0;
3414 DPRINT("REnumDependentServicesA() called\n");
3416 hSCObject
= &hService
;
3417 hSvc
= (PSERVICE_HANDLE
) *hSCObject
;
3418 lpService
= hSvc
->ServiceEntry
;
3420 /* Check access rights */
3421 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3422 SC_MANAGER_ENUMERATE_SERVICE
))
3424 DPRINT("Insufficient access rights! 0x%lx\n",
3425 hSvc
->Handle
.DesiredAccess
);
3426 return ERROR_ACCESS_DENIED
;
3429 /* Open the Services Reg key */
3430 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3431 L
"System\\CurrentControlSet\\Services",
3436 if (dwError
!= ERROR_SUCCESS
)
3439 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3440 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3441 are the same for both. Verified in WINXP. */
3443 /* First determine the bytes needed and get the number of dependent services*/
3444 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3449 &dwServicesReturned
);
3450 if (dwError
!= ERROR_SUCCESS
)
3453 /* If buffer size is less than the bytes needed or pointer is null*/
3454 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3456 dwError
= ERROR_MORE_DATA
;
3460 /* Allocate memory for array of service pointers */
3461 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3463 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3464 if (!lpServicesArray
)
3466 DPRINT("Could not allocate a buffer!!\n");
3467 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3471 dwServicesReturned
= 0;
3472 *pcbBytesNeeded
= 0;
3474 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3479 &dwServicesReturned
);
3480 if (dwError
!= ERROR_SUCCESS
)
3485 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3486 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3488 /* Copy EnumDepenedentService to Buffer */
3489 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3491 lpService
= lpServicesArray
[dwServiceCount
];
3493 /* Copy the status info */
3494 memcpy(&lpServicesPtr
->ServiceStatus
,
3496 sizeof(SERVICE_STATUS
));
3498 /* Copy display name */
3499 WideCharToMultiByte(CP_ACP
,
3501 lpService
->lpDisplayName
,
3504 wcslen(lpService
->lpDisplayName
),
3507 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3508 lpStr
+= strlen(lpStr
) + 1;
3510 /* Copy service name */
3511 WideCharToMultiByte(CP_ACP
,
3513 lpService
->lpServiceName
,
3516 wcslen(lpService
->lpServiceName
),
3519 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3520 lpStr
+= strlen(lpStr
) + 1;
3525 *lpServicesReturned
= dwServicesReturned
;
3528 if (lpServicesArray
)
3529 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3531 RegCloseKey(hServicesKey
);
3533 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3540 DWORD
REnumServicesStatusA(
3541 SC_RPC_HANDLE hSCManager
,
3542 DWORD dwServiceType
,
3543 DWORD dwServiceState
,
3546 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3547 LPBOUNDED_DWORD_256K lpServicesReturned
,
3548 LPBOUNDED_DWORD_256K lpResumeHandle
)
3550 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3551 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3552 LPWSTR lpStringPtrW
;
3555 DWORD dwServiceCount
;
3557 DPRINT("REnumServicesStatusA() called\n");
3559 if ((dwBufSize
> 0) && (lpBuffer
))
3561 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3564 DPRINT("Failed to allocate buffer!\n");
3565 return ERROR_NOT_ENOUGH_MEMORY
;
3569 dwError
= REnumServicesStatusW(hSCManager
,
3572 (LPBYTE
)lpStatusPtrW
,
3578 /* if no services were returned then we are Done */
3579 if (*lpServicesReturned
== 0)
3582 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3583 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3584 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3585 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3586 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3588 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3590 /* Copy the service name */
3591 WideCharToMultiByte(CP_ACP
,
3596 wcslen(lpStringPtrW
),
3600 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3601 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3602 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3604 /* Copy the display name */
3605 WideCharToMultiByte(CP_ACP
,
3610 wcslen(lpStringPtrW
),
3614 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3615 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3616 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3618 /* Copy the status information */
3619 memcpy(&lpStatusPtrA
->ServiceStatus
,
3620 &lpStatusPtrW
->ServiceStatus
,
3621 sizeof(SERVICE_STATUS
));
3628 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3630 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3637 DWORD
ROpenSCManagerA(
3638 LPSTR lpMachineName
,
3639 LPSTR lpDatabaseName
,
3640 DWORD dwDesiredAccess
,
3641 LPSC_RPC_HANDLE lpScHandle
)
3643 UNICODE_STRING MachineName
;
3644 UNICODE_STRING DatabaseName
;
3647 DPRINT("ROpenSCManagerA() called\n");
3650 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3654 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3657 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3658 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3663 RtlFreeUnicodeString(&MachineName
);
3666 RtlFreeUnicodeString(&DatabaseName
);
3673 DWORD
ROpenServiceA(
3674 SC_RPC_HANDLE hSCManager
,
3675 LPSTR lpServiceName
,
3676 DWORD dwDesiredAccess
,
3677 LPSC_RPC_HANDLE lpServiceHandle
)
3679 UNICODE_STRING ServiceName
;
3682 DPRINT("ROpenServiceA() called\n");
3685 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3688 dwError
= ROpenServiceW(hSCManager
,
3689 lpServiceName
? ServiceName
.Buffer
: NULL
,
3694 RtlFreeUnicodeString(&ServiceName
);
3701 DWORD
RQueryServiceConfigA(
3702 SC_RPC_HANDLE hService
,
3703 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3705 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3707 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3708 DWORD dwError
= ERROR_SUCCESS
;
3709 PSERVICE_HANDLE hSvc
;
3710 PSERVICE lpService
= NULL
;
3711 HKEY hServiceKey
= NULL
;
3712 LPWSTR lpImagePath
= NULL
;
3713 LPWSTR lpServiceStartName
= NULL
;
3714 LPWSTR lpDependencies
= NULL
;
3715 DWORD dwDependenciesLength
= 0;
3716 DWORD dwRequiredSize
;
3717 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3718 CHAR lpEmptyString
[]={0,0};
3721 DPRINT("RQueryServiceConfigA() called\n");
3724 return ERROR_SHUTDOWN_IN_PROGRESS
;
3726 hSvc
= (PSERVICE_HANDLE
)hService
;
3727 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3729 DPRINT("Invalid handle tag!\n");
3730 return ERROR_INVALID_HANDLE
;
3733 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3734 SERVICE_QUERY_CONFIG
))
3736 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3737 return ERROR_ACCESS_DENIED
;
3740 lpService
= hSvc
->ServiceEntry
;
3741 if (lpService
== NULL
)
3743 DPRINT("lpService == NULL!\n");
3744 return ERROR_INVALID_HANDLE
;
3747 /* FIXME: Lock the service database shared */
3749 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3752 if (dwError
!= ERROR_SUCCESS
)
3755 /* Read the image path */
3756 dwError
= ScmReadString(hServiceKey
,
3759 if (dwError
!= ERROR_SUCCESS
)
3762 /* Read the service start name */
3763 ScmReadString(hServiceKey
,
3765 &lpServiceStartName
);
3767 /* Read the dependencies */
3768 ScmReadDependencies(hServiceKey
,
3770 &dwDependenciesLength
);
3772 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3774 if (lpImagePath
!= NULL
)
3775 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3777 dwRequiredSize
+= 2;
3779 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3780 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3782 dwRequiredSize
+= 2;
3784 /* Add Dependencies length */
3785 if (lpDependencies
!= NULL
)
3786 dwRequiredSize
+= dwDependenciesLength
;
3788 dwRequiredSize
+= 2;
3790 if (lpServiceStartName
!= NULL
)
3791 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3793 dwRequiredSize
+= 2;
3795 if (lpService
->lpDisplayName
!= NULL
)
3796 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3798 dwRequiredSize
+= 2;
3800 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3802 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3806 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3807 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3808 lpConfig
->dwStartType
= lpService
->dwStartType
;
3809 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3810 lpConfig
->dwTagId
= lpService
->dwTag
;
3812 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3814 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3819 WideCharToMultiByte(CP_ACP
,
3824 wcslen(lpImagePath
) + 1,
3830 strcpy(lpStr
, lpEmptyString
);
3833 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3834 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3836 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
3838 WideCharToMultiByte(CP_ACP
,
3840 lpService
->lpGroup
->lpGroupName
,
3843 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
3849 strcpy(lpStr
, lpEmptyString
);
3852 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3853 lpStr
+= (strlen(lpStr
) + 1);
3855 /* Append Dependencies */
3858 WideCharToMultiByte(CP_ACP
,
3861 dwDependenciesLength
,
3863 dwDependenciesLength
,
3869 strcpy(lpStr
, lpEmptyString
);
3872 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3874 lpStr
+= dwDependenciesLength
;
3876 lpStr
+= (strlen(lpStr
) + 1);
3878 if (lpServiceStartName
)
3880 WideCharToMultiByte(CP_ACP
,
3885 wcslen(lpServiceStartName
) + 1,
3891 strcpy(lpStr
, lpEmptyString
);
3894 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3895 lpStr
+= (strlen(lpStr
) + 1);
3897 if (lpService
->lpDisplayName
)
3899 WideCharToMultiByte(CP_ACP
,
3901 lpService
->lpDisplayName
,
3904 wcslen(lpService
->lpDisplayName
) + 1,
3910 strcpy(lpStr
, lpEmptyString
);
3913 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3916 if (pcbBytesNeeded
!= NULL
)
3917 *pcbBytesNeeded
= dwRequiredSize
;
3920 if (lpImagePath
!= NULL
)
3921 HeapFree(GetProcessHeap(), 0, lpImagePath
);
3923 if (lpServiceStartName
!= NULL
)
3924 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
3926 if (lpDependencies
!= NULL
)
3927 HeapFree(GetProcessHeap(), 0, lpDependencies
);
3929 if (hServiceKey
!= NULL
)
3930 RegCloseKey(hServiceKey
);
3932 /* FIXME: Unlock the service database */
3934 DPRINT("RQueryServiceConfigA() done\n");
3941 DWORD
RQueryServiceLockStatusA(
3942 SC_RPC_HANDLE hSCManager
,
3943 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
3945 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
3948 return ERROR_CALL_NOT_IMPLEMENTED
;
3953 DWORD
RStartServiceA(
3954 SC_RPC_HANDLE hService
,
3956 LPSTRING_PTRSA argv
)
3958 DWORD dwError
= ERROR_SUCCESS
;
3959 PSERVICE_HANDLE hSvc
;
3960 PSERVICE lpService
= NULL
;
3962 DPRINT("RStartServiceA() called\n");
3965 return ERROR_SHUTDOWN_IN_PROGRESS
;
3967 hSvc
= (PSERVICE_HANDLE
)hService
;
3968 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
3970 DPRINT("Invalid handle tag!\n");
3971 return ERROR_INVALID_HANDLE
;
3974 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3977 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3978 return ERROR_ACCESS_DENIED
;
3981 lpService
= hSvc
->ServiceEntry
;
3982 if (lpService
== NULL
)
3984 DPRINT("lpService == NULL!\n");
3985 return ERROR_INVALID_HANDLE
;
3988 if (lpService
->dwStartType
== SERVICE_DISABLED
)
3989 return ERROR_SERVICE_DISABLED
;
3991 if (lpService
->bDeleted
)
3992 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3994 /* FIXME: Convert argument vector to Unicode */
3996 /* Start the service */
3997 dwError
= ScmStartService(lpService
, 0, NULL
);
3999 /* FIXME: Free argument vector */
4006 DWORD
RGetServiceDisplayNameA(
4007 SC_RPC_HANDLE hSCManager
,
4008 LPCSTR lpServiceName
,
4009 LPSTR lpDisplayName
,
4010 LPBOUNDED_DWORD_4K lpcchBuffer
)
4012 // PMANAGER_HANDLE hManager;
4013 PSERVICE lpService
= NULL
;
4016 LPWSTR lpServiceNameW
;
4018 DPRINT("RGetServiceDisplayNameA() called\n");
4019 DPRINT("hSCManager = %p\n", hSCManager
);
4020 DPRINT("lpServiceName: %s\n", lpServiceName
);
4021 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4022 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4024 // hManager = (PMANAGER_HANDLE)hSCManager;
4025 // if (hManager->Handle.Tag != MANAGER_TAG)
4027 // DPRINT("Invalid manager handle!\n");
4028 // return ERROR_INVALID_HANDLE;
4031 if (lpServiceName
!= NULL
)
4033 dwLength
= strlen(lpServiceName
) + 1;
4034 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4036 dwLength
* sizeof(WCHAR
));
4037 if (!lpServiceNameW
)
4038 return ERROR_NOT_ENOUGH_MEMORY
;
4040 MultiByteToWideChar(CP_ACP
,
4047 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4049 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4052 if (lpService
== NULL
)
4054 DPRINT("Could not find a service!\n");
4056 /* If the service could not be found and lpcchBuffer is 0, windows
4057 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4058 if (*lpcchBuffer
== 0)
4061 if (lpDisplayName
!= NULL
)
4063 *lpDisplayName
= '\0';
4066 return ERROR_SERVICE_DOES_NOT_EXIST
;
4069 if (!lpService
->lpDisplayName
)
4071 dwLength
= wcslen(lpService
->lpServiceName
);
4072 if (lpDisplayName
!= NULL
&&
4073 *lpcchBuffer
> dwLength
)
4075 WideCharToMultiByte(CP_ACP
,
4077 lpService
->lpServiceName
,
4078 wcslen(lpService
->lpServiceName
),
4083 return ERROR_SUCCESS
;
4088 dwLength
= wcslen(lpService
->lpDisplayName
);
4089 if (lpDisplayName
!= NULL
&&
4090 *lpcchBuffer
> dwLength
)
4092 WideCharToMultiByte(CP_ACP
,
4094 lpService
->lpDisplayName
,
4095 wcslen(lpService
->lpDisplayName
),
4100 return ERROR_SUCCESS
;
4104 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4106 *lpcchBuffer
= dwLength
* 2;
4113 DWORD
RGetServiceKeyNameA(
4114 SC_RPC_HANDLE hSCManager
,
4115 LPCSTR lpDisplayName
,
4116 LPSTR lpServiceName
,
4117 LPBOUNDED_DWORD_4K lpcchBuffer
)
4122 LPWSTR lpDisplayNameW
;
4124 DPRINT("RGetServiceKeyNameA() called\n");
4125 DPRINT("hSCManager = %p\n", hSCManager
);
4126 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4127 DPRINT("lpServiceName: %p\n", lpServiceName
);
4128 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4130 dwLength
= strlen(lpDisplayName
) + 1;
4131 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4133 dwLength
* sizeof(WCHAR
));
4134 if (!lpDisplayNameW
)
4135 return ERROR_NOT_ENOUGH_MEMORY
;
4137 MultiByteToWideChar(CP_ACP
,
4144 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4146 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4148 if (lpService
== NULL
)
4150 DPRINT("Could not find the service!\n");
4152 /* If the service could not be found and lpcchBuffer is 0,
4153 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4154 if (*lpcchBuffer
== 0)
4157 if (lpServiceName
!= NULL
)
4159 *lpServiceName
= '\0';
4163 return ERROR_SERVICE_DOES_NOT_EXIST
;
4166 dwLength
= wcslen(lpService
->lpServiceName
);
4167 if (lpServiceName
!= NULL
&&
4168 *lpcchBuffer
> dwLength
)
4170 WideCharToMultiByte(CP_ACP
,
4172 lpService
->lpServiceName
,
4173 wcslen(lpService
->lpServiceName
),
4178 return ERROR_SUCCESS
;
4181 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4183 *lpcchBuffer
= dwLength
* 2;
4190 DWORD
RI_ScGetCurrentGroupStateW(
4191 SC_RPC_HANDLE hSCManager
,
4192 LPWSTR lpLoadOrderGroup
,
4196 return ERROR_CALL_NOT_IMPLEMENTED
;
4201 DWORD
REnumServiceGroupW(
4202 SC_RPC_HANDLE hSCManager
,
4203 DWORD dwServiceType
,
4204 DWORD dwServiceState
,
4207 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4208 LPBOUNDED_DWORD_256K lpServicesReturned
,
4209 LPBOUNDED_DWORD_256K lpResumeIndex
,
4210 LPCWSTR pszGroupName
)
4213 return ERROR_CALL_NOT_IMPLEMENTED
;
4218 // WARNING: This function is untested
4221 DWORD
RChangeServiceConfig2A(
4222 SC_RPC_HANDLE hService
,
4223 SC_RPC_CONFIG_INFOA Info
)
4225 SC_RPC_CONFIG_INFOW InfoW
;
4226 DWORD dwRet
, dwLength
;
4229 DPRINT("RChangeServiceConfig2A() called\n");
4230 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4232 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4234 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4236 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4237 LPSERVICE_DESCRIPTIONA lpServiceDescriptonA
;
4239 lpServiceDescriptonA
= Info
.psd
;
4241 ///if (lpServiceDescriptonA &&
4242 ///lpServiceDescriptonA->lpDescription)
4244 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4246 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4248 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4249 if (!lpServiceDescriptonW
)
4251 return ERROR_NOT_ENOUGH_MEMORY
;
4254 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4256 MultiByteToWideChar(CP_ACP
,
4260 lpServiceDescriptonW
->lpDescription
,
4263 ptr
= lpServiceDescriptonW
;
4264 InfoW
.psd
= lpServiceDescriptonW
;
4267 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4269 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4270 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4271 DWORD dwRebootLen
= 0;
4272 DWORD dwCommandLen
= 0;
4274 lpServiceFailureActionsA
= Info
.psfa
;
4276 if (lpServiceFailureActionsA
)
4278 if (lpServiceFailureActionsA
->lpRebootMsg
)
4280 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4282 if (lpServiceFailureActionsA
->lpCommand
)
4284 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4286 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4288 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4291 if (!lpServiceFailureActionsW
)
4293 return ERROR_NOT_ENOUGH_MEMORY
;
4296 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4297 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4298 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4300 if (lpServiceFailureActionsA
->lpRebootMsg
)
4302 MultiByteToWideChar(CP_ACP
,
4304 lpServiceFailureActionsA
->lpRebootMsg
,
4306 lpServiceFailureActionsW
->lpRebootMsg
,
4310 if (lpServiceFailureActionsA
->lpCommand
)
4312 MultiByteToWideChar(CP_ACP
,
4314 lpServiceFailureActionsA
->lpCommand
,
4316 lpServiceFailureActionsW
->lpCommand
,
4320 ptr
= lpServiceFailureActionsW
;
4324 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4326 HeapFree(GetProcessHeap(), 0, ptr
);
4333 DWORD
RChangeServiceConfig2W(
4334 SC_RPC_HANDLE hService
,
4335 SC_RPC_CONFIG_INFOW Info
)
4337 DWORD dwError
= ERROR_SUCCESS
;
4338 PSERVICE_HANDLE hSvc
;
4339 PSERVICE lpService
= NULL
;
4340 HKEY hServiceKey
= NULL
;
4342 DPRINT("RChangeServiceConfig2W() called\n");
4343 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4346 return ERROR_SHUTDOWN_IN_PROGRESS
;
4348 hSvc
= (PSERVICE_HANDLE
)hService
;
4349 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4351 DPRINT("Invalid handle tag!\n");
4352 return ERROR_INVALID_HANDLE
;
4355 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4356 SERVICE_CHANGE_CONFIG
))
4358 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4359 return ERROR_ACCESS_DENIED
;
4362 lpService
= hSvc
->ServiceEntry
;
4363 if (lpService
== NULL
)
4365 DPRINT("lpService == NULL!\n");
4366 return ERROR_INVALID_HANDLE
;
4369 /* FIXME: Lock database exclusively */
4371 if (lpService
->bDeleted
)
4373 /* FIXME: Unlock database */
4374 DPRINT("The service has already been marked for delete!\n");
4375 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4378 /* Open the service key */
4379 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4382 if (dwError
!= ERROR_SUCCESS
)
4385 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4387 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4389 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4390 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4392 if (lpServiceDescription
!= NULL
&&
4393 lpServiceDescription
->lpDescription
!= NULL
)
4395 DPRINT("Setting value %S\n", lpServiceDescription
->lpDescription
);
4396 RegSetValueExW(hServiceKey
,
4400 (LPBYTE
)lpServiceDescription
->lpDescription
,
4401 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4403 if (dwError
!= ERROR_SUCCESS
)
4407 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4410 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4415 /* FIXME: Unlock database */
4416 if (hServiceKey
!= NULL
)
4417 RegCloseKey(hServiceKey
);
4419 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4426 DWORD
RQueryServiceConfig2A(
4427 SC_RPC_HANDLE hService
,
4431 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4433 DWORD dwError
= ERROR_SUCCESS
;
4434 PSERVICE_HANDLE hSvc
;
4435 PSERVICE lpService
= NULL
;
4436 HKEY hServiceKey
= NULL
;
4437 LPWSTR lpDescriptionW
= NULL
;
4438 LPSTR lpDescription
= NULL
;
4440 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4441 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4444 return ERROR_INVALID_ADDRESS
;
4447 return ERROR_SHUTDOWN_IN_PROGRESS
;
4449 hSvc
= (PSERVICE_HANDLE
)hService
;
4450 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4452 DPRINT("Invalid handle tag!\n");
4453 return ERROR_INVALID_HANDLE
;
4456 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4457 SERVICE_QUERY_CONFIG
))
4459 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4460 return ERROR_ACCESS_DENIED
;
4463 lpService
= hSvc
->ServiceEntry
;
4464 if (lpService
== NULL
)
4466 DPRINT("lpService == NULL!\n");
4467 return ERROR_INVALID_HANDLE
;
4470 /* FIXME: Lock the service database shared */
4472 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4475 if (dwError
!= ERROR_SUCCESS
)
4478 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4480 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4483 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4485 dwError
= ScmReadString(hServiceKey
,
4488 if (dwError
== ERROR_SUCCESS
)
4490 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4493 if (cbBufSize
>= *pcbBytesNeeded
)
4496 if (dwError
== ERROR_SUCCESS
)
4498 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4500 WideCharToMultiByte(CP_ACP
,
4505 wcslen(lpDescriptionW
),
4508 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4512 lpServiceDescription
->lpDescription
= NULL
;
4518 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4522 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4525 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4530 if (lpDescription
!= NULL
)
4531 HeapFree(GetProcessHeap(), 0, lpDescription
);
4533 if (hServiceKey
!= NULL
)
4534 RegCloseKey(hServiceKey
);
4536 /* FIXME: Unlock database */
4538 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4545 DWORD
RQueryServiceConfig2W(
4546 SC_RPC_HANDLE hService
,
4550 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4552 DWORD dwError
= ERROR_SUCCESS
;
4553 PSERVICE_HANDLE hSvc
;
4554 PSERVICE lpService
= NULL
;
4555 HKEY hServiceKey
= NULL
;
4556 DWORD dwRequiredSize
;
4557 LPWSTR lpDescription
= NULL
;
4558 LPWSTR lpFailureCommand
= NULL
;
4559 LPWSTR lpRebootMessage
= NULL
;
4561 DPRINT("RQueryServiceConfig2W() called\n");
4564 return ERROR_INVALID_ADDRESS
;
4567 return ERROR_SHUTDOWN_IN_PROGRESS
;
4569 hSvc
= (PSERVICE_HANDLE
)hService
;
4570 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4572 DPRINT("Invalid handle tag!\n");
4573 return ERROR_INVALID_HANDLE
;
4576 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4577 SERVICE_QUERY_CONFIG
))
4579 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4580 return ERROR_ACCESS_DENIED
;
4583 lpService
= hSvc
->ServiceEntry
;
4584 if (lpService
== NULL
)
4586 DPRINT("lpService == NULL!\n");
4587 return ERROR_INVALID_HANDLE
;
4590 /* FIXME: Lock the service database shared */
4592 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4595 if (dwError
!= ERROR_SUCCESS
)
4598 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4600 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4603 dwError
= ScmReadString(hServiceKey
,
4606 if (dwError
!= ERROR_SUCCESS
)
4609 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4611 if (cbBufSize
< dwRequiredSize
)
4613 *pcbBytesNeeded
= dwRequiredSize
;
4614 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4618 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4619 wcscpy(lpStr
, lpDescription
);
4620 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4622 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4625 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
4629 dwError
= ScmReadString(hServiceKey
,
4633 dwError
= ScmReadString(hServiceKey
,
4637 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
4639 if (lpFailureCommand
)
4640 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
4642 if (lpRebootMessage
)
4643 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
4645 if (cbBufSize
< dwRequiredSize
)
4647 *pcbBytesNeeded
= dwRequiredSize
;
4648 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4652 lpFailureActions
->cActions
= 0;
4653 lpFailureActions
->dwResetPeriod
= 0;
4654 lpFailureActions
->lpCommand
= NULL
;
4655 lpFailureActions
->lpRebootMsg
= NULL
;
4656 lpFailureActions
->lpsaActions
= NULL
;
4658 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
4659 if (lpRebootMessage
)
4661 wcscpy(lpStr
, lpRebootMessage
);
4662 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
4663 lpStr
+= wcslen(lpRebootMessage
) + 1;
4666 if (lpFailureCommand
)
4668 wcscpy(lpStr
, lpFailureCommand
);
4669 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
4670 lpStr
+= wcslen(lpRebootMessage
) + 1;
4672 dwError
= STATUS_SUCCESS
;
4677 if (lpDescription
!= NULL
)
4678 HeapFree(GetProcessHeap(), 0, lpDescription
);
4680 if (lpRebootMessage
!= NULL
)
4681 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
4683 if (lpFailureCommand
!= NULL
)
4684 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
4686 if (hServiceKey
!= NULL
)
4687 RegCloseKey(hServiceKey
);
4689 /* FIXME: Unlock database */
4691 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4698 DWORD
RQueryServiceStatusEx(
4699 SC_RPC_HANDLE hService
,
4700 SC_STATUS_TYPE InfoLevel
,
4703 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4705 LPSERVICE_STATUS_PROCESS lpStatus
;
4706 PSERVICE_HANDLE hSvc
;
4709 DPRINT("RQueryServiceStatusEx() called\n");
4712 return ERROR_SHUTDOWN_IN_PROGRESS
;
4714 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4715 return ERROR_INVALID_LEVEL
;
4717 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4719 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4720 return ERROR_INSUFFICIENT_BUFFER
;
4722 hSvc
= (PSERVICE_HANDLE
)hService
;
4723 if (!hSvc
|| hSvc
->Handle
.Tag
!= SERVICE_TAG
)
4725 DPRINT("Invalid handle tag!\n");
4726 return ERROR_INVALID_HANDLE
;
4729 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4730 SERVICE_QUERY_STATUS
))
4732 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4733 return ERROR_ACCESS_DENIED
;
4736 lpService
= hSvc
->ServiceEntry
;
4737 if (lpService
== NULL
)
4739 DPRINT("lpService == NULL!\n");
4740 return ERROR_INVALID_HANDLE
;
4743 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4745 /* Return service status information */
4746 RtlCopyMemory(lpStatus
,
4748 sizeof(SERVICE_STATUS
));
4750 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
4751 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4753 return ERROR_SUCCESS
;
4758 DWORD
REnumServicesStatusExA(
4759 SC_RPC_HANDLE hSCManager
,
4760 SC_ENUM_TYPE InfoLevel
,
4761 DWORD dwServiceType
,
4762 DWORD dwServiceState
,
4765 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4766 LPBOUNDED_DWORD_256K lpServicesReturned
,
4767 LPBOUNDED_DWORD_256K lpResumeIndex
,
4768 LPCSTR pszGroupName
)
4770 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
4771 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
4772 LPWSTR lpStringPtrW
;
4774 LPWSTR pszGroupNameW
= NULL
;
4776 DWORD dwServiceCount
;
4778 DPRINT("REnumServicesStatusExA() called\n");
4782 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
4785 DPRINT("Failed to allocate buffer!\n");
4786 return ERROR_NOT_ENOUGH_MEMORY
;
4789 MultiByteToWideChar(CP_ACP
,
4794 strlen(pszGroupName
) + 1);
4797 if ((cbBufSize
> 0) && (lpBuffer
))
4799 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
4802 DPRINT("Failed to allocate buffer!\n");
4803 return ERROR_NOT_ENOUGH_MEMORY
;
4807 dwError
= REnumServicesStatusExW(hSCManager
,
4811 (LPBYTE
)lpStatusPtrW
,
4818 /* if no services were returned then we are Done */
4819 if (*lpServicesReturned
== 0)
4822 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
4823 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
4824 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
4825 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
4826 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4828 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
4830 /* Copy the service name */
4831 WideCharToMultiByte(CP_ACP
,
4836 wcslen(lpStringPtrW
),
4840 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4841 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4842 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4844 /* Copy the display name */
4845 WideCharToMultiByte(CP_ACP
,
4850 wcslen(lpStringPtrW
),
4854 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4855 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4856 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4858 /* Copy the status information */
4859 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
4860 &lpStatusPtrW
->ServiceStatusProcess
,
4861 sizeof(SERVICE_STATUS
));
4863 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
4864 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4870 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
4873 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
4875 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
4882 DWORD
REnumServicesStatusExW(
4883 SC_RPC_HANDLE hSCManager
,
4884 SC_ENUM_TYPE InfoLevel
,
4885 DWORD dwServiceType
,
4886 DWORD dwServiceState
,
4889 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4890 LPBOUNDED_DWORD_256K lpServicesReturned
,
4891 LPBOUNDED_DWORD_256K lpResumeIndex
,
4892 LPCWSTR pszGroupName
)
4894 PMANAGER_HANDLE hManager
;
4896 DWORD dwError
= ERROR_SUCCESS
;
4897 PLIST_ENTRY ServiceEntry
;
4898 PSERVICE CurrentService
;
4900 DWORD dwRequiredSize
;
4901 DWORD dwServiceCount
;
4903 DWORD dwLastResumeCount
= 0;
4904 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
4907 DPRINT("REnumServicesStatusExW() called\n");
4910 return ERROR_SHUTDOWN_IN_PROGRESS
;
4912 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
4913 return ERROR_INVALID_LEVEL
;
4915 hManager
= (PMANAGER_HANDLE
)hSCManager
;
4916 if (!hManager
|| hManager
->Handle
.Tag
!= MANAGER_TAG
)
4918 DPRINT("Invalid manager handle!\n");
4919 return ERROR_INVALID_HANDLE
;
4922 *pcbBytesNeeded
= 0;
4923 *lpServicesReturned
= 0;
4925 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
4927 DPRINT("Not a valid Service Type!\n");
4928 return ERROR_INVALID_PARAMETER
;
4931 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
4933 DPRINT("Not a valid Service State!\n");
4934 return ERROR_INVALID_PARAMETER
;
4937 /* Check access rights */
4938 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
4939 SC_MANAGER_ENUMERATE_SERVICE
))
4941 DPRINT("Insufficient access rights! 0x%lx\n",
4942 hManager
->Handle
.DesiredAccess
);
4943 return ERROR_ACCESS_DENIED
;
4946 if (lpResumeIndex
) dwLastResumeCount
= *lpResumeIndex
;
4948 /* Lock the service list shared */
4950 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
4951 if (lpService
== NULL
)
4953 dwError
= ERROR_SUCCESS
;
4960 for (ServiceEntry
= &lpService
->ServiceListEntry
;
4961 ServiceEntry
!= &ServiceListHead
;
4962 ServiceEntry
= ServiceEntry
->Flink
)
4964 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
4968 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
4971 dwState
= SERVICE_ACTIVE
;
4972 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
4973 dwState
= SERVICE_INACTIVE
;
4975 if ((dwState
& dwServiceState
) == 0)
4980 if (*pszGroupName
== 0)
4982 if (CurrentService
->lpGroup
!= NULL
)
4987 if ((CurrentService
->lpGroup
== NULL
) ||
4988 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
4993 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
4994 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
4995 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
4997 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
4999 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5000 dwRequiredSize
+= dwSize
;
5002 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5006 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5012 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5013 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5016 ServiceEntry
!= &ServiceListHead
;
5017 ServiceEntry
= ServiceEntry
->Flink
)
5019 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5023 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5026 dwState
= SERVICE_ACTIVE
;
5027 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5028 dwState
= SERVICE_INACTIVE
;
5030 if ((dwState
& dwServiceState
) == 0)
5035 if (*pszGroupName
== 0)
5037 if (CurrentService
->lpGroup
!= NULL
)
5042 if ((CurrentService
->lpGroup
== NULL
) ||
5043 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5048 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5049 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5050 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5052 dwError
= ERROR_MORE_DATA
;
5055 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5058 *lpResumeIndex
= dwLastResumeCount
;
5060 *lpServicesReturned
= dwServiceCount
;
5061 *pcbBytesNeeded
= dwRequiredSize
;
5063 /* If there was no services that matched */
5064 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5066 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5070 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5071 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5072 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5075 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5076 ServiceEntry
!= &ServiceListHead
;
5077 ServiceEntry
= ServiceEntry
->Flink
)
5079 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5083 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5086 dwState
= SERVICE_ACTIVE
;
5087 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5088 dwState
= SERVICE_INACTIVE
;
5090 if ((dwState
& dwServiceState
) == 0)
5095 if (*pszGroupName
== 0)
5097 if (CurrentService
->lpGroup
!= NULL
)
5102 if ((CurrentService
->lpGroup
== NULL
) ||
5103 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5108 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5109 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5110 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5112 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5114 /* Copy the service name */
5116 CurrentService
->lpServiceName
);
5117 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5118 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5120 /* Copy the display name */
5122 CurrentService
->lpDisplayName
);
5123 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5124 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5126 /* Copy the status information */
5127 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5128 &CurrentService
->Status
,
5129 sizeof(SERVICE_STATUS
));
5130 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
5131 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5134 dwRequiredSize
+= dwSize
;
5144 *pcbBytesNeeded
= 0;
5150 /* Unlock the service list */
5152 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5159 DWORD
RSendTSMessage(
5160 handle_t BindingHandle
) /* FIXME */
5163 return ERROR_CALL_NOT_IMPLEMENTED
;
5168 DWORD
RCreateServiceWOW64A(
5169 handle_t BindingHandle
,
5170 LPSTR lpServiceName
,
5171 LPSTR lpDisplayName
,
5172 DWORD dwDesiredAccess
,
5173 DWORD dwServiceType
,
5175 DWORD dwErrorControl
,
5176 LPSTR lpBinaryPathName
,
5177 LPSTR lpLoadOrderGroup
,
5179 LPBYTE lpDependencies
,
5181 LPSTR lpServiceStartName
,
5184 LPSC_RPC_HANDLE lpServiceHandle
)
5187 return ERROR_CALL_NOT_IMPLEMENTED
;
5192 DWORD
RCreateServiceWOW64W(
5193 handle_t BindingHandle
,
5194 LPWSTR lpServiceName
,
5195 LPWSTR lpDisplayName
,
5196 DWORD dwDesiredAccess
,
5197 DWORD dwServiceType
,
5199 DWORD dwErrorControl
,
5200 LPWSTR lpBinaryPathName
,
5201 LPWSTR lpLoadOrderGroup
,
5203 LPBYTE lpDependencies
,
5205 LPWSTR lpServiceStartName
,
5208 LPSC_RPC_HANDLE lpServiceHandle
)
5211 return ERROR_CALL_NOT_IMPLEMENTED
;
5216 DWORD
RQueryServiceTagInfo(
5217 handle_t BindingHandle
) /* FIXME */
5220 return ERROR_CALL_NOT_IMPLEMENTED
;
5225 DWORD
RNotifyServiceStatusChange(
5226 SC_RPC_HANDLE hService
,
5227 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5228 GUID
*pClientProcessGuid
,
5229 GUID
*pSCMProcessGuid
,
5230 PBOOL pfCreateRemoteQueue
,
5231 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5234 return ERROR_CALL_NOT_IMPLEMENTED
;
5239 DWORD
RGetNotifyResults(
5240 SC_NOTIFY_RPC_HANDLE hNotify
,
5241 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5244 return ERROR_CALL_NOT_IMPLEMENTED
;
5249 DWORD
RCloseNotifyHandle(
5250 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5254 return ERROR_CALL_NOT_IMPLEMENTED
;
5259 DWORD
RControlServiceExA(
5260 SC_RPC_HANDLE hService
,
5265 return ERROR_CALL_NOT_IMPLEMENTED
;
5270 DWORD
RControlServiceExW(
5271 SC_RPC_HANDLE hService
,
5276 return ERROR_CALL_NOT_IMPLEMENTED
;
5281 DWORD
RSendPnPMessage(
5282 handle_t BindingHandle
) /* FIXME */
5285 return ERROR_CALL_NOT_IMPLEMENTED
;
5290 DWORD
RValidatePnPService(
5291 handle_t BindingHandle
) /* FIXME */
5294 return ERROR_CALL_NOT_IMPLEMENTED
;
5299 DWORD
ROpenServiceStatusHandle(
5300 handle_t BindingHandle
) /* FIXME */
5303 return ERROR_CALL_NOT_IMPLEMENTED
;
5309 handle_t BindingHandle
) /* FIXME */
5312 return ERROR_CALL_NOT_IMPLEMENTED
;
5316 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5318 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5322 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5324 HeapFree(GetProcessHeap(), 0, ptr
);
5328 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5333 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5338 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)