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
31 typedef struct _MANAGER_HANDLE
34 WCHAR DatabaseName
[1];
35 } MANAGER_HANDLE
, *PMANAGER_HANDLE
;
38 typedef struct _SERVICE_HANDLE
41 PSERVICE ServiceEntry
;
42 } SERVICE_HANDLE
, *PSERVICE_HANDLE
;
45 #define SC_MANAGER_READ \
46 (STANDARD_RIGHTS_READ | \
47 SC_MANAGER_QUERY_LOCK_STATUS | \
48 SC_MANAGER_ENUMERATE_SERVICE)
50 #define SC_MANAGER_WRITE \
51 (STANDARD_RIGHTS_WRITE | \
52 SC_MANAGER_MODIFY_BOOT_CONFIG | \
53 SC_MANAGER_CREATE_SERVICE)
55 #define SC_MANAGER_EXECUTE \
56 (STANDARD_RIGHTS_EXECUTE | \
58 SC_MANAGER_ENUMERATE_SERVICE | \
59 SC_MANAGER_CONNECT | \
60 SC_MANAGER_CREATE_SERVICE)
63 #define SERVICE_READ \
64 (STANDARD_RIGHTS_READ | \
65 SERVICE_INTERROGATE | \
66 SERVICE_ENUMERATE_DEPENDENTS | \
67 SERVICE_QUERY_STATUS | \
70 #define SERVICE_WRITE \
71 (STANDARD_RIGHTS_WRITE | \
72 SERVICE_CHANGE_CONFIG)
74 #define SERVICE_EXECUTE \
75 (STANDARD_RIGHTS_EXECUTE | \
76 SERVICE_USER_DEFINED_CONTROL | \
77 SERVICE_PAUSE_CONTINUE | \
82 /* VARIABLES ***************************************************************/
84 static GENERIC_MAPPING
85 ScmManagerMapping
= {SC_MANAGER_READ
,
88 SC_MANAGER_ALL_ACCESS
};
90 static GENERIC_MAPPING
91 ScmServiceMapping
= {SERVICE_READ
,
94 SC_MANAGER_ALL_ACCESS
};
97 /* FUNCTIONS ***************************************************************/
100 ScmStartRpcServer(VOID
)
104 DPRINT("ScmStartRpcServer() called\n");
106 Status
= RpcServerUseProtseqEpW(L
"ncacn_np",
110 if (Status
!= RPC_S_OK
)
112 DPRINT1("RpcServerUseProtseqEpW() failed (Status %lx)\n", Status
);
116 Status
= RpcServerRegisterIf(svcctl_v2_0_s_ifspec
,
119 if (Status
!= RPC_S_OK
)
121 DPRINT1("RpcServerRegisterIf() failed (Status %lx)\n", Status
);
125 Status
= RpcServerListen(1, 20, TRUE
);
126 if (Status
!= RPC_S_OK
)
128 DPRINT1("RpcServerListen() failed (Status %lx)\n", Status
);
132 DPRINT("ScmStartRpcServer() done\n");
137 ScmCreateManagerHandle(LPWSTR lpDatabaseName
,
142 if (lpDatabaseName
== NULL
)
143 lpDatabaseName
= SERVICES_ACTIVE_DATABASEW
;
145 if (_wcsicmp(lpDatabaseName
, SERVICES_FAILED_DATABASEW
) == 0)
147 DPRINT("Database %S, does not exist\n",lpDatabaseName
);
148 return ERROR_DATABASE_DOES_NOT_EXIST
;
150 else if (_wcsicmp(lpDatabaseName
, SERVICES_ACTIVE_DATABASEW
) != 0)
152 DPRINT("Invalid Database name %S.\n",lpDatabaseName
);
153 return ERROR_INVALID_NAME
;
156 Ptr
= (MANAGER_HANDLE
*) HeapAlloc(GetProcessHeap(),
158 sizeof(MANAGER_HANDLE
) + (wcslen(lpDatabaseName
) + 1) * sizeof(WCHAR
));
160 return ERROR_NOT_ENOUGH_MEMORY
;
162 Ptr
->Handle
.Tag
= MANAGER_TAG
;
164 wcscpy(Ptr
->DatabaseName
, lpDatabaseName
);
166 *Handle
= (SC_HANDLE
)Ptr
;
168 return ERROR_SUCCESS
;
173 ScmCreateServiceHandle(PSERVICE lpServiceEntry
,
178 Ptr
= (SERVICE_HANDLE
*) HeapAlloc(GetProcessHeap(),
180 sizeof(SERVICE_HANDLE
));
182 return ERROR_NOT_ENOUGH_MEMORY
;
184 Ptr
->Handle
.Tag
= SERVICE_TAG
;
186 Ptr
->ServiceEntry
= lpServiceEntry
;
188 *Handle
= (SC_HANDLE
)Ptr
;
190 return ERROR_SUCCESS
;
194 static PMANAGER_HANDLE
195 ScmGetServiceManagerFromHandle(SC_RPC_HANDLE Handle
)
197 PMANAGER_HANDLE pManager
= NULL
;
201 if (((PMANAGER_HANDLE
)Handle
)->Handle
.Tag
== MANAGER_TAG
)
202 pManager
= (PMANAGER_HANDLE
)Handle
;
204 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
206 DPRINT1("Exception: Invalid Service Manager handle!\n");
214 static PSERVICE_HANDLE
215 ScmGetServiceFromHandle(SC_RPC_HANDLE Handle
)
217 PSERVICE_HANDLE pService
= NULL
;
221 if (((PSERVICE_HANDLE
)Handle
)->Handle
.Tag
== SERVICE_TAG
)
222 pService
= (PSERVICE_HANDLE
)Handle
;
224 _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER
)
226 DPRINT1("Exception: Invalid Service handle!\n");
235 ScmCheckAccess(SC_HANDLE Handle
,
236 DWORD dwDesiredAccess
)
238 PMANAGER_HANDLE hMgr
;
240 hMgr
= (PMANAGER_HANDLE
)Handle
;
241 if (hMgr
->Handle
.Tag
== MANAGER_TAG
)
243 RtlMapGenericMask(&dwDesiredAccess
,
246 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
248 return ERROR_SUCCESS
;
250 else if (hMgr
->Handle
.Tag
== SERVICE_TAG
)
252 RtlMapGenericMask(&dwDesiredAccess
,
255 hMgr
->Handle
.DesiredAccess
= dwDesiredAccess
;
257 return ERROR_SUCCESS
;
260 return ERROR_INVALID_HANDLE
;
265 ScmAssignNewTag(PSERVICE lpService
)
268 DPRINT("Assigning new tag to service %S\n", lpService
->lpServiceName
);
269 lpService
->dwTag
= 0;
270 return ERROR_SUCCESS
;
274 /* Internal recursive function */
275 /* Need to search for every dependency on every service */
277 Int_EnumDependentServicesW(HKEY hServicesKey
,
279 DWORD dwServiceState
,
280 PSERVICE
*lpServices
,
281 LPDWORD pcbBytesNeeded
,
282 LPDWORD lpServicesReturned
)
284 DWORD dwError
= ERROR_SUCCESS
;
285 WCHAR szNameBuf
[MAX_PATH
];
286 WCHAR szValueBuf
[MAX_PATH
];
287 WCHAR
*lpszNameBuf
= szNameBuf
;
288 WCHAR
*lpszValueBuf
= szValueBuf
;
292 PSERVICE lpCurrentService
;
293 HKEY hServiceEnumKey
;
294 DWORD dwCurrentServiceState
= SERVICE_ACTIVE
;
295 DWORD dwDependServiceStrPtr
= 0;
296 DWORD dwRequiredSize
= 0;
298 /* Get the number of service keys */
299 dwError
= RegQueryInfoKeyW(hServicesKey
,
311 if (dwError
!= ERROR_SUCCESS
)
313 DPRINT("ERROR! Unable to get number of services keys.\n");
317 /* Iterate the service keys to see if another service depends on the this service */
318 for (dwIteration
= 0; dwIteration
< dwNumSubKeys
; dwIteration
++)
321 dwError
= RegEnumKeyExW(hServicesKey
,
329 if (dwError
!= ERROR_SUCCESS
)
332 /* Open the Service key */
333 dwError
= RegOpenKeyExW(hServicesKey
,
338 if (dwError
!= ERROR_SUCCESS
)
343 /* Check for the DependOnService Value */
344 dwError
= RegQueryValueExW(hServiceEnumKey
,
348 (LPBYTE
)lpszValueBuf
,
351 /* FIXME: Handle load order. */
353 /* If the service found has a DependOnService value */
354 if (dwError
== ERROR_SUCCESS
)
356 dwDependServiceStrPtr
= 0;
358 /* Can be more than one Dependencies in the DependOnService string */
359 while (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) > 0)
361 if (_wcsicmp(lpszValueBuf
+ dwDependServiceStrPtr
, lpService
->lpServiceName
) == 0)
363 /* Get the current enumed service pointer */
364 lpCurrentService
= ScmGetServiceEntryByName(lpszNameBuf
);
366 /* Check for valid Service */
367 if (!lpCurrentService
)
369 /* This should never happen! */
370 DPRINT("This should not happen at this point, report to Developer\n");
371 return ERROR_NOT_FOUND
;
374 /* Determine state the service is in */
375 if (lpCurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
376 dwCurrentServiceState
= SERVICE_INACTIVE
;
378 /* If the ServiceState matches that requested or searching for SERVICE_STATE_ALL */
379 if ((dwCurrentServiceState
== dwServiceState
) ||
380 (dwServiceState
== SERVICE_STATE_ALL
))
382 /* Calculate the required size */
383 dwRequiredSize
+= sizeof(SERVICE_STATUS
);
384 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
));
385 dwRequiredSize
+= ((wcslen(lpCurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
387 /* Add the size for service name and display name pointers */
388 dwRequiredSize
+= (2 * sizeof(PVOID
));
390 /* increase the BytesNeeded size */
391 *pcbBytesNeeded
= *pcbBytesNeeded
+ dwRequiredSize
;
393 /* Don't fill callers buffer yet, as MSDN read that the last service with dependency
396 /* Recursive call to check for its dependencies */
397 Int_EnumDependentServicesW(hServicesKey
,
404 /* If the lpServices is valid set the service pointer */
406 lpServices
[*lpServicesReturned
] = lpCurrentService
;
408 *lpServicesReturned
= *lpServicesReturned
+ 1;
412 dwDependServiceStrPtr
+= (wcslen(lpszValueBuf
+ dwDependServiceStrPtr
) + 1);
415 else if (*pcbBytesNeeded
)
417 dwError
= ERROR_SUCCESS
;
420 RegCloseKey(hServiceEnumKey
);
428 DWORD
RCloseServiceHandle(
429 LPSC_RPC_HANDLE hSCObject
)
431 PMANAGER_HANDLE hManager
;
432 PSERVICE_HANDLE hService
;
436 DWORD pcbBytesNeeded
= 0;
437 DWORD dwServicesReturned
= 0;
439 DPRINT("RCloseServiceHandle() called\n");
441 DPRINT("hSCObject = %p\n", *hSCObject
);
444 return ERROR_INVALID_HANDLE
;
446 hManager
= ScmGetServiceManagerFromHandle(*hSCObject
);
447 hService
= ScmGetServiceFromHandle(*hSCObject
);
449 if (hManager
!= NULL
)
451 DPRINT("Found manager handle\n");
453 /* FIXME: add handle cleanup code */
455 HeapFree(GetProcessHeap(), 0, hManager
);
458 DPRINT("RCloseServiceHandle() done\n");
459 return ERROR_SUCCESS
;
461 else if (hService
!= NULL
)
463 DPRINT("Found service handle\n");
465 /* Get the pointer to the service record */
466 lpService
= hService
->ServiceEntry
;
468 /* FIXME: add handle cleanup code */
470 /* Free the handle */
471 HeapFree(GetProcessHeap(), 0, hService
);
474 ASSERT(lpService
->dwRefCount
> 0);
476 lpService
->dwRefCount
--;
477 DPRINT("CloseServiceHandle - lpService->dwRefCount %u\n",
478 lpService
->dwRefCount
);
480 if (lpService
->dwRefCount
== 0)
482 /* If this service has been marked for deletion */
483 if (lpService
->bDeleted
)
485 /* Open the Services Reg key */
486 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
487 L
"System\\CurrentControlSet\\Services",
489 KEY_SET_VALUE
| KEY_READ
,
491 if (dwError
!= ERROR_SUCCESS
)
493 DPRINT("Failed to open services key\n");
497 /* Call the internal function with NULL, just to get bytes we need */
498 Int_EnumDependentServicesW(hServicesKey
,
503 &dwServicesReturned
);
505 /* if pcbBytesNeeded returned a value then there are services running that are dependent on this service*/
508 DPRINT("Deletion failed due to running dependencies.\n");
509 RegCloseKey(hServicesKey
);
510 return ERROR_SUCCESS
;
513 /* There are no references and no runnning dependencies,
514 it is now safe to delete the service */
516 /* Delete the Service Key */
517 dwError
= RegDeleteKeyW(hServicesKey
,
518 lpService
->lpServiceName
);
520 RegCloseKey(hServicesKey
);
522 if (dwError
!= ERROR_SUCCESS
)
524 DPRINT("Failed to Delete the Service Registry key\n");
528 /* Delete the Service */
529 ScmDeleteServiceRecord(lpService
);
533 DPRINT("RCloseServiceHandle() done\n");
534 return ERROR_SUCCESS
;
537 DPRINT("Invalid handle tag (Tag %lx)\n", hManager
->Handle
.Tag
);
539 return ERROR_INVALID_HANDLE
;
544 DWORD
RControlService(
545 SC_RPC_HANDLE hService
,
547 LPSERVICE_STATUS lpServiceStatus
)
549 PSERVICE_HANDLE hSvc
;
551 ACCESS_MASK DesiredAccess
;
552 DWORD dwError
= ERROR_SUCCESS
;
553 DWORD pcbBytesNeeded
= 0;
554 DWORD dwServicesReturned
= 0;
555 DWORD dwControlsAccepted
;
556 DWORD dwCurrentState
;
557 HKEY hServicesKey
= NULL
;
559 DPRINT("RControlService() called\n");
562 return ERROR_SHUTDOWN_IN_PROGRESS
;
564 /* Check the service handle */
565 hSvc
= ScmGetServiceFromHandle(hService
);
568 DPRINT1("Invalid service handle!\n");
569 return ERROR_INVALID_HANDLE
;
573 /* Check the service entry point */
574 lpService
= hSvc
->ServiceEntry
;
575 if (lpService
== NULL
)
577 DPRINT1("lpService == NULL!\n");
578 return ERROR_INVALID_HANDLE
;
581 /* Check access rights */
584 case SERVICE_CONTROL_STOP
:
585 DesiredAccess
= SERVICE_STOP
;
588 case SERVICE_CONTROL_PAUSE
:
589 case SERVICE_CONTROL_CONTINUE
:
590 DesiredAccess
= SERVICE_PAUSE_CONTINUE
;
593 case SERVICE_INTERROGATE
:
594 DesiredAccess
= SERVICE_INTERROGATE
;
598 if (dwControl
>= 128 && dwControl
<= 255)
599 DesiredAccess
= SERVICE_USER_DEFINED_CONTROL
;
601 DesiredAccess
= SERVICE_QUERY_CONFIG
|
602 SERVICE_CHANGE_CONFIG
|
603 SERVICE_QUERY_STATUS
|
605 SERVICE_PAUSE_CONTINUE
;
609 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
611 return ERROR_ACCESS_DENIED
;
613 if (dwControl
== SERVICE_CONTROL_STOP
)
615 /* Check if the service has dependencies running as windows
616 doesn't stop a service that does */
618 /* Open the Services Reg key */
619 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
620 L
"System\\CurrentControlSet\\Services",
624 if (dwError
!= ERROR_SUCCESS
)
626 DPRINT("Failed to open services key\n");
630 /* Call the internal function with NULL, just to get bytes we need */
631 Int_EnumDependentServicesW(hServicesKey
,
636 &dwServicesReturned
);
638 RegCloseKey(hServicesKey
);
640 /* If pcbBytesNeeded is not zero then there are services running that
641 are dependent on this service */
642 if (pcbBytesNeeded
!= 0)
644 DPRINT("Service has running dependencies. Failed to stop service.\n");
645 return ERROR_DEPENDENT_SERVICES_RUNNING
;
649 if (lpService
->Status
.dwServiceType
& SERVICE_DRIVER
)
651 /* Send control code to the driver */
652 dwError
= ScmControlDriver(lpService
,
658 dwControlsAccepted
= lpService
->Status
.dwControlsAccepted
;
659 dwCurrentState
= lpService
->Status
.dwCurrentState
;
661 /* Check the current state before sending a control request */
662 switch (dwCurrentState
)
664 case SERVICE_STOP_PENDING
:
665 case SERVICE_STOPPED
:
666 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
668 case SERVICE_START_PENDING
:
671 case SERVICE_CONTROL_STOP
:
674 case SERVICE_CONTROL_INTERROGATE
:
675 RtlCopyMemory(lpServiceStatus
,
677 sizeof(SERVICE_STATUS
));
678 return ERROR_SUCCESS
;
681 return ERROR_SERVICE_CANNOT_ACCEPT_CTRL
;
686 /* Check if the control code is acceptable to the service */
689 case SERVICE_CONTROL_STOP
:
690 if ((dwControlsAccepted
& SERVICE_ACCEPT_STOP
) == 0)
691 return ERROR_INVALID_SERVICE_CONTROL
;
694 case SERVICE_CONTROL_PAUSE
:
695 case SERVICE_CONTROL_CONTINUE
:
696 if ((dwControlsAccepted
& SERVICE_ACCEPT_PAUSE_CONTINUE
) == 0)
697 return ERROR_INVALID_SERVICE_CONTROL
;
701 /* Send control code to the service */
702 dwError
= ScmControlService(lpService
,
705 /* Return service status information */
706 RtlCopyMemory(lpServiceStatus
,
708 sizeof(SERVICE_STATUS
));
711 if ((dwError
== ERROR_SUCCESS
) && (pcbBytesNeeded
))
712 dwError
= ERROR_DEPENDENT_SERVICES_RUNNING
;
714 if (dwError
== ERROR_SUCCESS
&&
715 dwControl
== SERVICE_CONTROL_STOP
&&
716 lpServiceStatus
->dwCurrentState
== SERVICE_STOPPED
)
718 lpService
->ProcessId
= 0; /* FIXME */
719 lpService
->ThreadId
= 0;
728 DWORD
RDeleteService(
729 SC_RPC_HANDLE hService
)
731 PSERVICE_HANDLE hSvc
;
735 DPRINT("RDeleteService() called\n");
738 return ERROR_SHUTDOWN_IN_PROGRESS
;
740 hSvc
= ScmGetServiceFromHandle(hService
);
743 DPRINT1("Invalid service handle!\n");
744 return ERROR_INVALID_HANDLE
;
747 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
749 return ERROR_ACCESS_DENIED
;
751 lpService
= hSvc
->ServiceEntry
;
752 if (lpService
== NULL
)
754 DPRINT("lpService == NULL!\n");
755 return ERROR_INVALID_HANDLE
;
758 /* FIXME: Acquire service database lock exclusively */
760 if (lpService
->bDeleted
)
762 DPRINT("The service has already been marked for delete!\n");
763 return ERROR_SERVICE_MARKED_FOR_DELETE
;
766 /* Mark service for delete */
767 lpService
->bDeleted
= TRUE
;
769 dwError
= ScmMarkServiceForDelete(lpService
);
771 /* FIXME: Release service database lock */
773 DPRINT("RDeleteService() done\n");
780 DWORD
RLockServiceDatabase(
781 SC_RPC_HANDLE hSCManager
,
782 LPSC_RPC_LOCK lpLock
)
784 PMANAGER_HANDLE hMgr
;
786 DPRINT("RLockServiceDatabase() called\n");
790 hMgr
= ScmGetServiceManagerFromHandle(hSCManager
);
793 DPRINT1("Invalid service manager handle!\n");
794 return ERROR_INVALID_HANDLE
;
797 if (!RtlAreAllAccessesGranted(hMgr
->Handle
.DesiredAccess
,
799 return ERROR_ACCESS_DENIED
;
801 // return ScmLockDatabase(0, hMgr->0xC, hLock);
803 /* FIXME: Lock the database */
804 *lpLock
= (SC_RPC_LOCK
)0x12345678; /* Dummy! */
806 return ERROR_SUCCESS
;
811 DWORD
RQueryServiceObjectSecurity(
812 SC_RPC_HANDLE hService
,
813 SECURITY_INFORMATION dwSecurityInformation
,
814 LPBYTE lpSecurityDescriptor
,
816 LPBOUNDED_DWORD_256K pcbBytesNeeded
)
818 PSERVICE_HANDLE hSvc
;
820 ULONG DesiredAccess
= 0;
826 SECURITY_DESCRIPTOR ObjectDescriptor
;
828 DPRINT("RQueryServiceObjectSecurity() called\n");
830 hSvc
= ScmGetServiceFromHandle(hService
);
833 DPRINT1("Invalid service handle!\n");
834 return ERROR_INVALID_HANDLE
;
837 if (dwSecurityInformation
& (DACL_SECURITY_INFORMATION
|
838 GROUP_SECURITY_INFORMATION
|
839 OWNER_SECURITY_INFORMATION
))
840 DesiredAccess
|= READ_CONTROL
;
842 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
843 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
845 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
848 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
849 return ERROR_ACCESS_DENIED
;
852 lpService
= hSvc
->ServiceEntry
;
853 if (lpService
== NULL
)
855 DPRINT("lpService == NULL!\n");
856 return ERROR_INVALID_HANDLE
;
859 /* FIXME: Lock the service list */
862 Status
= RtlCreateSecurityDescriptor(&ObjectDescriptor
, SECURITY_DESCRIPTOR_REVISION
);
864 Status
= RtlQuerySecurityObject(&ObjectDescriptor
/* lpService->lpSecurityDescriptor */,
865 dwSecurityInformation
,
866 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
870 /* FIXME: Unlock the service list */
872 if (NT_SUCCESS(Status
))
874 *pcbBytesNeeded
= dwBytesNeeded
;
875 dwError
= STATUS_SUCCESS
;
877 else if (Status
== STATUS_BUFFER_TOO_SMALL
)
879 *pcbBytesNeeded
= dwBytesNeeded
;
880 dwError
= ERROR_INSUFFICIENT_BUFFER
;
882 else if (Status
== STATUS_BAD_DESCRIPTOR_FORMAT
)
884 dwError
= ERROR_GEN_FAILURE
;
888 dwError
= RtlNtStatusToDosError(Status
);
896 DWORD
RSetServiceObjectSecurity(
897 SC_RPC_HANDLE hService
,
898 DWORD dwSecurityInformation
,
899 LPBYTE lpSecurityDescriptor
,
900 DWORD dwSecuityDescriptorSize
)
902 PSERVICE_HANDLE hSvc
;
904 ULONG DesiredAccess
= 0;
905 /* HANDLE hToken = NULL; */
907 /* NTSTATUS Status; */
910 DPRINT("RSetServiceObjectSecurity() called\n");
912 hSvc
= ScmGetServiceFromHandle(hService
);
915 DPRINT1("Invalid service handle!\n");
916 return ERROR_INVALID_HANDLE
;
919 if (dwSecurityInformation
== 0 ||
920 dwSecurityInformation
& ~(OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
921 | DACL_SECURITY_INFORMATION
| SACL_SECURITY_INFORMATION
))
922 return ERROR_INVALID_PARAMETER
;
924 if (!RtlValidSecurityDescriptor((PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
))
925 return ERROR_INVALID_PARAMETER
;
927 if (dwSecurityInformation
& SACL_SECURITY_INFORMATION
)
928 DesiredAccess
|= ACCESS_SYSTEM_SECURITY
;
930 if (dwSecurityInformation
& DACL_SECURITY_INFORMATION
)
931 DesiredAccess
|= WRITE_DAC
;
933 if (dwSecurityInformation
& (OWNER_SECURITY_INFORMATION
| GROUP_SECURITY_INFORMATION
))
934 DesiredAccess
|= WRITE_OWNER
;
936 if ((dwSecurityInformation
& OWNER_SECURITY_INFORMATION
) &&
937 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Owner
== NULL
))
938 return ERROR_INVALID_PARAMETER
;
940 if ((dwSecurityInformation
& GROUP_SECURITY_INFORMATION
) &&
941 (((PISECURITY_DESCRIPTOR
)lpSecurityDescriptor
)->Group
== NULL
))
942 return ERROR_INVALID_PARAMETER
;
944 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
947 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
948 return ERROR_ACCESS_DENIED
;
951 lpService
= hSvc
->ServiceEntry
;
952 if (lpService
== NULL
)
954 DPRINT("lpService == NULL!\n");
955 return ERROR_INVALID_HANDLE
;
958 if (lpService
->bDeleted
)
959 return ERROR_SERVICE_MARKED_FOR_DELETE
;
962 RpcImpersonateClient(NULL
);
964 Status
= NtOpenThreadToken(NtCurrentThread(),
968 if (!NT_SUCCESS(Status
))
969 return RtlNtStatusToDosError(Status
);
973 /* FIXME: Lock service database */
975 Status
= RtlSetSecurityObject(dwSecurityInformation
,
976 (PSECURITY_DESCRIPTOR
)lpSecurityDescriptor
,
977 &lpService
->lpSecurityDescriptor
,
980 if (!NT_SUCCESS(Status
))
982 dwError
= RtlNtStatusToDosError(Status
);
987 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
988 READ_CONTROL
| KEY_CREATE_SUB_KEY
| KEY_SET_VALUE
,
990 if (dwError
!= ERROR_SUCCESS
)
994 dwError
= ERROR_SUCCESS
;
995 // dwError = ScmWriteSecurityDescriptor(hServiceKey,
996 // lpService->lpSecurityDescriptor);
998 RegFlushKey(hServiceKey
);
999 RegCloseKey(hServiceKey
);
1008 /* FIXME: Unlock service database */
1010 DPRINT("RSetServiceObjectSecurity() done (Error %lu)\n", dwError
);
1017 DWORD
RQueryServiceStatus(
1018 SC_RPC_HANDLE hService
,
1019 LPSERVICE_STATUS lpServiceStatus
)
1021 PSERVICE_HANDLE hSvc
;
1024 DPRINT("RQueryServiceStatus() called\n");
1027 return ERROR_SHUTDOWN_IN_PROGRESS
;
1029 hSvc
= ScmGetServiceFromHandle(hService
);
1032 DPRINT1("Invalid service handle!\n");
1033 return ERROR_INVALID_HANDLE
;
1036 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1037 SERVICE_QUERY_STATUS
))
1039 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1040 return ERROR_ACCESS_DENIED
;
1043 lpService
= hSvc
->ServiceEntry
;
1044 if (lpService
== NULL
)
1046 DPRINT("lpService == NULL!\n");
1047 return ERROR_INVALID_HANDLE
;
1050 ScmLockDatabaseShared();
1052 /* Return service status information */
1053 RtlCopyMemory(lpServiceStatus
,
1055 sizeof(SERVICE_STATUS
));
1057 ScmUnlockDatabase();
1059 return ERROR_SUCCESS
;
1064 ScmIsValidServiceState(DWORD dwCurrentState
)
1066 switch (dwCurrentState
)
1068 case SERVICE_STOPPED
:
1069 case SERVICE_START_PENDING
:
1070 case SERVICE_STOP_PENDING
:
1071 case SERVICE_RUNNING
:
1072 case SERVICE_CONTINUE_PENDING
:
1073 case SERVICE_PAUSE_PENDING
:
1074 case SERVICE_PAUSED
:
1084 DWORD
RSetServiceStatus(
1085 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1086 LPSERVICE_STATUS lpServiceStatus
)
1090 DPRINT("RSetServiceStatus() called\n");
1091 DPRINT("hServiceStatus = %p\n", hServiceStatus
);
1092 DPRINT("dwServiceType = %lu\n", lpServiceStatus
->dwServiceType
);
1093 DPRINT("dwCurrentState = %lu\n", lpServiceStatus
->dwCurrentState
);
1094 DPRINT("dwControlsAccepted = %lu\n", lpServiceStatus
->dwControlsAccepted
);
1095 DPRINT("dwWin32ExitCode = %lu\n", lpServiceStatus
->dwWin32ExitCode
);
1096 DPRINT("dwServiceSpecificExitCode = %lu\n", lpServiceStatus
->dwServiceSpecificExitCode
);
1097 DPRINT("dwCheckPoint = %lu\n", lpServiceStatus
->dwCheckPoint
);
1098 DPRINT("dwWaitHint = %lu\n", lpServiceStatus
->dwWaitHint
);
1100 if (hServiceStatus
== 0)
1102 DPRINT("hServiceStatus == NULL!\n");
1103 return ERROR_INVALID_HANDLE
;
1106 lpService
= (PSERVICE
)hServiceStatus
;
1107 if (lpService
== NULL
)
1109 DPRINT("lpService == NULL!\n");
1110 return ERROR_INVALID_HANDLE
;
1113 /* Check current state */
1114 if (!ScmIsValidServiceState(lpServiceStatus
->dwCurrentState
))
1116 DPRINT("Invalid service state!\n");
1117 return ERROR_INVALID_DATA
;
1120 /* Check service type */
1121 if (!(lpServiceStatus
->dwServiceType
& SERVICE_WIN32
) &&
1122 (lpServiceStatus
->dwServiceType
& SERVICE_DRIVER
))
1124 DPRINT("Invalid service type!\n");
1125 return ERROR_INVALID_DATA
;
1128 /* Check accepted controls */
1129 if (lpServiceStatus
->dwControlsAccepted
& ~0xFF)
1131 DPRINT("Invalid controls accepted!\n");
1132 return ERROR_INVALID_DATA
;
1135 ScmLockDatabaseExclusive();
1137 RtlCopyMemory(&lpService
->Status
,
1139 sizeof(SERVICE_STATUS
));
1141 ScmUnlockDatabase();
1143 DPRINT("Set %S to %lu\n", lpService
->lpDisplayName
, lpService
->Status
.dwCurrentState
);
1144 DPRINT("RSetServiceStatus() done\n");
1146 return ERROR_SUCCESS
;
1151 DWORD
RUnlockServiceDatabase(
1155 return ERROR_SUCCESS
;
1160 DWORD
RNotifyBootConfigStatus(
1161 SVCCTL_HANDLEW lpMachineName
,
1162 DWORD BootAcceptable
)
1165 return ERROR_CALL_NOT_IMPLEMENTED
;
1170 DWORD
RI_ScSetServiceBitsW(
1171 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
1172 DWORD dwServiceBits
,
1174 int bUpdateImmediately
,
1178 return ERROR_CALL_NOT_IMPLEMENTED
;
1183 DWORD
RChangeServiceConfigW(
1184 SC_RPC_HANDLE hService
,
1185 DWORD dwServiceType
,
1187 DWORD dwErrorControl
,
1188 LPWSTR lpBinaryPathName
,
1189 LPWSTR lpLoadOrderGroup
,
1191 LPBYTE lpDependencies
,
1193 LPWSTR lpServiceStartName
,
1196 LPWSTR lpDisplayName
)
1198 DWORD dwError
= ERROR_SUCCESS
;
1199 PSERVICE_HANDLE hSvc
;
1200 PSERVICE lpService
= NULL
;
1201 HKEY hServiceKey
= NULL
;
1202 LPWSTR lpDisplayNameW
= NULL
;
1204 DPRINT("RChangeServiceConfigW() called\n");
1205 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1206 DPRINT("dwStartType = %lu\n", dwStartType
);
1207 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1208 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1209 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1210 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1213 return ERROR_SHUTDOWN_IN_PROGRESS
;
1215 hSvc
= ScmGetServiceFromHandle(hService
);
1218 DPRINT1("Invalid service handle!\n");
1219 return ERROR_INVALID_HANDLE
;
1222 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
1223 SERVICE_CHANGE_CONFIG
))
1225 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
1226 return ERROR_ACCESS_DENIED
;
1229 lpService
= hSvc
->ServiceEntry
;
1230 if (lpService
== NULL
)
1232 DPRINT("lpService == NULL!\n");
1233 return ERROR_INVALID_HANDLE
;
1236 /* FIXME: Lock database exclusively */
1238 if (lpService
->bDeleted
)
1240 /* FIXME: Unlock database */
1241 DPRINT("The service has already been marked for delete!\n");
1242 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1245 /* Open the service key */
1246 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
1249 if (dwError
!= ERROR_SUCCESS
)
1252 /* Write service data to the registry */
1253 /* Set the display name */
1254 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1256 RegSetValueExW(hServiceKey
,
1260 (LPBYTE
)lpDisplayName
,
1261 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1263 /* Update the display name */
1264 lpDisplayNameW
= (LPWSTR
)HeapAlloc(GetProcessHeap(),
1266 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1267 if (lpDisplayNameW
== NULL
)
1269 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1273 if (lpService
->lpDisplayName
!= lpService
->lpServiceName
)
1274 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
1276 lpService
->lpDisplayName
= lpDisplayNameW
;
1279 if (dwServiceType
!= SERVICE_NO_CHANGE
)
1281 /* Set the service type */
1282 dwError
= RegSetValueExW(hServiceKey
,
1286 (LPBYTE
)&dwServiceType
,
1288 if (dwError
!= ERROR_SUCCESS
)
1291 lpService
->Status
.dwServiceType
= dwServiceType
;
1294 if (dwStartType
!= SERVICE_NO_CHANGE
)
1296 /* Set the start value */
1297 dwError
= RegSetValueExW(hServiceKey
,
1301 (LPBYTE
)&dwStartType
,
1303 if (dwError
!= ERROR_SUCCESS
)
1306 lpService
->dwStartType
= dwStartType
;
1309 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
1311 /* Set the error control value */
1312 dwError
= RegSetValueExW(hServiceKey
,
1316 (LPBYTE
)&dwErrorControl
,
1318 if (dwError
!= ERROR_SUCCESS
)
1321 lpService
->dwErrorControl
= dwErrorControl
;
1325 /* FIXME: set the new ImagePath value */
1327 /* Set the image path */
1328 if (dwServiceType
& SERVICE_WIN32
)
1330 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
1332 dwError
= RegSetValueExW(hServiceKey
,
1336 (LPBYTE
)lpBinaryPathName
,
1337 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
1338 if (dwError
!= ERROR_SUCCESS
)
1342 else if (dwServiceType
& SERVICE_DRIVER
)
1344 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
1346 dwError
= RegSetValueExW(hServiceKey
,
1350 (LPBYTE
)lpImagePath
,
1351 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
1352 if (dwError
!= ERROR_SUCCESS
)
1358 /* Set the group name */
1359 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1361 dwError
= RegSetValueExW(hServiceKey
,
1365 (LPBYTE
)lpLoadOrderGroup
,
1366 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
1367 if (dwError
!= ERROR_SUCCESS
)
1370 dwError
= ScmSetServiceGroup(lpService
,
1372 if (dwError
!= ERROR_SUCCESS
)
1376 if (lpdwTagId
!= NULL
)
1378 dwError
= ScmAssignNewTag(lpService
);
1379 if (dwError
!= ERROR_SUCCESS
)
1382 dwError
= RegSetValueExW(hServiceKey
,
1386 (LPBYTE
)&lpService
->dwTag
,
1388 if (dwError
!= ERROR_SUCCESS
)
1391 *lpdwTagId
= lpService
->dwTag
;
1394 /* Write dependencies */
1395 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
1397 dwError
= ScmWriteDependencies(hServiceKey
,
1398 (LPWSTR
)lpDependencies
,
1400 if (dwError
!= ERROR_SUCCESS
)
1404 if (lpPassword
!= NULL
)
1406 /* FIXME: Write password */
1409 /* FIXME: Unlock database */
1412 if (hServiceKey
!= NULL
)
1413 RegCloseKey(hServiceKey
);
1415 DPRINT("RChangeServiceConfigW() done (Error %lu)\n", dwError
);
1421 /* Create a path suitable for the bootloader out of the full path */
1423 ScmConvertToBootPathName(wchar_t *CanonName
, wchar_t **RelativeName
)
1425 DWORD ServiceNameLen
, BufferSize
, ExpandedLen
;
1428 UNICODE_STRING NtPathName
, SystemRoot
, LinkTarget
;
1429 OBJECT_ATTRIBUTES ObjectAttributes
;
1431 HANDLE SymbolicLinkHandle
;
1433 DPRINT("ScmConvertToBootPathName %S\n", CanonName
);
1435 ServiceNameLen
= wcslen(CanonName
);
1437 /* First check, if it's already good */
1438 if (ServiceNameLen
> 12 &&
1439 !_wcsnicmp(L
"\\SystemRoot\\", CanonName
, 12))
1441 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1442 if (*RelativeName
== NULL
)
1444 DPRINT("Error allocating memory for boot driver name!\n");
1445 return ERROR_NOT_ENOUGH_MEMORY
;
1449 wcscpy(*RelativeName
, CanonName
);
1451 DPRINT("Bootdriver name %S\n", *RelativeName
);
1452 return ERROR_SUCCESS
;
1455 /* If it has %SystemRoot% prefix, substitute it to \System*/
1456 if (ServiceNameLen
> 13 &&
1457 !_wcsnicmp(L
"%SystemRoot%\\", CanonName
, 13))
1459 /* There is no +sizeof(wchar_t) because the name is less by 1 wchar */
1460 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
));
1462 if (*RelativeName
== NULL
)
1464 DPRINT("Error allocating memory for boot driver name!\n");
1465 return ERROR_NOT_ENOUGH_MEMORY
;
1469 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1470 wcscat(*RelativeName
, CanonName
+ 13);
1472 DPRINT("Bootdriver name %S\n", *RelativeName
);
1473 return ERROR_SUCCESS
;
1476 /* Get buffer size needed for expanding env strings */
1477 BufferSize
= ExpandEnvironmentStringsW(L
"%SystemRoot%\\", &Dest
, 1);
1479 if (BufferSize
<= 1)
1481 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1482 return ERROR_INVALID_ENVIRONMENT
;
1485 /* Allocate memory, since the size is known now */
1486 Expanded
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
* sizeof(WCHAR
) + sizeof(WCHAR
));
1489 DPRINT("Error allocating memory for boot driver name!\n");
1490 return ERROR_NOT_ENOUGH_MEMORY
;
1494 if (ExpandEnvironmentStringsW(L
"%SystemRoot%\\", Expanded
, BufferSize
) >
1497 DPRINT("Error during a call to ExpandEnvironmentStringsW()\n");
1498 LocalFree(Expanded
);
1499 return ERROR_NOT_ENOUGH_MEMORY
;
1502 /* Convert to NY-style path */
1503 if (!RtlDosPathNameToNtPathName_U(Expanded
, &NtPathName
, NULL
, NULL
))
1505 DPRINT("Error during a call to RtlDosPathNameToNtPathName_U()\n");
1506 return ERROR_INVALID_ENVIRONMENT
;
1509 DPRINT("Converted to NT-style %wZ\n", &NtPathName
);
1511 /* No need to keep the dos-path anymore */
1512 LocalFree(Expanded
);
1514 /* Copy it to the allocated place */
1515 Expanded
= LocalAlloc(LMEM_ZEROINIT
, NtPathName
.Length
+ sizeof(WCHAR
));
1518 DPRINT("Error allocating memory for boot driver name!\n");
1519 return ERROR_NOT_ENOUGH_MEMORY
;
1522 ExpandedLen
= NtPathName
.Length
/ sizeof(WCHAR
);
1523 wcsncpy(Expanded
, NtPathName
.Buffer
, ExpandedLen
);
1524 Expanded
[ExpandedLen
] = 0;
1526 if (ServiceNameLen
> ExpandedLen
&&
1527 !_wcsnicmp(Expanded
, CanonName
, ExpandedLen
))
1529 /* Only \SystemRoot\ is missing */
1530 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1531 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1532 if (*RelativeName
== NULL
)
1534 DPRINT("Error allocating memory for boot driver name!\n");
1535 LocalFree(Expanded
);
1536 return ERROR_NOT_ENOUGH_MEMORY
;
1539 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1540 wcscat(*RelativeName
, CanonName
+ ExpandedLen
);
1542 RtlFreeUnicodeString(&NtPathName
);
1543 return ERROR_SUCCESS
;
1546 /* The most complex case starts here */
1547 RtlInitUnicodeString(&SystemRoot
, L
"\\SystemRoot");
1548 InitializeObjectAttributes(&ObjectAttributes
,
1550 OBJ_CASE_INSENSITIVE
,
1554 /* Open this symlink */
1555 Status
= NtOpenSymbolicLinkObject(&SymbolicLinkHandle
, SYMBOLIC_LINK_QUERY
, &ObjectAttributes
);
1557 if (NT_SUCCESS(Status
))
1559 LinkTarget
.Length
= 0;
1560 LinkTarget
.MaximumLength
= 0;
1562 DPRINT("Opened symbolic link object\n");
1564 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1565 if (NT_SUCCESS(Status
) || Status
== STATUS_BUFFER_TOO_SMALL
)
1567 /* Check if required buffer size is sane */
1568 if (BufferSize
> 0xFFFD)
1570 DPRINT("Too large buffer required\n");
1573 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1574 LocalFree(Expanded
);
1575 return ERROR_NOT_ENOUGH_MEMORY
;
1578 /* Alloc the string */
1579 LinkTarget
.Buffer
= LocalAlloc(LMEM_ZEROINIT
, BufferSize
+ sizeof(WCHAR
));
1580 if (!LinkTarget
.Buffer
)
1582 DPRINT("Unable to alloc buffer\n");
1583 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1584 LocalFree(Expanded
);
1585 return ERROR_NOT_ENOUGH_MEMORY
;
1588 /* Do a real query now */
1589 LinkTarget
.Length
= BufferSize
;
1590 LinkTarget
.MaximumLength
= LinkTarget
.Length
+ sizeof(WCHAR
);
1592 Status
= NtQuerySymbolicLinkObject(SymbolicLinkHandle
, &LinkTarget
, &BufferSize
);
1593 if (NT_SUCCESS(Status
))
1595 DPRINT("LinkTarget: %wZ\n", &LinkTarget
);
1597 ExpandedLen
= LinkTarget
.Length
/ sizeof(WCHAR
);
1598 if ((ServiceNameLen
> ExpandedLen
) &&
1599 !_wcsnicmp(LinkTarget
.Buffer
, CanonName
, ExpandedLen
))
1601 *RelativeName
= LocalAlloc(LMEM_ZEROINIT
,
1602 (ServiceNameLen
- ExpandedLen
) * sizeof(WCHAR
) + 13*sizeof(WCHAR
));
1604 if (*RelativeName
== NULL
)
1606 DPRINT("Unable to alloc buffer\n");
1607 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1608 LocalFree(Expanded
);
1609 RtlFreeUnicodeString(&NtPathName
);
1610 return ERROR_NOT_ENOUGH_MEMORY
;
1613 /* Copy it over, substituting the first part
1615 wcscpy(*RelativeName
, L
"\\SystemRoot\\");
1616 wcscat(*RelativeName
, CanonName
+ExpandedLen
+1);
1619 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1620 LocalFree(Expanded
);
1621 RtlFreeUnicodeString(&NtPathName
);
1623 /* Return success */
1624 return ERROR_SUCCESS
;
1628 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1629 LocalFree(Expanded
);
1630 RtlFreeUnicodeString(&NtPathName
);
1631 return ERROR_INVALID_PARAMETER
;
1636 DPRINT("Error, Status = %08X\n", Status
);
1637 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1638 LocalFree(Expanded
);
1639 RtlFreeUnicodeString(&NtPathName
);
1640 return ERROR_INVALID_PARAMETER
;
1645 DPRINT("Error, Status = %08X\n", Status
);
1646 if (SymbolicLinkHandle
) NtClose(SymbolicLinkHandle
);
1647 LocalFree(Expanded
);
1648 RtlFreeUnicodeString(&NtPathName
);
1649 return ERROR_INVALID_PARAMETER
;
1654 DPRINT("Error, Status = %08X\n", Status
);
1655 LocalFree(Expanded
);
1656 return ERROR_INVALID_PARAMETER
;
1660 *RelativeName
= NULL
;
1661 return ERROR_INVALID_PARAMETER
;
1665 ScmCanonDriverImagePath(DWORD dwStartType
,
1666 const wchar_t *lpServiceName
,
1667 wchar_t **lpCanonName
)
1669 DWORD ServiceNameLen
, Result
;
1670 UNICODE_STRING NtServiceName
;
1671 WCHAR
*RelativeName
;
1672 const WCHAR
*SourceName
= lpServiceName
;
1674 /* Calculate the length of the service's name */
1675 ServiceNameLen
= wcslen(lpServiceName
);
1677 /* 12 is wcslen(L"\\SystemRoot\\") */
1678 if (ServiceNameLen
> 12 &&
1679 !_wcsnicmp(L
"\\SystemRoot\\", lpServiceName
, 12))
1681 /* SystemRoot prefix is already included */
1683 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1685 if (*lpCanonName
== NULL
)
1687 DPRINT("Error allocating memory for canonized service name!\n");
1688 return ERROR_NOT_ENOUGH_MEMORY
;
1691 /* If it's a boot-time driver, it must be systemroot relative */
1692 if (dwStartType
== SERVICE_BOOT_START
)
1696 wcscpy(*lpCanonName
, SourceName
);
1698 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1702 /* Check if it has %SystemRoot% (len=13) */
1703 if (ServiceNameLen
> 13 &&
1704 !_wcsnicmp(L
"%%SystemRoot%%\\", lpServiceName
, 13))
1706 /* Substitute %SystemRoot% with \\SystemRoot\\ */
1707 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1709 if (*lpCanonName
== NULL
)
1711 DPRINT("Error allocating memory for canonized service name!\n");
1712 return ERROR_NOT_ENOUGH_MEMORY
;
1715 /* If it's a boot-time driver, it must be systemroot relative */
1716 if (dwStartType
== SERVICE_BOOT_START
)
1717 wcscpy(*lpCanonName
, L
"\\SystemRoot\\");
1719 wcscat(*lpCanonName
, lpServiceName
+ 13);
1721 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1725 /* Check if it's a relative path name */
1726 if (lpServiceName
[0] != L
'\\' && lpServiceName
[1] != L
':')
1728 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, ServiceNameLen
* sizeof(WCHAR
) + sizeof(WCHAR
));
1730 if (*lpCanonName
== NULL
)
1732 DPRINT("Error allocating memory for canonized service name!\n");
1733 return ERROR_NOT_ENOUGH_MEMORY
;
1736 /* Just copy it over without changing */
1737 wcscpy(*lpCanonName
, lpServiceName
);
1742 /* It seems to be a DOS path, convert it */
1743 if (!RtlDosPathNameToNtPathName_U(lpServiceName
, &NtServiceName
, NULL
, NULL
))
1745 DPRINT("RtlDosPathNameToNtPathName_U() failed!\n");
1746 return ERROR_INVALID_PARAMETER
;
1749 *lpCanonName
= LocalAlloc(LMEM_ZEROINIT
, NtServiceName
.Length
+ sizeof(WCHAR
));
1751 if (*lpCanonName
== NULL
)
1753 DPRINT("Error allocating memory for canonized service name!\n");
1754 RtlFreeUnicodeString(&NtServiceName
);
1755 return ERROR_NOT_ENOUGH_MEMORY
;
1758 /* Copy the string */
1759 wcsncpy(*lpCanonName
, NtServiceName
.Buffer
, NtServiceName
.Length
/ sizeof(WCHAR
));
1761 /* The unicode string is not needed anymore */
1762 RtlFreeUnicodeString(&NtServiceName
);
1764 if (dwStartType
!= SERVICE_BOOT_START
)
1766 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1770 /* The service is boot-started, so must be relative */
1771 Result
= ScmConvertToBootPathName(*lpCanonName
, &RelativeName
);
1774 /* There is a problem, free name and return */
1775 LocalFree(*lpCanonName
);
1776 DPRINT("Error converting named!\n");
1780 ASSERT(RelativeName
);
1782 /* Copy that string */
1783 wcscpy(*lpCanonName
, RelativeName
+ 12);
1785 /* Free the allocated buffer */
1786 LocalFree(RelativeName
);
1788 DPRINT("Canonicalized name %S\n", *lpCanonName
);
1796 DWORD
RCreateServiceW(
1797 SC_RPC_HANDLE hSCManager
,
1798 LPCWSTR lpServiceName
,
1799 LPCWSTR lpDisplayName
,
1800 DWORD dwDesiredAccess
,
1801 DWORD dwServiceType
,
1803 DWORD dwErrorControl
,
1804 LPCWSTR lpBinaryPathName
,
1805 LPCWSTR lpLoadOrderGroup
,
1807 LPBYTE lpDependencies
,
1809 LPCWSTR lpServiceStartName
,
1812 LPSC_RPC_HANDLE lpServiceHandle
)
1814 PMANAGER_HANDLE hManager
;
1815 DWORD dwError
= ERROR_SUCCESS
;
1816 PSERVICE lpService
= NULL
;
1817 SC_HANDLE hServiceHandle
= NULL
;
1818 LPWSTR lpImagePath
= NULL
;
1819 HKEY hServiceKey
= NULL
;
1820 LPWSTR lpObjectName
;
1822 DPRINT("RCreateServiceW() called\n");
1823 DPRINT("lpServiceName = %S\n", lpServiceName
);
1824 DPRINT("lpDisplayName = %S\n", lpDisplayName
);
1825 DPRINT("dwDesiredAccess = %lx\n", dwDesiredAccess
);
1826 DPRINT("dwServiceType = %lu\n", dwServiceType
);
1827 DPRINT("dwStartType = %lu\n", dwStartType
);
1828 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
1829 DPRINT("lpBinaryPathName = %S\n", lpBinaryPathName
);
1830 DPRINT("lpLoadOrderGroup = %S\n", lpLoadOrderGroup
);
1833 return ERROR_SHUTDOWN_IN_PROGRESS
;
1835 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
1836 if (hManager
== NULL
)
1838 DPRINT1("Invalid service manager handle!\n");
1839 return ERROR_INVALID_HANDLE
;
1842 /* Check access rights */
1843 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
1844 SC_MANAGER_CREATE_SERVICE
))
1846 DPRINT("Insufficient access rights! 0x%lx\n",
1847 hManager
->Handle
.DesiredAccess
);
1848 return ERROR_ACCESS_DENIED
;
1851 if (wcslen(lpServiceName
) == 0)
1853 return ERROR_INVALID_NAME
;
1856 if (wcslen(lpBinaryPathName
) == 0)
1858 return ERROR_INVALID_PARAMETER
;
1861 if ((dwServiceType
== (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1862 (lpServiceStartName
))
1864 return ERROR_INVALID_PARAMETER
;
1867 if ((dwServiceType
> SERVICE_WIN32_SHARE_PROCESS
) &&
1868 (dwServiceType
!= (SERVICE_WIN32_OWN_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)) &&
1869 (dwServiceType
!= (SERVICE_WIN32_SHARE_PROCESS
| SERVICE_INTERACTIVE_PROCESS
)))
1871 return ERROR_INVALID_PARAMETER
;
1874 if (dwStartType
> SERVICE_DISABLED
)
1876 return ERROR_INVALID_PARAMETER
;
1879 lpService
= ScmGetServiceEntryByName(lpServiceName
);
1882 /* check if it is marked for deletion */
1883 if (lpService
->bDeleted
)
1884 return ERROR_SERVICE_MARKED_FOR_DELETE
;
1885 /* Return Error exist */
1886 return ERROR_SERVICE_EXISTS
;
1889 if (lpDisplayName
!= NULL
&&
1890 ScmGetServiceEntryByDisplayName(lpDisplayName
) != NULL
)
1891 return ERROR_DUPLICATE_SERVICE_NAME
;
1893 if (dwServiceType
& SERVICE_DRIVER
)
1895 dwError
= ScmCanonDriverImagePath(dwStartType
,
1898 if (dwError
!= ERROR_SUCCESS
)
1903 if (dwStartType
== SERVICE_BOOT_START
||
1904 dwStartType
== SERVICE_SYSTEM_START
)
1906 return ERROR_INVALID_PARAMETER
;
1910 /* Allocate a new service entry */
1911 dwError
= ScmCreateNewServiceRecord(lpServiceName
,
1913 if (dwError
!= ERROR_SUCCESS
)
1916 /* Fill the new service entry */
1917 lpService
->Status
.dwServiceType
= dwServiceType
;
1918 lpService
->dwStartType
= dwStartType
;
1919 lpService
->dwErrorControl
= dwErrorControl
;
1921 /* Fill the display name */
1922 if (lpDisplayName
!= NULL
&&
1923 *lpDisplayName
!= 0 &&
1924 _wcsicmp(lpService
->lpDisplayName
, lpDisplayName
) != 0)
1926 lpService
->lpDisplayName
= (WCHAR
*) HeapAlloc(GetProcessHeap(), 0,
1927 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1928 if (lpService
->lpDisplayName
== NULL
)
1930 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
1933 wcscpy(lpService
->lpDisplayName
, lpDisplayName
);
1936 /* Assign the service to a group */
1937 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
1939 dwError
= ScmSetServiceGroup(lpService
,
1941 if (dwError
!= ERROR_SUCCESS
)
1945 /* Assign a new tag */
1946 if (lpdwTagId
!= NULL
)
1948 dwError
= ScmAssignNewTag(lpService
);
1949 if (dwError
!= ERROR_SUCCESS
)
1953 /* Write service data to the registry */
1954 /* Create the service key */
1955 dwError
= ScmCreateServiceKey(lpServiceName
,
1958 if (dwError
!= ERROR_SUCCESS
)
1961 /* Set the display name */
1962 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
1964 RegSetValueExW(hServiceKey
,
1968 (LPBYTE
)lpDisplayName
,
1969 (wcslen(lpDisplayName
) + 1) * sizeof(WCHAR
));
1972 /* Set the service type */
1973 dwError
= RegSetValueExW(hServiceKey
,
1977 (LPBYTE
)&dwServiceType
,
1979 if (dwError
!= ERROR_SUCCESS
)
1982 /* Set the start value */
1983 dwError
= RegSetValueExW(hServiceKey
,
1987 (LPBYTE
)&dwStartType
,
1989 if (dwError
!= ERROR_SUCCESS
)
1992 /* Set the error control value */
1993 dwError
= RegSetValueExW(hServiceKey
,
1997 (LPBYTE
)&dwErrorControl
,
1999 if (dwError
!= ERROR_SUCCESS
)
2002 /* Set the image path */
2003 if (dwServiceType
& SERVICE_WIN32
)
2005 dwError
= RegSetValueExW(hServiceKey
,
2009 (LPBYTE
)lpBinaryPathName
,
2010 (wcslen(lpBinaryPathName
) + 1) * sizeof(WCHAR
));
2011 if (dwError
!= ERROR_SUCCESS
)
2014 else if (dwServiceType
& SERVICE_DRIVER
)
2016 dwError
= RegSetValueExW(hServiceKey
,
2020 (LPBYTE
)lpImagePath
,
2021 (wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2022 if (dwError
!= ERROR_SUCCESS
)
2026 /* Set the group name */
2027 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
2029 dwError
= RegSetValueExW(hServiceKey
,
2033 (LPBYTE
)lpLoadOrderGroup
,
2034 (wcslen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
2035 if (dwError
!= ERROR_SUCCESS
)
2039 if (lpdwTagId
!= NULL
)
2041 dwError
= RegSetValueExW(hServiceKey
,
2045 (LPBYTE
)&lpService
->dwTag
,
2047 if (dwError
!= ERROR_SUCCESS
)
2051 /* Write dependencies */
2052 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
2054 dwError
= ScmWriteDependencies(hServiceKey
,
2055 (LPWSTR
)lpDependencies
,
2057 if (dwError
!= ERROR_SUCCESS
)
2061 /* Write service start name */
2062 if (dwServiceType
& SERVICE_WIN32
)
2064 lpObjectName
= (lpServiceStartName
!= NULL
) ? (LPWSTR
)lpServiceStartName
: L
"LocalSystem";
2065 dwError
= RegSetValueExW(hServiceKey
,
2069 (LPBYTE
)lpObjectName
,
2070 (wcslen(lpObjectName
) + 1) * sizeof(WCHAR
));
2071 if (dwError
!= ERROR_SUCCESS
)
2075 if (lpPassword
!= NULL
)
2077 /* FIXME: Write password */
2080 dwError
= ScmCreateServiceHandle(lpService
,
2082 if (dwError
!= ERROR_SUCCESS
)
2085 dwError
= ScmCheckAccess(hServiceHandle
,
2087 if (dwError
!= ERROR_SUCCESS
)
2090 lpService
->dwRefCount
= 1;
2091 DPRINT("CreateService - lpService->dwRefCount %u\n", lpService
->dwRefCount
);
2094 if (hServiceKey
!= NULL
)
2095 RegCloseKey(hServiceKey
);
2097 if (dwError
== ERROR_SUCCESS
)
2099 DPRINT("hService %p\n", hServiceHandle
);
2100 *lpServiceHandle
= (SC_RPC_HANDLE
)hServiceHandle
;
2102 if (lpdwTagId
!= NULL
)
2103 *lpdwTagId
= lpService
->dwTag
;
2107 /* Release the display name buffer */
2108 if (lpService
->lpServiceName
!= NULL
)
2109 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
2113 /* Remove the service handle */
2114 HeapFree(GetProcessHeap(), 0, hServiceHandle
);
2117 if (lpService
!= NULL
)
2119 /* FIXME: remove the service entry */
2123 if (lpImagePath
!= NULL
)
2124 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2126 DPRINT("RCreateServiceW() done (Error %lu)\n", dwError
);
2133 DWORD
REnumDependentServicesW(
2134 SC_RPC_HANDLE hService
,
2135 DWORD dwServiceState
,
2138 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2139 LPBOUNDED_DWORD_256K lpServicesReturned
)
2141 DWORD dwError
= ERROR_SUCCESS
;
2142 DWORD dwServicesReturned
= 0;
2143 DWORD dwServiceCount
;
2144 HKEY hServicesKey
= NULL
;
2145 PSERVICE_HANDLE hSvc
;
2146 PSERVICE lpService
= NULL
;
2147 PSERVICE
*lpServicesArray
= NULL
;
2148 LPENUM_SERVICE_STATUSW lpServicesPtr
= NULL
;
2151 *pcbBytesNeeded
= 0;
2152 *lpServicesReturned
= 0;
2154 DPRINT("REnumDependentServicesW() called\n");
2156 hSvc
= ScmGetServiceFromHandle(hService
);
2159 DPRINT1("Invalid service handle!\n");
2160 return ERROR_INVALID_HANDLE
;
2163 lpService
= hSvc
->ServiceEntry
;
2165 /* Check access rights */
2166 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2167 SC_MANAGER_ENUMERATE_SERVICE
))
2169 DPRINT("Insufficient access rights! 0x%lx\n",
2170 hSvc
->Handle
.DesiredAccess
);
2171 return ERROR_ACCESS_DENIED
;
2174 /* Open the Services Reg key */
2175 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
2176 L
"System\\CurrentControlSet\\Services",
2180 if (dwError
!= ERROR_SUCCESS
)
2183 /* First determine the bytes needed and get the number of dependent services */
2184 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2189 &dwServicesReturned
);
2190 if (dwError
!= ERROR_SUCCESS
)
2193 /* If buffer size is less than the bytes needed or pointer is null */
2194 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
2196 dwError
= ERROR_MORE_DATA
;
2200 /* Allocate memory for array of service pointers */
2201 lpServicesArray
= HeapAlloc(GetProcessHeap(),
2203 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
2204 if (!lpServicesArray
)
2206 DPRINT("Could not allocate a buffer!!\n");
2207 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
2211 dwServicesReturned
= 0;
2212 *pcbBytesNeeded
= 0;
2214 dwError
= Int_EnumDependentServicesW(hServicesKey
,
2219 &dwServicesReturned
);
2220 if (dwError
!= ERROR_SUCCESS
)
2225 lpServicesPtr
= (LPENUM_SERVICE_STATUSW
) lpServices
;
2226 lpStr
= (LPWSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
)));
2228 /* Copy EnumDepenedentService to Buffer */
2229 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
2231 lpService
= lpServicesArray
[dwServiceCount
];
2233 /* Copy status info */
2234 memcpy(&lpServicesPtr
->ServiceStatus
,
2236 sizeof(SERVICE_STATUS
));
2238 /* Copy display name */
2239 wcscpy(lpStr
, lpService
->lpDisplayName
);
2240 lpServicesPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2241 lpStr
+= (wcslen(lpService
->lpDisplayName
) + 1);
2243 /* Copy service name */
2244 wcscpy(lpStr
, lpService
->lpServiceName
);
2245 lpServicesPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
2246 lpStr
+= (wcslen(lpService
->lpServiceName
) + 1);
2251 *lpServicesReturned
= dwServicesReturned
;
2254 if (lpServicesArray
!= NULL
)
2255 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
2257 RegCloseKey(hServicesKey
);
2259 DPRINT("REnumDependentServicesW() done (Error %lu)\n", dwError
);
2266 DWORD
REnumServicesStatusW(
2267 SC_RPC_HANDLE hSCManager
,
2268 DWORD dwServiceType
,
2269 DWORD dwServiceState
,
2272 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
2273 LPBOUNDED_DWORD_256K lpServicesReturned
,
2274 LPBOUNDED_DWORD_256K lpResumeHandle
)
2276 PMANAGER_HANDLE hManager
;
2278 DWORD dwError
= ERROR_SUCCESS
;
2279 PLIST_ENTRY ServiceEntry
;
2280 PSERVICE CurrentService
;
2282 DWORD dwRequiredSize
;
2283 DWORD dwServiceCount
;
2285 DWORD dwLastResumeCount
= 0;
2286 LPENUM_SERVICE_STATUSW lpStatusPtr
;
2289 DPRINT("REnumServicesStatusW() called\n");
2292 return ERROR_SHUTDOWN_IN_PROGRESS
;
2294 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2295 if (hManager
== NULL
)
2297 DPRINT1("Invalid service manager handle!\n");
2298 return ERROR_INVALID_HANDLE
;
2302 *pcbBytesNeeded
= 0;
2303 *lpServicesReturned
= 0;
2305 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
2307 DPRINT("Not a valid Service Type!\n");
2308 return ERROR_INVALID_PARAMETER
;
2311 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
2313 DPRINT("Not a valid Service State!\n");
2314 return ERROR_INVALID_PARAMETER
;
2317 /* Check access rights */
2318 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
2319 SC_MANAGER_ENUMERATE_SERVICE
))
2321 DPRINT("Insufficient access rights! 0x%lx\n",
2322 hManager
->Handle
.DesiredAccess
);
2323 return ERROR_ACCESS_DENIED
;
2327 dwLastResumeCount
= *lpResumeHandle
;
2329 /* FIXME: Lock the service list shared */
2331 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
2332 if (lpService
== NULL
)
2334 dwError
= ERROR_SUCCESS
;
2341 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2342 ServiceEntry
!= &ServiceListHead
;
2343 ServiceEntry
= ServiceEntry
->Flink
)
2345 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2349 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2352 dwState
= SERVICE_ACTIVE
;
2353 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2354 dwState
= SERVICE_INACTIVE
;
2356 if ((dwState
& dwServiceState
) == 0)
2359 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2360 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2361 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2363 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2365 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
2369 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
2370 dwRequiredSize
+= dwSize
;
2372 dwLastResumeCount
= CurrentService
->dwResumeCount
;
2375 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
2376 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
2379 ServiceEntry
!= &ServiceListHead
;
2380 ServiceEntry
= ServiceEntry
->Flink
)
2382 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2386 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2389 dwState
= SERVICE_ACTIVE
;
2390 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2391 dwState
= SERVICE_INACTIVE
;
2393 if ((dwState
& dwServiceState
) == 0)
2396 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUSW
) +
2397 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2398 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
2400 dwError
= ERROR_MORE_DATA
;
2403 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
2406 *lpResumeHandle
= dwLastResumeCount
;
2408 *lpServicesReturned
= dwServiceCount
;
2409 *pcbBytesNeeded
= dwRequiredSize
;
2411 lpStatusPtr
= (LPENUM_SERVICE_STATUSW
)lpBuffer
;
2412 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
2413 dwServiceCount
* sizeof(ENUM_SERVICE_STATUSW
));
2416 for (ServiceEntry
= &lpService
->ServiceListEntry
;
2417 ServiceEntry
!= &ServiceListHead
;
2418 ServiceEntry
= ServiceEntry
->Flink
)
2420 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
2424 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
2427 dwState
= SERVICE_ACTIVE
;
2428 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
2429 dwState
= SERVICE_INACTIVE
;
2431 if ((dwState
& dwServiceState
) == 0)
2434 dwSize
= sizeof(ENUM_SERVICE_STATUSW
) +
2435 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
2436 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2438 if (dwRequiredSize
+ dwSize
> dwBufSize
)
2441 /* Copy the service name */
2442 wcscpy(lpStringPtr
, CurrentService
->lpServiceName
);
2443 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2444 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
2446 /* Copy the display name */
2447 wcscpy(lpStringPtr
, CurrentService
->lpDisplayName
);
2448 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
2449 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
2451 /* Copy the status information */
2452 memcpy(&lpStatusPtr
->ServiceStatus
,
2453 &CurrentService
->Status
,
2454 sizeof(SERVICE_STATUS
));
2457 dwRequiredSize
+= dwSize
;
2462 *pcbBytesNeeded
= 0;
2463 if (lpResumeHandle
) *lpResumeHandle
= 0;
2467 /* FIXME: Unlock the service list */
2469 DPRINT("REnumServicesStatusW() done (Error %lu)\n", dwError
);
2476 DWORD
ROpenSCManagerW(
2477 LPWSTR lpMachineName
,
2478 LPWSTR lpDatabaseName
,
2479 DWORD dwDesiredAccess
,
2480 LPSC_RPC_HANDLE lpScHandle
)
2485 DPRINT("ROpenSCManagerW() called\n");
2486 DPRINT("lpMachineName = %p\n", lpMachineName
);
2487 DPRINT("lpMachineName: %S\n", lpMachineName
);
2488 DPRINT("lpDataBaseName = %p\n", lpDatabaseName
);
2489 DPRINT("lpDataBaseName: %S\n", lpDatabaseName
);
2490 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2493 return ERROR_SHUTDOWN_IN_PROGRESS
;
2496 return ERROR_INVALID_PARAMETER
;
2498 dwError
= ScmCreateManagerHandle(lpDatabaseName
,
2500 if (dwError
!= ERROR_SUCCESS
)
2502 DPRINT("ScmCreateManagerHandle() failed (Error %lu)\n", dwError
);
2506 /* Check the desired access */
2507 dwError
= ScmCheckAccess(hHandle
,
2508 dwDesiredAccess
| SC_MANAGER_CONNECT
);
2509 if (dwError
!= ERROR_SUCCESS
)
2511 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2512 HeapFree(GetProcessHeap(), 0, hHandle
);
2516 *lpScHandle
= (SC_RPC_HANDLE
)hHandle
;
2517 DPRINT("*hScm = %p\n", *lpScHandle
);
2519 DPRINT("ROpenSCManagerW() done\n");
2521 return ERROR_SUCCESS
;
2526 DWORD
ROpenServiceW(
2527 SC_RPC_HANDLE hSCManager
,
2528 LPWSTR lpServiceName
,
2529 DWORD dwDesiredAccess
,
2530 LPSC_RPC_HANDLE lpServiceHandle
)
2533 PMANAGER_HANDLE hManager
;
2537 DPRINT("ROpenServiceW() called\n");
2538 DPRINT("hSCManager = %p\n", hSCManager
);
2539 DPRINT("lpServiceName = %p\n", lpServiceName
);
2540 DPRINT("lpServiceName: %S\n", lpServiceName
);
2541 DPRINT("dwDesiredAccess = %x\n", dwDesiredAccess
);
2544 return ERROR_SHUTDOWN_IN_PROGRESS
;
2546 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
2547 if (hManager
== NULL
)
2549 DPRINT1("Invalid service manager handle!\n");
2550 return ERROR_INVALID_HANDLE
;
2553 if (!lpServiceHandle
)
2554 return ERROR_INVALID_PARAMETER
;
2557 return ERROR_INVALID_ADDRESS
;
2559 /* FIXME: Lock the service list */
2561 /* Get service database entry */
2562 lpService
= ScmGetServiceEntryByName(lpServiceName
);
2563 if (lpService
== NULL
)
2565 DPRINT("Could not find a service!\n");
2566 return ERROR_SERVICE_DOES_NOT_EXIST
;
2569 /* Create a service handle */
2570 dwError
= ScmCreateServiceHandle(lpService
,
2572 if (dwError
!= ERROR_SUCCESS
)
2574 DPRINT("ScmCreateServiceHandle() failed (Error %lu)\n", dwError
);
2578 /* Check the desired access */
2579 dwError
= ScmCheckAccess(hHandle
,
2581 if (dwError
!= ERROR_SUCCESS
)
2583 DPRINT("ScmCheckAccess() failed (Error %lu)\n", dwError
);
2584 HeapFree(GetProcessHeap(), 0, hHandle
);
2588 lpService
->dwRefCount
++;
2589 DPRINT("OpenService - lpService->dwRefCount %u\n",lpService
->dwRefCount
);
2591 *lpServiceHandle
= (SC_RPC_HANDLE
)hHandle
;
2592 DPRINT("*hService = %p\n", *lpServiceHandle
);
2594 DPRINT("ROpenServiceW() done\n");
2596 return ERROR_SUCCESS
;
2601 DWORD
RQueryServiceConfigW(
2602 SC_RPC_HANDLE hService
,
2603 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGW lpServiceConfig,
2605 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
2607 LPQUERY_SERVICE_CONFIGW lpServiceConfig
= (LPQUERY_SERVICE_CONFIGW
)lpBuf
;
2608 DWORD dwError
= ERROR_SUCCESS
;
2609 PSERVICE_HANDLE hSvc
;
2610 PSERVICE lpService
= NULL
;
2611 HKEY hServiceKey
= NULL
;
2612 LPWSTR lpImagePath
= NULL
;
2613 LPWSTR lpServiceStartName
= NULL
;
2614 LPWSTR lpDependencies
= NULL
;
2615 DWORD dwDependenciesLength
= 0;
2616 DWORD dwRequiredSize
;
2617 LPQUERY_SERVICE_CONFIGW lpConfig
= NULL
;
2618 WCHAR lpEmptyString
[] = {0,0};
2621 DPRINT("RQueryServiceConfigW() called\n");
2624 return ERROR_SHUTDOWN_IN_PROGRESS
;
2626 hSvc
= ScmGetServiceFromHandle(hService
);
2629 DPRINT1("Invalid service handle!\n");
2630 return ERROR_INVALID_HANDLE
;
2633 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2634 SERVICE_QUERY_CONFIG
))
2636 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2637 return ERROR_ACCESS_DENIED
;
2640 lpService
= hSvc
->ServiceEntry
;
2641 if (lpService
== NULL
)
2643 DPRINT("lpService == NULL!\n");
2644 return ERROR_INVALID_HANDLE
;
2647 /* FIXME: Lock the service database shared */
2649 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
2652 if (dwError
!= ERROR_SUCCESS
)
2655 /* Read the image path */
2656 dwError
= ScmReadString(hServiceKey
,
2659 if (dwError
!= ERROR_SUCCESS
)
2662 /* Read the service start name */
2663 ScmReadString(hServiceKey
,
2665 &lpServiceStartName
);
2667 /* Read the dependencies */
2668 ScmReadDependencies(hServiceKey
,
2670 &dwDependenciesLength
);
2672 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
2674 if (lpImagePath
!= NULL
)
2675 dwRequiredSize
+= ((wcslen(lpImagePath
) + 1) * sizeof(WCHAR
));
2677 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2679 if (lpService
->lpGroup
!= NULL
)
2680 dwRequiredSize
+= ((wcslen(lpService
->lpGroup
->lpGroupName
) + 1) * sizeof(WCHAR
));
2682 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2684 if (lpDependencies
!= NULL
)
2685 dwRequiredSize
+= dwDependenciesLength
* sizeof(WCHAR
);
2687 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2689 if (lpServiceStartName
!= NULL
)
2690 dwRequiredSize
+= ((wcslen(lpServiceStartName
) + 1) * sizeof(WCHAR
));
2692 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2694 if (lpService
->lpDisplayName
!= NULL
)
2695 dwRequiredSize
+= ((wcslen(lpService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
2697 dwRequiredSize
+= 2 * sizeof(WCHAR
);
2699 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
2701 dwError
= ERROR_INSUFFICIENT_BUFFER
;
2705 lpConfig
= (LPQUERY_SERVICE_CONFIGW
)lpServiceConfig
;
2706 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
2707 lpConfig
->dwStartType
= lpService
->dwStartType
;
2708 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
2709 lpConfig
->dwTagId
= lpService
->dwTag
;
2711 lpStr
= (LPWSTR
)(lpConfig
+ 1);
2713 /* Append the image path */
2714 if (lpImagePath
!= NULL
)
2716 wcscpy(lpStr
, lpImagePath
);
2720 wcscpy(lpStr
, lpEmptyString
);
2723 lpConfig
->lpBinaryPathName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2724 lpStr
+= (wcslen(lpStr
) + 1);
2726 /* Append the group name */
2727 if (lpService
->lpGroup
!= NULL
)
2729 wcscpy(lpStr
, lpService
->lpGroup
->lpGroupName
);
2733 wcscpy(lpStr
, lpEmptyString
);
2736 lpConfig
->lpLoadOrderGroup
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2737 lpStr
+= (wcslen(lpStr
) + 1);
2739 /* Append Dependencies */
2740 if (lpDependencies
!= NULL
)
2744 dwDependenciesLength
* sizeof(WCHAR
));
2748 wcscpy(lpStr
, lpEmptyString
);
2751 lpConfig
->lpDependencies
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2752 if (lpDependencies
!= NULL
)
2753 lpStr
+= dwDependenciesLength
* sizeof(WCHAR
);
2755 lpStr
+= (wcslen(lpStr
) + 1);
2757 /* Append the service start name */
2758 if (lpServiceStartName
!= NULL
)
2760 wcscpy(lpStr
, lpServiceStartName
);
2764 wcscpy(lpStr
, lpEmptyString
);
2767 lpConfig
->lpServiceStartName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2768 lpStr
+= (wcslen(lpStr
) + 1);
2770 /* Append the display name */
2771 if (lpService
->lpDisplayName
!= NULL
)
2773 wcscpy(lpStr
, lpService
->lpDisplayName
);
2777 wcscpy(lpStr
, lpEmptyString
);
2780 lpConfig
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
2783 if (pcbBytesNeeded
!= NULL
)
2784 *pcbBytesNeeded
= dwRequiredSize
;
2787 if (lpImagePath
!= NULL
)
2788 HeapFree(GetProcessHeap(), 0, lpImagePath
);
2790 if (lpServiceStartName
!= NULL
)
2791 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
2793 if (lpDependencies
!= NULL
)
2794 HeapFree(GetProcessHeap(), 0, lpDependencies
);
2796 if (hServiceKey
!= NULL
)
2797 RegCloseKey(hServiceKey
);
2799 /* FIXME: Unlock the service database */
2801 DPRINT("RQueryServiceConfigW() done\n");
2808 DWORD
RQueryServiceLockStatusW(
2809 SC_RPC_HANDLE hSCManager
,
2810 LPQUERY_SERVICE_LOCK_STATUSW lpLockStatus
,
2812 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
2815 return ERROR_CALL_NOT_IMPLEMENTED
;
2820 DWORD
RStartServiceW(
2821 SC_RPC_HANDLE hService
,
2823 LPSTRING_PTRSW argv
)
2825 DWORD dwError
= ERROR_SUCCESS
;
2826 PSERVICE_HANDLE hSvc
;
2827 PSERVICE lpService
= NULL
;
2829 DPRINT("RStartServiceW() called\n");
2832 return ERROR_SHUTDOWN_IN_PROGRESS
;
2834 hSvc
= ScmGetServiceFromHandle(hService
);
2837 DPRINT1("Invalid service handle!\n");
2838 return ERROR_INVALID_HANDLE
;
2841 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
2844 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
2845 return ERROR_ACCESS_DENIED
;
2848 lpService
= hSvc
->ServiceEntry
;
2849 if (lpService
== NULL
)
2851 DPRINT("lpService == NULL!\n");
2852 return ERROR_INVALID_HANDLE
;
2855 if (lpService
->dwStartType
== SERVICE_DISABLED
)
2856 return ERROR_SERVICE_DISABLED
;
2858 if (lpService
->bDeleted
)
2859 return ERROR_SERVICE_MARKED_FOR_DELETE
;
2866 /* Start the service */
2867 dwError
= ScmStartService(lpService
, argc
, (LPWSTR
*)argv
);
2874 DWORD
RGetServiceDisplayNameW(
2875 SC_RPC_HANDLE hSCManager
,
2876 LPCWSTR lpServiceName
,
2877 LPWSTR lpDisplayName
,
2880 // PMANAGER_HANDLE hManager;
2885 DPRINT("RGetServiceDisplayNameW() called\n");
2886 DPRINT("hSCManager = %p\n", hSCManager
);
2887 DPRINT("lpServiceName: %S\n", lpServiceName
);
2888 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
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
= ScmGetServiceEntryByName(lpServiceName
);
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 (lpDisplayName
!= NULL
)
2911 *lpDisplayName
= '\0';
2915 return ERROR_SERVICE_DOES_NOT_EXIST
;
2918 if (!lpService
->lpDisplayName
)
2920 dwLength
= wcslen(lpService
->lpServiceName
);
2922 if (lpDisplayName
!= NULL
&&
2923 *lpcchBuffer
> dwLength
)
2925 wcscpy(lpDisplayName
, lpService
->lpServiceName
);
2930 dwLength
= wcslen(lpService
->lpDisplayName
);
2932 if (lpDisplayName
!= NULL
&&
2933 *lpcchBuffer
> dwLength
)
2935 wcscpy(lpDisplayName
, lpService
->lpDisplayName
);
2939 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
2941 *lpcchBuffer
= dwLength
;
2948 DWORD
RGetServiceKeyNameW(
2949 SC_RPC_HANDLE hSCManager
,
2950 LPCWSTR lpDisplayName
,
2951 LPWSTR lpServiceName
,
2954 // PMANAGER_HANDLE hManager;
2959 DPRINT("RGetServiceKeyNameW() called\n");
2960 DPRINT("hSCManager = %p\n", hSCManager
);
2961 DPRINT("lpDisplayName: %S\n", lpDisplayName
);
2962 DPRINT("lpServiceName: %p\n", lpServiceName
);
2963 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
2965 // hManager = (PMANAGER_HANDLE)hSCManager;
2966 // if (hManager->Handle.Tag != MANAGER_TAG)
2968 // DPRINT("Invalid manager handle!\n");
2969 // return ERROR_INVALID_HANDLE;
2972 /* Get service database entry */
2973 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayName
);
2974 if (lpService
== NULL
)
2976 DPRINT("Could not find a service!\n");
2978 /* If the service could not be found and lpcchBuffer is less than 2, windows
2979 puts null in lpDisplayName and puts 2 in lpcchBuffer */
2980 if (*lpcchBuffer
< 2)
2983 if (lpServiceName
!= NULL
)
2985 *lpServiceName
= '\0';
2989 return ERROR_SERVICE_DOES_NOT_EXIST
;
2992 dwLength
= wcslen(lpService
->lpServiceName
);
2994 if (lpServiceName
!= NULL
&&
2995 *lpcchBuffer
> dwLength
)
2997 wcscpy(lpServiceName
, lpService
->lpServiceName
);
2998 *lpcchBuffer
= dwLength
;
2999 return ERROR_SUCCESS
;
3002 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
3004 *lpcchBuffer
= dwLength
;
3011 DWORD
RI_ScSetServiceBitsA(
3012 RPC_SERVICE_STATUS_HANDLE hServiceStatus
,
3013 DWORD dwServiceBits
,
3015 int bUpdateImmediately
,
3019 return ERROR_CALL_NOT_IMPLEMENTED
;
3024 DWORD
RChangeServiceConfigA(
3025 SC_RPC_HANDLE hService
,
3026 DWORD dwServiceType
,
3028 DWORD dwErrorControl
,
3029 LPSTR lpBinaryPathName
,
3030 LPSTR lpLoadOrderGroup
,
3032 LPSTR lpDependencies
,
3034 LPSTR lpServiceStartName
,
3037 LPSTR lpDisplayName
)
3039 DWORD dwError
= ERROR_SUCCESS
;
3040 PSERVICE_HANDLE hSvc
;
3041 PSERVICE lpService
= NULL
;
3042 HKEY hServiceKey
= NULL
;
3043 LPWSTR lpDisplayNameW
= NULL
;
3044 // LPWSTR lpBinaryPathNameW = NULL;
3045 LPWSTR lpLoadOrderGroupW
= NULL
;
3046 LPWSTR lpDependenciesW
= NULL
;
3047 // LPWSTR lpPasswordW = NULL;
3049 DPRINT("RChangeServiceConfigA() called\n");
3050 DPRINT("dwServiceType = %lu\n", dwServiceType
);
3051 DPRINT("dwStartType = %lu\n", dwStartType
);
3052 DPRINT("dwErrorControl = %lu\n", dwErrorControl
);
3053 DPRINT("lpBinaryPathName = %s\n", lpBinaryPathName
);
3054 DPRINT("lpLoadOrderGroup = %s\n", lpLoadOrderGroup
);
3055 DPRINT("lpDisplayName = %s\n", lpDisplayName
);
3058 return ERROR_SHUTDOWN_IN_PROGRESS
;
3060 hSvc
= ScmGetServiceFromHandle(hService
);
3063 DPRINT1("Invalid service handle!\n");
3064 return ERROR_INVALID_HANDLE
;
3067 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3068 SERVICE_CHANGE_CONFIG
))
3070 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3071 return ERROR_ACCESS_DENIED
;
3074 lpService
= hSvc
->ServiceEntry
;
3075 if (lpService
== NULL
)
3077 DPRINT("lpService == NULL!\n");
3078 return ERROR_INVALID_HANDLE
;
3081 /* FIXME: Lock database exclusively */
3083 if (lpService
->bDeleted
)
3085 /* FIXME: Unlock database */
3086 DPRINT("The service has already been marked for delete!\n");
3087 return ERROR_SERVICE_MARKED_FOR_DELETE
;
3090 /* Open the service key */
3091 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
3094 if (dwError
!= ERROR_SUCCESS
)
3097 /* Write service data to the registry */
3099 if (lpDisplayName
!= NULL
&& *lpDisplayName
!= 0)
3101 /* Set the display name */
3102 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
3104 (strlen(lpDisplayName
) + 1) * sizeof(WCHAR
));
3105 if (lpDisplayNameW
== NULL
)
3107 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3111 MultiByteToWideChar(CP_ACP
,
3116 strlen(lpDisplayName
) + 1);
3118 RegSetValueExW(hServiceKey
,
3122 (LPBYTE
)lpDisplayNameW
,
3123 (wcslen(lpDisplayNameW
) + 1) * sizeof(WCHAR
));
3125 /* Update lpService->lpDisplayName */
3126 if (lpService
->lpDisplayName
)
3127 HeapFree(GetProcessHeap(), 0, lpService
->lpDisplayName
);
3129 lpService
->lpDisplayName
= lpDisplayNameW
;
3132 if (dwServiceType
!= SERVICE_NO_CHANGE
)
3134 /* Set the service type */
3135 dwError
= RegSetValueExW(hServiceKey
,
3139 (LPBYTE
)&dwServiceType
,
3141 if (dwError
!= ERROR_SUCCESS
)
3144 lpService
->Status
.dwServiceType
= dwServiceType
;
3147 if (dwStartType
!= SERVICE_NO_CHANGE
)
3149 /* Set the start value */
3150 dwError
= RegSetValueExW(hServiceKey
,
3154 (LPBYTE
)&dwStartType
,
3156 if (dwError
!= ERROR_SUCCESS
)
3159 lpService
->dwStartType
= dwStartType
;
3162 if (dwErrorControl
!= SERVICE_NO_CHANGE
)
3164 /* Set the error control value */
3165 dwError
= RegSetValueExW(hServiceKey
,
3169 (LPBYTE
)&dwErrorControl
,
3171 if (dwError
!= ERROR_SUCCESS
)
3174 lpService
->dwErrorControl
= dwErrorControl
;
3178 /* FIXME: set the new ImagePath value */
3180 /* Set the image path */
3181 if (dwServiceType
& SERVICE_WIN32
)
3183 if (lpBinaryPathName
!= NULL
&& *lpBinaryPathName
!= 0)
3185 lpBinaryPathNameW
=HeapAlloc(GetProcessHeap(),0, (strlen(lpBinaryPathName
)+1) * sizeof(WCHAR
));
3186 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, strlen(lpBinaryPathName
)+1);
3187 dwError
= RegSetValueExW(hServiceKey
,
3191 (LPBYTE
)lpBinaryPathNameW
,
3192 (wcslen(lpBinaryPathNameW
) + 1) * sizeof(WCHAR
));
3193 if (dwError
!= ERROR_SUCCESS
)
3197 else if (dwServiceType
& SERVICE_DRIVER
)
3199 if (lpImagePath
!= NULL
&& *lpImagePath
!= 0)
3201 dwError
= RegSetValueExW(hServiceKey
,
3205 (LPBYTE
)lpImagePath
,
3206 (wcslen(lpImagePath
) + 1) *sizeof(WCHAR
));
3207 if (dwError
!= ERROR_SUCCESS
)
3213 /* Set the group name */
3214 if (lpLoadOrderGroup
!= NULL
&& *lpLoadOrderGroup
!= 0)
3216 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(),
3218 (strlen(lpLoadOrderGroup
) + 1) * sizeof(WCHAR
));
3219 if (lpLoadOrderGroupW
== NULL
)
3221 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3225 MultiByteToWideChar(CP_ACP
,
3230 strlen(lpLoadOrderGroup
) + 1);
3232 dwError
= RegSetValueExW(hServiceKey
,
3236 (LPBYTE
)lpLoadOrderGroupW
,
3237 (wcslen(lpLoadOrderGroupW
) + 1) * sizeof(WCHAR
));
3238 if (dwError
!= ERROR_SUCCESS
)
3240 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3244 dwError
= ScmSetServiceGroup(lpService
,
3247 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3249 if (dwError
!= ERROR_SUCCESS
)
3253 if (lpdwTagId
!= NULL
)
3255 dwError
= ScmAssignNewTag(lpService
);
3256 if (dwError
!= ERROR_SUCCESS
)
3259 dwError
= RegSetValueExW(hServiceKey
,
3263 (LPBYTE
)&lpService
->dwTag
,
3265 if (dwError
!= ERROR_SUCCESS
)
3268 *lpdwTagId
= lpService
->dwTag
;
3271 /* Write dependencies */
3272 if (lpDependencies
!= NULL
&& *lpDependencies
!= 0)
3274 lpDependenciesW
= HeapAlloc(GetProcessHeap(),
3276 (strlen(lpDependencies
) + 1) * sizeof(WCHAR
));
3277 if (lpDependenciesW
== NULL
)
3279 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3283 MultiByteToWideChar(CP_ACP
,
3288 strlen(lpDependencies
) + 1);
3290 dwError
= ScmWriteDependencies(hServiceKey
,
3291 (LPWSTR
)lpDependenciesW
,
3294 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3297 if (lpPassword
!= NULL
)
3299 /* FIXME: Write password */
3302 /* FIXME: Unlock database */
3305 if (hServiceKey
!= NULL
)
3306 RegCloseKey(hServiceKey
);
3308 DPRINT("RChangeServiceConfigA() done (Error %lu)\n", dwError
);
3315 DWORD
RCreateServiceA(
3316 SC_RPC_HANDLE hSCManager
,
3317 LPSTR lpServiceName
,
3318 LPSTR lpDisplayName
,
3319 DWORD dwDesiredAccess
,
3320 DWORD dwServiceType
,
3322 DWORD dwErrorControl
,
3323 LPSTR lpBinaryPathName
,
3324 LPSTR lpLoadOrderGroup
,
3326 LPBYTE lpDependencies
,
3328 LPSTR lpServiceStartName
,
3331 LPSC_RPC_HANDLE lpServiceHandle
)
3333 DWORD dwError
= ERROR_SUCCESS
;
3334 LPWSTR lpServiceNameW
= NULL
;
3335 LPWSTR lpDisplayNameW
= NULL
;
3336 LPWSTR lpBinaryPathNameW
= NULL
;
3337 LPWSTR lpLoadOrderGroupW
= NULL
;
3338 LPWSTR lpDependenciesW
= NULL
;
3339 LPWSTR lpServiceStartNameW
= NULL
;
3340 DWORD dwDependenciesLength
= 0;
3347 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, NULL
, 0);
3348 lpServiceNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3349 if (!lpServiceNameW
)
3351 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3354 MultiByteToWideChar(CP_ACP
, 0, lpServiceName
, -1, lpServiceNameW
, len
);
3359 len
= MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, NULL
, 0);
3360 lpDisplayNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3361 if (!lpDisplayNameW
)
3363 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3366 MultiByteToWideChar(CP_ACP
, 0, lpDisplayName
, -1, lpDisplayNameW
, len
);
3369 if (lpBinaryPathName
)
3371 len
= MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, NULL
, 0);
3372 lpBinaryPathNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3373 if (!lpBinaryPathNameW
)
3375 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3378 MultiByteToWideChar(CP_ACP
, 0, lpBinaryPathName
, -1, lpBinaryPathNameW
, len
);
3381 if (lpLoadOrderGroup
)
3383 len
= MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, NULL
, 0);
3384 lpLoadOrderGroupW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3385 if (!lpLoadOrderGroupW
)
3387 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3390 MultiByteToWideChar(CP_ACP
, 0, lpLoadOrderGroup
, -1, lpLoadOrderGroupW
, len
);
3395 lpStr
= (LPSTR
)lpDependencies
;
3398 dwLength
= strlen(lpStr
) + 1;
3399 dwDependenciesLength
+= dwLength
;
3400 lpStr
= lpStr
+ dwLength
;
3402 dwDependenciesLength
++;
3404 lpDependenciesW
= HeapAlloc(GetProcessHeap(), 0, dwDependenciesLength
* sizeof(WCHAR
));
3405 if (!lpDependenciesW
)
3407 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3410 MultiByteToWideChar(CP_ACP
, 0, (LPSTR
)lpDependencies
, dwDependenciesLength
, lpDependenciesW
, dwDependenciesLength
);
3413 if (lpServiceStartName
)
3415 len
= MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, NULL
, 0);
3416 lpServiceStartNameW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3417 if (!lpServiceStartNameW
)
3419 SetLastError(ERROR_NOT_ENOUGH_MEMORY
);
3422 MultiByteToWideChar(CP_ACP
, 0, lpServiceStartName
, -1, lpServiceStartNameW
, len
);
3425 dwError
= RCreateServiceW(hSCManager
,
3435 (LPBYTE
)lpDependenciesW
,
3436 dwDependenciesLength
,
3437 lpServiceStartNameW
,
3443 if (lpServiceNameW
!=NULL
)
3444 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
3446 if (lpDisplayNameW
!= NULL
)
3447 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
3449 if (lpBinaryPathNameW
!= NULL
)
3450 HeapFree(GetProcessHeap(), 0, lpBinaryPathNameW
);
3452 if (lpLoadOrderGroupW
!= NULL
)
3453 HeapFree(GetProcessHeap(), 0, lpLoadOrderGroupW
);
3455 if (lpDependenciesW
!= NULL
)
3456 HeapFree(GetProcessHeap(), 0, lpDependenciesW
);
3458 if (lpServiceStartNameW
!= NULL
)
3459 HeapFree(GetProcessHeap(), 0, lpServiceStartNameW
);
3466 DWORD
REnumDependentServicesA(
3467 SC_RPC_HANDLE hService
,
3468 DWORD dwServiceState
,
3471 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3472 LPBOUNDED_DWORD_256K lpServicesReturned
)
3474 DWORD dwError
= ERROR_SUCCESS
;
3475 DWORD dwServicesReturned
= 0;
3476 DWORD dwServiceCount
;
3477 HKEY hServicesKey
= NULL
;
3478 PSERVICE_HANDLE hSvc
;
3479 PSERVICE lpService
= NULL
;
3480 PSERVICE
*lpServicesArray
= NULL
;
3481 LPENUM_SERVICE_STATUSA lpServicesPtr
= NULL
;
3484 *pcbBytesNeeded
= 0;
3485 *lpServicesReturned
= 0;
3487 DPRINT("REnumDependentServicesA() called\n");
3489 hSvc
= ScmGetServiceFromHandle(hService
);
3492 DPRINT1("Invalid service handle!\n");
3493 return ERROR_INVALID_HANDLE
;
3496 lpService
= hSvc
->ServiceEntry
;
3498 /* Check access rights */
3499 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3500 SC_MANAGER_ENUMERATE_SERVICE
))
3502 DPRINT("Insufficient access rights! 0x%lx\n",
3503 hSvc
->Handle
.DesiredAccess
);
3504 return ERROR_ACCESS_DENIED
;
3507 /* Open the Services Reg key */
3508 dwError
= RegOpenKeyExW(HKEY_LOCAL_MACHINE
,
3509 L
"System\\CurrentControlSet\\Services",
3514 if (dwError
!= ERROR_SUCCESS
)
3517 /* NOTE: Windows calculates the pcbBytesNeeded based on WCHAR strings for
3518 both EnumDependentServicesA and EnumDependentServicesW. So returned pcbBytesNeeded
3519 are the same for both. Verified in WINXP. */
3521 /* First determine the bytes needed and get the number of dependent services*/
3522 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3527 &dwServicesReturned
);
3528 if (dwError
!= ERROR_SUCCESS
)
3531 /* If buffer size is less than the bytes needed or pointer is null*/
3532 if ((!lpServices
) || (cbBufSize
< *pcbBytesNeeded
))
3534 dwError
= ERROR_MORE_DATA
;
3538 /* Allocate memory for array of service pointers */
3539 lpServicesArray
= HeapAlloc(GetProcessHeap(),
3541 (dwServicesReturned
+ 1) * sizeof(PSERVICE
));
3542 if (!lpServicesArray
)
3544 DPRINT("Could not allocate a buffer!!\n");
3545 dwError
= ERROR_NOT_ENOUGH_MEMORY
;
3549 dwServicesReturned
= 0;
3550 *pcbBytesNeeded
= 0;
3552 dwError
= Int_EnumDependentServicesW(hServicesKey
,
3557 &dwServicesReturned
);
3558 if (dwError
!= ERROR_SUCCESS
)
3563 lpServicesPtr
= (LPENUM_SERVICE_STATUSA
)lpServices
;
3564 lpStr
= (LPSTR
)(lpServices
+ (dwServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
)));
3566 /* Copy EnumDepenedentService to Buffer */
3567 for (dwServiceCount
= 0; dwServiceCount
< dwServicesReturned
; dwServiceCount
++)
3569 lpService
= lpServicesArray
[dwServiceCount
];
3571 /* Copy the status info */
3572 memcpy(&lpServicesPtr
->ServiceStatus
,
3574 sizeof(SERVICE_STATUS
));
3576 /* Copy display name */
3577 WideCharToMultiByte(CP_ACP
,
3579 lpService
->lpDisplayName
,
3582 wcslen(lpService
->lpDisplayName
),
3585 lpServicesPtr
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3586 lpStr
+= strlen(lpStr
) + 1;
3588 /* Copy service name */
3589 WideCharToMultiByte(CP_ACP
,
3591 lpService
->lpServiceName
,
3594 wcslen(lpService
->lpServiceName
),
3597 lpServicesPtr
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServices
);
3598 lpStr
+= strlen(lpStr
) + 1;
3603 *lpServicesReturned
= dwServicesReturned
;
3606 if (lpServicesArray
)
3607 HeapFree(GetProcessHeap(), 0, lpServicesArray
);
3609 RegCloseKey(hServicesKey
);
3611 DPRINT("REnumDependentServicesA() done (Error %lu)\n", dwError
);
3618 DWORD
REnumServicesStatusA(
3619 SC_RPC_HANDLE hSCManager
,
3620 DWORD dwServiceType
,
3621 DWORD dwServiceState
,
3624 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
3625 LPBOUNDED_DWORD_256K lpServicesReturned
,
3626 LPBOUNDED_DWORD_256K lpResumeHandle
)
3628 LPENUM_SERVICE_STATUSW lpStatusPtrW
= NULL
;
3629 LPENUM_SERVICE_STATUSA lpStatusPtrA
= NULL
;
3630 LPWSTR lpStringPtrW
;
3633 DWORD dwServiceCount
;
3635 DPRINT("REnumServicesStatusA() called\n");
3637 if ((dwBufSize
> 0) && (lpBuffer
))
3639 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, dwBufSize
);
3642 DPRINT("Failed to allocate buffer!\n");
3643 return ERROR_NOT_ENOUGH_MEMORY
;
3647 dwError
= REnumServicesStatusW(hSCManager
,
3650 (LPBYTE
)lpStatusPtrW
,
3656 /* if no services were returned then we are Done */
3657 if (*lpServicesReturned
== 0)
3660 lpStatusPtrA
= (LPENUM_SERVICE_STATUSA
)lpBuffer
;
3661 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
3662 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSA
));
3663 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
3664 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUSW
));
3666 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
3668 /* Copy the service name */
3669 WideCharToMultiByte(CP_ACP
,
3674 wcslen(lpStringPtrW
),
3678 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3679 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3680 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3682 /* Copy the display name */
3683 WideCharToMultiByte(CP_ACP
,
3688 wcslen(lpStringPtrW
),
3692 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
3693 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
3694 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
3696 /* Copy the status information */
3697 memcpy(&lpStatusPtrA
->ServiceStatus
,
3698 &lpStatusPtrW
->ServiceStatus
,
3699 sizeof(SERVICE_STATUS
));
3706 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
3708 DPRINT("REnumServicesStatusA() done (Error %lu)\n", dwError
);
3715 DWORD
ROpenSCManagerA(
3716 LPSTR lpMachineName
,
3717 LPSTR lpDatabaseName
,
3718 DWORD dwDesiredAccess
,
3719 LPSC_RPC_HANDLE lpScHandle
)
3721 UNICODE_STRING MachineName
;
3722 UNICODE_STRING DatabaseName
;
3725 DPRINT("ROpenSCManagerA() called\n");
3728 RtlCreateUnicodeStringFromAsciiz(&MachineName
,
3732 RtlCreateUnicodeStringFromAsciiz(&DatabaseName
,
3735 dwError
= ROpenSCManagerW(lpMachineName
? MachineName
.Buffer
: NULL
,
3736 lpDatabaseName
? DatabaseName
.Buffer
: NULL
,
3741 RtlFreeUnicodeString(&MachineName
);
3744 RtlFreeUnicodeString(&DatabaseName
);
3751 DWORD
ROpenServiceA(
3752 SC_RPC_HANDLE hSCManager
,
3753 LPSTR lpServiceName
,
3754 DWORD dwDesiredAccess
,
3755 LPSC_RPC_HANDLE lpServiceHandle
)
3757 UNICODE_STRING ServiceName
;
3760 DPRINT("ROpenServiceA() called\n");
3763 RtlCreateUnicodeStringFromAsciiz(&ServiceName
,
3766 dwError
= ROpenServiceW(hSCManager
,
3767 lpServiceName
? ServiceName
.Buffer
: NULL
,
3772 RtlFreeUnicodeString(&ServiceName
);
3779 DWORD
RQueryServiceConfigA(
3780 SC_RPC_HANDLE hService
,
3781 LPBYTE lpBuf
, //LPQUERY_SERVICE_CONFIGA lpServiceConfig,
3783 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
3785 LPQUERY_SERVICE_CONFIGA lpServiceConfig
= (LPQUERY_SERVICE_CONFIGA
)lpBuf
;
3786 DWORD dwError
= ERROR_SUCCESS
;
3787 PSERVICE_HANDLE hSvc
;
3788 PSERVICE lpService
= NULL
;
3789 HKEY hServiceKey
= NULL
;
3790 LPWSTR lpImagePath
= NULL
;
3791 LPWSTR lpServiceStartName
= NULL
;
3792 LPWSTR lpDependencies
= NULL
;
3793 DWORD dwDependenciesLength
= 0;
3794 DWORD dwRequiredSize
;
3795 LPQUERY_SERVICE_CONFIGA lpConfig
= NULL
;
3796 CHAR lpEmptyString
[]={0,0};
3799 DPRINT("RQueryServiceConfigA() called\n");
3802 return ERROR_SHUTDOWN_IN_PROGRESS
;
3804 hSvc
= ScmGetServiceFromHandle(hService
);
3807 DPRINT1("Invalid service handle!\n");
3808 return ERROR_INVALID_HANDLE
;
3811 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
3812 SERVICE_QUERY_CONFIG
))
3814 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
3815 return ERROR_ACCESS_DENIED
;
3818 lpService
= hSvc
->ServiceEntry
;
3819 if (lpService
== NULL
)
3821 DPRINT("lpService == NULL!\n");
3822 return ERROR_INVALID_HANDLE
;
3825 /* FIXME: Lock the service database shared */
3827 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
3830 if (dwError
!= ERROR_SUCCESS
)
3833 /* Read the image path */
3834 dwError
= ScmReadString(hServiceKey
,
3837 if (dwError
!= ERROR_SUCCESS
)
3840 /* Read the service start name */
3841 ScmReadString(hServiceKey
,
3843 &lpServiceStartName
);
3845 /* Read the dependencies */
3846 ScmReadDependencies(hServiceKey
,
3848 &dwDependenciesLength
);
3850 dwRequiredSize
= sizeof(QUERY_SERVICE_CONFIGW
);
3852 if (lpImagePath
!= NULL
)
3853 dwRequiredSize
+= wcslen(lpImagePath
) + 1;
3855 dwRequiredSize
+= 2;
3857 if ((lpService
->lpGroup
!= NULL
) && (lpService
->lpGroup
->lpGroupName
!= NULL
))
3858 dwRequiredSize
+= wcslen(lpService
->lpGroup
->lpGroupName
) + 1;
3860 dwRequiredSize
+= 2;
3862 /* Add Dependencies length */
3863 if (lpDependencies
!= NULL
)
3864 dwRequiredSize
+= dwDependenciesLength
;
3866 dwRequiredSize
+= 2;
3868 if (lpServiceStartName
!= NULL
)
3869 dwRequiredSize
+= wcslen(lpServiceStartName
) + 1;
3871 dwRequiredSize
+= 2;
3873 if (lpService
->lpDisplayName
!= NULL
)
3874 dwRequiredSize
+= wcslen(lpService
->lpDisplayName
) + 1;
3876 dwRequiredSize
+= 2;
3878 if (lpServiceConfig
== NULL
|| cbBufSize
< dwRequiredSize
)
3880 dwError
= ERROR_INSUFFICIENT_BUFFER
;
3884 lpConfig
= (LPQUERY_SERVICE_CONFIGA
)lpServiceConfig
;
3885 lpConfig
->dwServiceType
= lpService
->Status
.dwServiceType
;
3886 lpConfig
->dwStartType
= lpService
->dwStartType
;
3887 lpConfig
->dwErrorControl
= lpService
->dwErrorControl
;
3888 lpConfig
->dwTagId
= lpService
->dwTag
;
3890 lpStr
= (LPSTR
)(lpServiceConfig
+ 1);
3892 /* NOTE: Strings that are NULL for QUERY_SERVICE_CONFIG are pointers to empty strings.
3897 WideCharToMultiByte(CP_ACP
,
3902 wcslen(lpImagePath
) + 1,
3908 strcpy(lpStr
, lpEmptyString
);
3911 lpConfig
->lpBinaryPathName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3912 lpStr
+= (strlen((LPSTR
)lpStr
) + 1);
3914 if (lpService
->lpGroup
&& lpService
->lpGroup
->lpGroupName
)
3916 WideCharToMultiByte(CP_ACP
,
3918 lpService
->lpGroup
->lpGroupName
,
3921 wcslen(lpService
->lpGroup
->lpGroupName
) + 1,
3927 strcpy(lpStr
, lpEmptyString
);
3930 lpConfig
->lpLoadOrderGroup
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3931 lpStr
+= (strlen(lpStr
) + 1);
3933 /* Append Dependencies */
3936 WideCharToMultiByte(CP_ACP
,
3939 dwDependenciesLength
,
3941 dwDependenciesLength
,
3947 strcpy(lpStr
, lpEmptyString
);
3950 lpConfig
->lpDependencies
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3952 lpStr
+= dwDependenciesLength
;
3954 lpStr
+= (strlen(lpStr
) + 1);
3956 if (lpServiceStartName
)
3958 WideCharToMultiByte(CP_ACP
,
3963 wcslen(lpServiceStartName
) + 1,
3969 strcpy(lpStr
, lpEmptyString
);
3972 lpConfig
->lpServiceStartName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3973 lpStr
+= (strlen(lpStr
) + 1);
3975 if (lpService
->lpDisplayName
)
3977 WideCharToMultiByte(CP_ACP
,
3979 lpService
->lpDisplayName
,
3982 wcslen(lpService
->lpDisplayName
) + 1,
3988 strcpy(lpStr
, lpEmptyString
);
3991 lpConfig
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpConfig
);
3994 if (pcbBytesNeeded
!= NULL
)
3995 *pcbBytesNeeded
= dwRequiredSize
;
3998 if (lpImagePath
!= NULL
)
3999 HeapFree(GetProcessHeap(), 0, lpImagePath
);
4001 if (lpServiceStartName
!= NULL
)
4002 HeapFree(GetProcessHeap(), 0, lpServiceStartName
);
4004 if (lpDependencies
!= NULL
)
4005 HeapFree(GetProcessHeap(), 0, lpDependencies
);
4007 if (hServiceKey
!= NULL
)
4008 RegCloseKey(hServiceKey
);
4010 /* FIXME: Unlock the service database */
4012 DPRINT("RQueryServiceConfigA() done\n");
4019 DWORD
RQueryServiceLockStatusA(
4020 SC_RPC_HANDLE hSCManager
,
4021 LPQUERY_SERVICE_LOCK_STATUSA lpLockStatus
,
4023 LPBOUNDED_DWORD_4K pcbBytesNeeded
)
4026 return ERROR_CALL_NOT_IMPLEMENTED
;
4031 DWORD
RStartServiceA(
4032 SC_RPC_HANDLE hService
,
4034 LPSTRING_PTRSA argv
)
4036 DWORD dwError
= ERROR_SUCCESS
;
4037 PSERVICE_HANDLE hSvc
;
4038 PSERVICE lpService
= NULL
;
4040 DPRINT("RStartServiceA() called\n");
4043 return ERROR_SHUTDOWN_IN_PROGRESS
;
4045 hSvc
= ScmGetServiceFromHandle(hService
);
4048 DPRINT1("Invalid service handle!\n");
4049 return ERROR_INVALID_HANDLE
;
4052 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4055 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4056 return ERROR_ACCESS_DENIED
;
4059 lpService
= hSvc
->ServiceEntry
;
4060 if (lpService
== NULL
)
4062 DPRINT("lpService == NULL!\n");
4063 return ERROR_INVALID_HANDLE
;
4066 if (lpService
->dwStartType
== SERVICE_DISABLED
)
4067 return ERROR_SERVICE_DISABLED
;
4069 if (lpService
->bDeleted
)
4070 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4072 /* FIXME: Convert argument vector to Unicode */
4074 /* Start the service */
4075 dwError
= ScmStartService(lpService
, 0, NULL
);
4077 /* FIXME: Free argument vector */
4084 DWORD
RGetServiceDisplayNameA(
4085 SC_RPC_HANDLE hSCManager
,
4086 LPCSTR lpServiceName
,
4087 LPSTR lpDisplayName
,
4088 LPBOUNDED_DWORD_4K lpcchBuffer
)
4090 // PMANAGER_HANDLE hManager;
4091 PSERVICE lpService
= NULL
;
4094 LPWSTR lpServiceNameW
;
4096 DPRINT("RGetServiceDisplayNameA() called\n");
4097 DPRINT("hSCManager = %p\n", hSCManager
);
4098 DPRINT("lpServiceName: %s\n", lpServiceName
);
4099 DPRINT("lpDisplayName: %p\n", lpDisplayName
);
4100 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4102 // hManager = (PMANAGER_HANDLE)hSCManager;
4103 // if (hManager->Handle.Tag != MANAGER_TAG)
4105 // DPRINT("Invalid manager handle!\n");
4106 // return ERROR_INVALID_HANDLE;
4109 if (lpServiceName
!= NULL
)
4111 dwLength
= strlen(lpServiceName
) + 1;
4112 lpServiceNameW
= HeapAlloc(GetProcessHeap(),
4114 dwLength
* sizeof(WCHAR
));
4115 if (!lpServiceNameW
)
4116 return ERROR_NOT_ENOUGH_MEMORY
;
4118 MultiByteToWideChar(CP_ACP
,
4125 lpService
= ScmGetServiceEntryByName(lpServiceNameW
);
4127 HeapFree(GetProcessHeap(), 0, lpServiceNameW
);
4130 if (lpService
== NULL
)
4132 DPRINT("Could not find a service!\n");
4134 /* If the service could not be found and lpcchBuffer is 0, windows
4135 puts null in lpDisplayName and puts 1 in lpcchBuffer */
4136 if (*lpcchBuffer
== 0)
4139 if (lpDisplayName
!= NULL
)
4141 *lpDisplayName
= '\0';
4144 return ERROR_SERVICE_DOES_NOT_EXIST
;
4147 if (!lpService
->lpDisplayName
)
4149 dwLength
= wcslen(lpService
->lpServiceName
);
4150 if (lpDisplayName
!= NULL
&&
4151 *lpcchBuffer
> dwLength
)
4153 WideCharToMultiByte(CP_ACP
,
4155 lpService
->lpServiceName
,
4156 wcslen(lpService
->lpServiceName
),
4161 return ERROR_SUCCESS
;
4166 dwLength
= wcslen(lpService
->lpDisplayName
);
4167 if (lpDisplayName
!= NULL
&&
4168 *lpcchBuffer
> dwLength
)
4170 WideCharToMultiByte(CP_ACP
,
4172 lpService
->lpDisplayName
,
4173 wcslen(lpService
->lpDisplayName
),
4178 return ERROR_SUCCESS
;
4182 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4184 *lpcchBuffer
= dwLength
* 2;
4191 DWORD
RGetServiceKeyNameA(
4192 SC_RPC_HANDLE hSCManager
,
4193 LPCSTR lpDisplayName
,
4194 LPSTR lpServiceName
,
4195 LPBOUNDED_DWORD_4K lpcchBuffer
)
4200 LPWSTR lpDisplayNameW
;
4202 DPRINT("RGetServiceKeyNameA() called\n");
4203 DPRINT("hSCManager = %p\n", hSCManager
);
4204 DPRINT("lpDisplayName: %s\n", lpDisplayName
);
4205 DPRINT("lpServiceName: %p\n", lpServiceName
);
4206 DPRINT("*lpcchBuffer: %lu\n", *lpcchBuffer
);
4208 dwLength
= strlen(lpDisplayName
) + 1;
4209 lpDisplayNameW
= HeapAlloc(GetProcessHeap(),
4211 dwLength
* sizeof(WCHAR
));
4212 if (!lpDisplayNameW
)
4213 return ERROR_NOT_ENOUGH_MEMORY
;
4215 MultiByteToWideChar(CP_ACP
,
4222 lpService
= ScmGetServiceEntryByDisplayName(lpDisplayNameW
);
4224 HeapFree(GetProcessHeap(), 0, lpDisplayNameW
);
4226 if (lpService
== NULL
)
4228 DPRINT("Could not find the service!\n");
4230 /* If the service could not be found and lpcchBuffer is 0,
4231 put null in lpDisplayName and puts 1 in lpcchBuffer, verified WINXP. */
4232 if (*lpcchBuffer
== 0)
4235 if (lpServiceName
!= NULL
)
4237 *lpServiceName
= '\0';
4241 return ERROR_SERVICE_DOES_NOT_EXIST
;
4244 dwLength
= wcslen(lpService
->lpServiceName
);
4245 if (lpServiceName
!= NULL
&&
4246 *lpcchBuffer
> dwLength
)
4248 WideCharToMultiByte(CP_ACP
,
4250 lpService
->lpServiceName
,
4251 wcslen(lpService
->lpServiceName
),
4256 return ERROR_SUCCESS
;
4259 dwError
= (*lpcchBuffer
> dwLength
) ? ERROR_SUCCESS
: ERROR_INSUFFICIENT_BUFFER
;
4261 *lpcchBuffer
= dwLength
* 2;
4268 DWORD
RI_ScGetCurrentGroupStateW(
4269 SC_RPC_HANDLE hSCManager
,
4270 LPWSTR lpLoadOrderGroup
,
4274 return ERROR_CALL_NOT_IMPLEMENTED
;
4279 DWORD
REnumServiceGroupW(
4280 SC_RPC_HANDLE hSCManager
,
4281 DWORD dwServiceType
,
4282 DWORD dwServiceState
,
4285 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4286 LPBOUNDED_DWORD_256K lpServicesReturned
,
4287 LPBOUNDED_DWORD_256K lpResumeIndex
,
4288 LPCWSTR pszGroupName
)
4291 return ERROR_CALL_NOT_IMPLEMENTED
;
4296 // WARNING: This function is untested
4299 DWORD
RChangeServiceConfig2A(
4300 SC_RPC_HANDLE hService
,
4301 SC_RPC_CONFIG_INFOA Info
)
4303 SC_RPC_CONFIG_INFOW InfoW
;
4304 DWORD dwRet
, dwLength
;
4307 DPRINT("RChangeServiceConfig2A() called\n");
4308 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4310 InfoW
.dwInfoLevel
= Info
.dwInfoLevel
;
4312 if (InfoW
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4314 LPSERVICE_DESCRIPTIONW lpServiceDescriptonW
;
4315 LPSERVICE_DESCRIPTIONA lpServiceDescriptonA
;
4317 lpServiceDescriptonA
= Info
.psd
;
4319 ///if (lpServiceDescriptonA &&
4320 ///lpServiceDescriptonA->lpDescription)
4322 dwLength
= (strlen(Info
.lpDescription
) + 1) * sizeof(WCHAR
);
4324 lpServiceDescriptonW
= HeapAlloc(GetProcessHeap(),
4326 dwLength
+ sizeof(SERVICE_DESCRIPTIONW
));
4327 if (!lpServiceDescriptonW
)
4329 return ERROR_NOT_ENOUGH_MEMORY
;
4332 lpServiceDescriptonW
->lpDescription
= (LPWSTR
)(lpServiceDescriptonW
+ 1);
4334 MultiByteToWideChar(CP_ACP
,
4338 lpServiceDescriptonW
->lpDescription
,
4341 ptr
= lpServiceDescriptonW
;
4342 InfoW
.psd
= lpServiceDescriptonW
;
4345 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4347 LPSERVICE_FAILURE_ACTIONSW lpServiceFailureActionsW
;
4348 LPSERVICE_FAILURE_ACTIONSA lpServiceFailureActionsA
;
4349 DWORD dwRebootLen
= 0;
4350 DWORD dwCommandLen
= 0;
4352 lpServiceFailureActionsA
= Info
.psfa
;
4354 if (lpServiceFailureActionsA
)
4356 if (lpServiceFailureActionsA
->lpRebootMsg
)
4358 dwRebootLen
= (strlen(lpServiceFailureActionsA
->lpRebootMsg
) + 1) * sizeof(WCHAR
);
4360 if (lpServiceFailureActionsA
->lpCommand
)
4362 dwCommandLen
= (strlen(lpServiceFailureActionsA
->lpCommand
) + 1) * sizeof(WCHAR
);
4364 dwLength
= dwRebootLen
+ dwCommandLen
+ sizeof(SERVICE_FAILURE_ACTIONSW
);
4366 lpServiceFailureActionsW
= HeapAlloc(GetProcessHeap(),
4369 if (!lpServiceFailureActionsW
)
4371 return ERROR_NOT_ENOUGH_MEMORY
;
4374 lpServiceFailureActionsW
->cActions
= lpServiceFailureActionsA
->cActions
;
4375 lpServiceFailureActionsW
->dwResetPeriod
= lpServiceFailureActionsA
->dwResetPeriod
;
4376 CopyMemory(lpServiceFailureActionsW
->lpsaActions
, lpServiceFailureActionsA
->lpsaActions
, sizeof(SC_ACTION
));
4378 if (lpServiceFailureActionsA
->lpRebootMsg
)
4380 MultiByteToWideChar(CP_ACP
,
4382 lpServiceFailureActionsA
->lpRebootMsg
,
4384 lpServiceFailureActionsW
->lpRebootMsg
,
4388 if (lpServiceFailureActionsA
->lpCommand
)
4390 MultiByteToWideChar(CP_ACP
,
4392 lpServiceFailureActionsA
->lpCommand
,
4394 lpServiceFailureActionsW
->lpCommand
,
4398 ptr
= lpServiceFailureActionsW
;
4402 dwRet
= RChangeServiceConfig2W(hService
, InfoW
);
4404 HeapFree(GetProcessHeap(), 0, ptr
);
4411 DWORD
RChangeServiceConfig2W(
4412 SC_RPC_HANDLE hService
,
4413 SC_RPC_CONFIG_INFOW Info
)
4415 DWORD dwError
= ERROR_SUCCESS
;
4416 PSERVICE_HANDLE hSvc
;
4417 PSERVICE lpService
= NULL
;
4418 HKEY hServiceKey
= NULL
;
4420 DPRINT("RChangeServiceConfig2W() called\n");
4421 DPRINT("dwInfoLevel = %lu\n", Info
.dwInfoLevel
);
4424 return ERROR_SHUTDOWN_IN_PROGRESS
;
4426 hSvc
= ScmGetServiceFromHandle(hService
);
4429 DPRINT1("Invalid service handle!\n");
4430 return ERROR_INVALID_HANDLE
;
4433 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4434 SERVICE_CHANGE_CONFIG
))
4436 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4437 return ERROR_ACCESS_DENIED
;
4440 lpService
= hSvc
->ServiceEntry
;
4441 if (lpService
== NULL
)
4443 DPRINT("lpService == NULL!\n");
4444 return ERROR_INVALID_HANDLE
;
4447 /* FIXME: Lock database exclusively */
4449 if (lpService
->bDeleted
)
4451 /* FIXME: Unlock database */
4452 DPRINT("The service has already been marked for delete!\n");
4453 return ERROR_SERVICE_MARKED_FOR_DELETE
;
4456 /* Open the service key */
4457 dwError
= ScmOpenServiceKey(lpService
->szServiceName
,
4460 if (dwError
!= ERROR_SUCCESS
)
4463 if (Info
.dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4465 LPSERVICE_DESCRIPTIONW lpServiceDescription
;
4467 lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)Info
.psd
;
4468 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpServiceDescription
+ sizeof(LPSERVICE_DESCRIPTIONW
));
4470 if (lpServiceDescription
!= NULL
&&
4471 lpServiceDescription
->lpDescription
!= NULL
)
4473 DPRINT("Setting value %S\n", lpServiceDescription
->lpDescription
);
4474 RegSetValueExW(hServiceKey
,
4478 (LPBYTE
)lpServiceDescription
->lpDescription
,
4479 (wcslen(lpServiceDescription
->lpDescription
) + 1) * sizeof(WCHAR
));
4481 if (dwError
!= ERROR_SUCCESS
)
4485 else if (Info
.dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4488 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4493 /* FIXME: Unlock database */
4494 if (hServiceKey
!= NULL
)
4495 RegCloseKey(hServiceKey
);
4497 DPRINT("RChangeServiceConfig2W() done (Error %lu)\n", dwError
);
4504 DWORD
RQueryServiceConfig2A(
4505 SC_RPC_HANDLE hService
,
4509 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4511 DWORD dwError
= ERROR_SUCCESS
;
4512 PSERVICE_HANDLE hSvc
;
4513 PSERVICE lpService
= NULL
;
4514 HKEY hServiceKey
= NULL
;
4515 LPWSTR lpDescriptionW
= NULL
;
4516 LPSTR lpDescription
= NULL
;
4518 DPRINT("RQueryServiceConfig2A() called hService %p dwInfoLevel %u, lpBuffer %p cbBufSize %u pcbBytesNeeded %p\n",
4519 hService
, dwInfoLevel
, lpBuffer
, cbBufSize
, pcbBytesNeeded
);
4522 return ERROR_INVALID_ADDRESS
;
4525 return ERROR_SHUTDOWN_IN_PROGRESS
;
4527 hSvc
= ScmGetServiceFromHandle(hService
);
4530 DPRINT1("Invalid service handle!\n");
4531 return ERROR_INVALID_HANDLE
;
4534 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4535 SERVICE_QUERY_CONFIG
))
4537 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4538 return ERROR_ACCESS_DENIED
;
4541 lpService
= hSvc
->ServiceEntry
;
4542 if (lpService
== NULL
)
4544 DPRINT("lpService == NULL!\n");
4545 return ERROR_INVALID_HANDLE
;
4548 /* FIXME: Lock the service database shared */
4550 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4553 if (dwError
!= ERROR_SUCCESS
)
4556 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4558 LPSERVICE_DESCRIPTIONA lpServiceDescription
= (LPSERVICE_DESCRIPTIONA
)lpBuffer
;
4561 *pcbBytesNeeded
= sizeof(SERVICE_DESCRIPTIONA
);
4563 dwError
= ScmReadString(hServiceKey
,
4566 if (dwError
== ERROR_SUCCESS
)
4568 *pcbBytesNeeded
+= ((wcslen(lpDescriptionW
) + 1) * sizeof(WCHAR
));
4571 if (cbBufSize
>= *pcbBytesNeeded
)
4574 if (dwError
== ERROR_SUCCESS
)
4576 lpStr
= (LPSTR
)(lpServiceDescription
+ 1);
4578 WideCharToMultiByte(CP_ACP
,
4583 wcslen(lpDescriptionW
),
4586 lpServiceDescription
->lpDescription
= (LPSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4590 lpServiceDescription
->lpDescription
= NULL
;
4596 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4600 else if (dwInfoLevel
& SERVICE_CONFIG_FAILURE_ACTIONS
)
4603 dwError
= ERROR_CALL_NOT_IMPLEMENTED
;
4608 if (lpDescription
!= NULL
)
4609 HeapFree(GetProcessHeap(), 0, lpDescription
);
4611 if (hServiceKey
!= NULL
)
4612 RegCloseKey(hServiceKey
);
4614 /* FIXME: Unlock database */
4616 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4623 DWORD
RQueryServiceConfig2W(
4624 SC_RPC_HANDLE hService
,
4628 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4630 DWORD dwError
= ERROR_SUCCESS
;
4631 PSERVICE_HANDLE hSvc
;
4632 PSERVICE lpService
= NULL
;
4633 HKEY hServiceKey
= NULL
;
4634 DWORD dwRequiredSize
;
4635 LPWSTR lpDescription
= NULL
;
4636 LPWSTR lpFailureCommand
= NULL
;
4637 LPWSTR lpRebootMessage
= NULL
;
4639 DPRINT("RQueryServiceConfig2W() called\n");
4642 return ERROR_INVALID_ADDRESS
;
4645 return ERROR_SHUTDOWN_IN_PROGRESS
;
4647 hSvc
= ScmGetServiceFromHandle(hService
);
4650 DPRINT1("Invalid service handle!\n");
4651 return ERROR_INVALID_HANDLE
;
4654 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4655 SERVICE_QUERY_CONFIG
))
4657 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4658 return ERROR_ACCESS_DENIED
;
4661 lpService
= hSvc
->ServiceEntry
;
4662 if (lpService
== NULL
)
4664 DPRINT("lpService == NULL!\n");
4665 return ERROR_INVALID_HANDLE
;
4668 /* FIXME: Lock the service database shared */
4670 dwError
= ScmOpenServiceKey(lpService
->lpServiceName
,
4673 if (dwError
!= ERROR_SUCCESS
)
4676 if (dwInfoLevel
== SERVICE_CONFIG_DESCRIPTION
)
4678 LPSERVICE_DESCRIPTIONW lpServiceDescription
= (LPSERVICE_DESCRIPTIONW
)lpBuffer
;
4681 dwError
= ScmReadString(hServiceKey
,
4684 if (dwError
!= ERROR_SUCCESS
)
4687 dwRequiredSize
= sizeof(SERVICE_DESCRIPTIONW
) + ((wcslen(lpDescription
) + 1) * sizeof(WCHAR
));
4689 if (cbBufSize
< dwRequiredSize
)
4691 *pcbBytesNeeded
= dwRequiredSize
;
4692 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4696 lpStr
= (LPWSTR
)(lpServiceDescription
+ 1);
4697 wcscpy(lpStr
, lpDescription
);
4698 lpServiceDescription
->lpDescription
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpServiceDescription
);
4700 else if (dwInfoLevel
== SERVICE_CONFIG_FAILURE_ACTIONS
)
4703 LPSERVICE_FAILURE_ACTIONSW lpFailureActions
= (LPSERVICE_FAILURE_ACTIONSW
)lpBuffer
;
4707 dwError
= ScmReadString(hServiceKey
,
4711 dwError
= ScmReadString(hServiceKey
,
4715 dwRequiredSize
= sizeof(SERVICE_FAILURE_ACTIONSW
);
4717 if (lpFailureCommand
)
4718 dwRequiredSize
+= (wcslen(lpFailureCommand
) + 1) * sizeof(WCHAR
);
4720 if (lpRebootMessage
)
4721 dwRequiredSize
+= (wcslen(lpRebootMessage
) + 1) * sizeof(WCHAR
);
4723 if (cbBufSize
< dwRequiredSize
)
4725 *pcbBytesNeeded
= dwRequiredSize
;
4726 dwError
= ERROR_INSUFFICIENT_BUFFER
;
4730 lpFailureActions
->cActions
= 0;
4731 lpFailureActions
->dwResetPeriod
= 0;
4732 lpFailureActions
->lpCommand
= NULL
;
4733 lpFailureActions
->lpRebootMsg
= NULL
;
4734 lpFailureActions
->lpsaActions
= NULL
;
4736 lpStr
= (LPWSTR
)(lpFailureActions
+ 1);
4737 if (lpRebootMessage
)
4739 wcscpy(lpStr
, lpRebootMessage
);
4740 lpFailureActions
->lpRebootMsg
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpRebootMessage
);
4741 lpStr
+= wcslen(lpRebootMessage
) + 1;
4744 if (lpFailureCommand
)
4746 wcscpy(lpStr
, lpFailureCommand
);
4747 lpFailureActions
->lpCommand
= (LPWSTR
)((ULONG_PTR
)lpStr
- (ULONG_PTR
)lpFailureCommand
);
4748 lpStr
+= wcslen(lpRebootMessage
) + 1;
4750 dwError
= STATUS_SUCCESS
;
4755 if (lpDescription
!= NULL
)
4756 HeapFree(GetProcessHeap(), 0, lpDescription
);
4758 if (lpRebootMessage
!= NULL
)
4759 HeapFree(GetProcessHeap(), 0, lpRebootMessage
);
4761 if (lpFailureCommand
!= NULL
)
4762 HeapFree(GetProcessHeap(), 0, lpFailureCommand
);
4764 if (hServiceKey
!= NULL
)
4765 RegCloseKey(hServiceKey
);
4767 /* FIXME: Unlock database */
4769 DPRINT("RQueryServiceConfig2W() done (Error %lu)\n", dwError
);
4776 DWORD
RQueryServiceStatusEx(
4777 SC_RPC_HANDLE hService
,
4778 SC_STATUS_TYPE InfoLevel
,
4781 LPBOUNDED_DWORD_8K pcbBytesNeeded
)
4783 LPSERVICE_STATUS_PROCESS lpStatus
;
4784 PSERVICE_HANDLE hSvc
;
4787 DPRINT("RQueryServiceStatusEx() called\n");
4790 return ERROR_SHUTDOWN_IN_PROGRESS
;
4792 if (InfoLevel
!= SC_STATUS_PROCESS_INFO
)
4793 return ERROR_INVALID_LEVEL
;
4795 *pcbBytesNeeded
= sizeof(SERVICE_STATUS_PROCESS
);
4797 if (cbBufSize
< sizeof(SERVICE_STATUS_PROCESS
))
4798 return ERROR_INSUFFICIENT_BUFFER
;
4800 hSvc
= ScmGetServiceFromHandle(hService
);
4803 DPRINT1("Invalid service handle!\n");
4804 return ERROR_INVALID_HANDLE
;
4807 if (!RtlAreAllAccessesGranted(hSvc
->Handle
.DesiredAccess
,
4808 SERVICE_QUERY_STATUS
))
4810 DPRINT("Insufficient access rights! 0x%lx\n", hSvc
->Handle
.DesiredAccess
);
4811 return ERROR_ACCESS_DENIED
;
4814 lpService
= hSvc
->ServiceEntry
;
4815 if (lpService
== NULL
)
4817 DPRINT("lpService == NULL!\n");
4818 return ERROR_INVALID_HANDLE
;
4821 lpStatus
= (LPSERVICE_STATUS_PROCESS
)lpBuffer
;
4823 /* Return service status information */
4824 RtlCopyMemory(lpStatus
,
4826 sizeof(SERVICE_STATUS
));
4828 lpStatus
->dwProcessId
= lpService
->ProcessId
; /* FIXME */
4829 lpStatus
->dwServiceFlags
= 0; /* FIXME */
4831 return ERROR_SUCCESS
;
4836 DWORD
REnumServicesStatusExA(
4837 SC_RPC_HANDLE hSCManager
,
4838 SC_ENUM_TYPE InfoLevel
,
4839 DWORD dwServiceType
,
4840 DWORD dwServiceState
,
4843 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4844 LPBOUNDED_DWORD_256K lpServicesReturned
,
4845 LPBOUNDED_DWORD_256K lpResumeIndex
,
4846 LPCSTR pszGroupName
)
4848 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtrW
= NULL
;
4849 LPENUM_SERVICE_STATUS_PROCESSA lpStatusPtrA
= NULL
;
4850 LPWSTR lpStringPtrW
;
4852 LPWSTR pszGroupNameW
= NULL
;
4854 DWORD dwServiceCount
;
4856 DPRINT("REnumServicesStatusExA() called\n");
4860 pszGroupNameW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, (strlen(pszGroupName
) + 1) * sizeof(WCHAR
));
4863 DPRINT("Failed to allocate buffer!\n");
4864 return ERROR_NOT_ENOUGH_MEMORY
;
4867 MultiByteToWideChar(CP_ACP
,
4872 strlen(pszGroupName
) + 1);
4875 if ((cbBufSize
> 0) && (lpBuffer
))
4877 lpStatusPtrW
= HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, cbBufSize
);
4880 DPRINT("Failed to allocate buffer!\n");
4881 return ERROR_NOT_ENOUGH_MEMORY
;
4885 dwError
= REnumServicesStatusExW(hSCManager
,
4889 (LPBYTE
)lpStatusPtrW
,
4896 /* if no services were returned then we are Done */
4897 if (*lpServicesReturned
== 0)
4900 lpStatusPtrA
= (LPENUM_SERVICE_STATUS_PROCESSA
)lpBuffer
;
4901 lpStringPtrA
= (LPSTR
)((ULONG_PTR
)lpBuffer
+
4902 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSA
));
4903 lpStringPtrW
= (LPWSTR
)((ULONG_PTR
)lpStatusPtrW
+
4904 *lpServicesReturned
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
4906 for (dwServiceCount
= 0; dwServiceCount
< *lpServicesReturned
; dwServiceCount
++)
4908 /* Copy the service name */
4909 WideCharToMultiByte(CP_ACP
,
4914 wcslen(lpStringPtrW
),
4918 lpStatusPtrA
->lpServiceName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4919 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4920 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4922 /* Copy the display name */
4923 WideCharToMultiByte(CP_ACP
,
4928 wcslen(lpStringPtrW
),
4932 lpStatusPtrA
->lpDisplayName
= (LPSTR
)((ULONG_PTR
)lpStringPtrA
- (ULONG_PTR
)lpBuffer
);
4933 lpStringPtrA
+= wcslen(lpStringPtrW
) + 1;
4934 lpStringPtrW
+= wcslen(lpStringPtrW
) + 1;
4936 /* Copy the status information */
4937 memcpy(&lpStatusPtrA
->ServiceStatusProcess
,
4938 &lpStatusPtrW
->ServiceStatusProcess
,
4939 sizeof(SERVICE_STATUS
));
4941 lpStatusPtrA
->ServiceStatusProcess
.dwProcessId
= lpStatusPtrW
->ServiceStatusProcess
.dwProcessId
; /* FIXME */
4942 lpStatusPtrA
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
4948 HeapFree(GetProcessHeap(), 0, pszGroupNameW
);
4951 HeapFree(GetProcessHeap(), 0, lpStatusPtrW
);
4953 DPRINT("REnumServicesStatusExA() done (Error %lu)\n", dwError
);
4960 DWORD
REnumServicesStatusExW(
4961 SC_RPC_HANDLE hSCManager
,
4962 SC_ENUM_TYPE InfoLevel
,
4963 DWORD dwServiceType
,
4964 DWORD dwServiceState
,
4967 LPBOUNDED_DWORD_256K pcbBytesNeeded
,
4968 LPBOUNDED_DWORD_256K lpServicesReturned
,
4969 LPBOUNDED_DWORD_256K lpResumeIndex
,
4970 LPCWSTR pszGroupName
)
4972 PMANAGER_HANDLE hManager
;
4974 DWORD dwError
= ERROR_SUCCESS
;
4975 PLIST_ENTRY ServiceEntry
;
4976 PSERVICE CurrentService
;
4978 DWORD dwRequiredSize
;
4979 DWORD dwServiceCount
;
4981 DWORD dwLastResumeCount
= 0;
4982 LPENUM_SERVICE_STATUS_PROCESSW lpStatusPtr
;
4985 DPRINT("REnumServicesStatusExW() called\n");
4988 return ERROR_SHUTDOWN_IN_PROGRESS
;
4990 if (InfoLevel
!= SC_ENUM_PROCESS_INFO
)
4991 return ERROR_INVALID_LEVEL
;
4993 hManager
= ScmGetServiceManagerFromHandle(hSCManager
);
4994 if (hManager
== NULL
)
4996 DPRINT1("Invalid service manager handle!\n");
4997 return ERROR_INVALID_HANDLE
;
5000 *pcbBytesNeeded
= 0;
5001 *lpServicesReturned
= 0;
5003 if ((dwServiceType
!=SERVICE_DRIVER
) && (dwServiceType
!=SERVICE_WIN32
))
5005 DPRINT("Not a valid Service Type!\n");
5006 return ERROR_INVALID_PARAMETER
;
5009 if ((dwServiceState
<SERVICE_ACTIVE
) || (dwServiceState
>SERVICE_STATE_ALL
))
5011 DPRINT("Not a valid Service State!\n");
5012 return ERROR_INVALID_PARAMETER
;
5015 /* Check access rights */
5016 if (!RtlAreAllAccessesGranted(hManager
->Handle
.DesiredAccess
,
5017 SC_MANAGER_ENUMERATE_SERVICE
))
5019 DPRINT("Insufficient access rights! 0x%lx\n",
5020 hManager
->Handle
.DesiredAccess
);
5021 return ERROR_ACCESS_DENIED
;
5024 if (lpResumeIndex
) dwLastResumeCount
= *lpResumeIndex
;
5026 /* Lock the service list shared */
5028 lpService
= ScmGetServiceEntryByResumeCount(dwLastResumeCount
);
5029 if (lpService
== NULL
)
5031 dwError
= ERROR_SUCCESS
;
5038 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5039 ServiceEntry
!= &ServiceListHead
;
5040 ServiceEntry
= ServiceEntry
->Flink
)
5042 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5046 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5049 dwState
= SERVICE_ACTIVE
;
5050 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5051 dwState
= SERVICE_INACTIVE
;
5053 if ((dwState
& dwServiceState
) == 0)
5058 if (*pszGroupName
== 0)
5060 if (CurrentService
->lpGroup
!= NULL
)
5065 if ((CurrentService
->lpGroup
== NULL
) ||
5066 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5071 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5072 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5073 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5075 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5077 DPRINT("Service name: %S fit\n", CurrentService
->lpServiceName
);
5078 dwRequiredSize
+= dwSize
;
5080 dwLastResumeCount
= CurrentService
->dwResumeCount
;
5084 DPRINT("Service name: %S no fit\n", CurrentService
->lpServiceName
);
5090 DPRINT("dwRequiredSize: %lu\n", dwRequiredSize
);
5091 DPRINT("dwServiceCount: %lu\n", dwServiceCount
);
5094 ServiceEntry
!= &ServiceListHead
;
5095 ServiceEntry
= ServiceEntry
->Flink
)
5097 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5101 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5104 dwState
= SERVICE_ACTIVE
;
5105 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5106 dwState
= SERVICE_INACTIVE
;
5108 if ((dwState
& dwServiceState
) == 0)
5113 if (*pszGroupName
== 0)
5115 if (CurrentService
->lpGroup
!= NULL
)
5120 if ((CurrentService
->lpGroup
== NULL
) ||
5121 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5126 dwRequiredSize
+= (sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5127 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5128 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
)));
5130 dwError
= ERROR_MORE_DATA
;
5133 DPRINT("*pcbBytesNeeded: %lu\n", dwRequiredSize
);
5136 *lpResumeIndex
= dwLastResumeCount
;
5138 *lpServicesReturned
= dwServiceCount
;
5139 *pcbBytesNeeded
= dwRequiredSize
;
5141 /* If there was no services that matched */
5142 if ((!dwServiceCount
) && (dwError
!= ERROR_MORE_DATA
))
5144 dwError
= ERROR_SERVICE_DOES_NOT_EXIST
;
5148 lpStatusPtr
= (LPENUM_SERVICE_STATUS_PROCESSW
)lpBuffer
;
5149 lpStringPtr
= (LPWSTR
)((ULONG_PTR
)lpBuffer
+
5150 dwServiceCount
* sizeof(ENUM_SERVICE_STATUS_PROCESSW
));
5153 for (ServiceEntry
= &lpService
->ServiceListEntry
;
5154 ServiceEntry
!= &ServiceListHead
;
5155 ServiceEntry
= ServiceEntry
->Flink
)
5157 CurrentService
= CONTAINING_RECORD(ServiceEntry
,
5161 if ((CurrentService
->Status
.dwServiceType
& dwServiceType
) == 0)
5164 dwState
= SERVICE_ACTIVE
;
5165 if (CurrentService
->Status
.dwCurrentState
== SERVICE_STOPPED
)
5166 dwState
= SERVICE_INACTIVE
;
5168 if ((dwState
& dwServiceState
) == 0)
5173 if (*pszGroupName
== 0)
5175 if (CurrentService
->lpGroup
!= NULL
)
5180 if ((CurrentService
->lpGroup
== NULL
) ||
5181 _wcsicmp(pszGroupName
, CurrentService
->lpGroup
->lpGroupName
))
5186 dwSize
= sizeof(ENUM_SERVICE_STATUS_PROCESSW
) +
5187 ((wcslen(CurrentService
->lpServiceName
) + 1) * sizeof(WCHAR
)) +
5188 ((wcslen(CurrentService
->lpDisplayName
) + 1) * sizeof(WCHAR
));
5190 if (dwRequiredSize
+ dwSize
<= cbBufSize
)
5192 /* Copy the service name */
5194 CurrentService
->lpServiceName
);
5195 lpStatusPtr
->lpServiceName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5196 lpStringPtr
+= (wcslen(CurrentService
->lpServiceName
) + 1);
5198 /* Copy the display name */
5200 CurrentService
->lpDisplayName
);
5201 lpStatusPtr
->lpDisplayName
= (LPWSTR
)((ULONG_PTR
)lpStringPtr
- (ULONG_PTR
)lpBuffer
);
5202 lpStringPtr
+= (wcslen(CurrentService
->lpDisplayName
) + 1);
5204 /* Copy the status information */
5205 memcpy(&lpStatusPtr
->ServiceStatusProcess
,
5206 &CurrentService
->Status
,
5207 sizeof(SERVICE_STATUS
));
5208 lpStatusPtr
->ServiceStatusProcess
.dwProcessId
= CurrentService
->ProcessId
; /* FIXME */
5209 lpStatusPtr
->ServiceStatusProcess
.dwServiceFlags
= 0; /* FIXME */
5212 dwRequiredSize
+= dwSize
;
5222 *pcbBytesNeeded
= 0;
5228 /* Unlock the service list */
5230 DPRINT("REnumServicesStatusExW() done (Error %lu)\n", dwError
);
5237 DWORD
RSendTSMessage(
5238 handle_t BindingHandle
) /* FIXME */
5241 return ERROR_CALL_NOT_IMPLEMENTED
;
5246 DWORD
RCreateServiceWOW64A(
5247 handle_t BindingHandle
,
5248 LPSTR lpServiceName
,
5249 LPSTR lpDisplayName
,
5250 DWORD dwDesiredAccess
,
5251 DWORD dwServiceType
,
5253 DWORD dwErrorControl
,
5254 LPSTR lpBinaryPathName
,
5255 LPSTR lpLoadOrderGroup
,
5257 LPBYTE lpDependencies
,
5259 LPSTR lpServiceStartName
,
5262 LPSC_RPC_HANDLE lpServiceHandle
)
5265 return ERROR_CALL_NOT_IMPLEMENTED
;
5270 DWORD
RCreateServiceWOW64W(
5271 handle_t BindingHandle
,
5272 LPWSTR lpServiceName
,
5273 LPWSTR lpDisplayName
,
5274 DWORD dwDesiredAccess
,
5275 DWORD dwServiceType
,
5277 DWORD dwErrorControl
,
5278 LPWSTR lpBinaryPathName
,
5279 LPWSTR lpLoadOrderGroup
,
5281 LPBYTE lpDependencies
,
5283 LPWSTR lpServiceStartName
,
5286 LPSC_RPC_HANDLE lpServiceHandle
)
5289 return ERROR_CALL_NOT_IMPLEMENTED
;
5294 DWORD
RQueryServiceTagInfo(
5295 handle_t BindingHandle
) /* FIXME */
5298 return ERROR_CALL_NOT_IMPLEMENTED
;
5303 DWORD
RNotifyServiceStatusChange(
5304 SC_RPC_HANDLE hService
,
5305 SC_RPC_NOTIFY_PARAMS NotifyParams
,
5306 GUID
*pClientProcessGuid
,
5307 GUID
*pSCMProcessGuid
,
5308 PBOOL pfCreateRemoteQueue
,
5309 LPSC_NOTIFY_RPC_HANDLE phNotify
)
5312 return ERROR_CALL_NOT_IMPLEMENTED
;
5317 DWORD
RGetNotifyResults(
5318 SC_NOTIFY_RPC_HANDLE hNotify
,
5319 PSC_RPC_NOTIFY_PARAMS_LIST
*ppNotifyParams
)
5322 return ERROR_CALL_NOT_IMPLEMENTED
;
5327 DWORD
RCloseNotifyHandle(
5328 LPSC_NOTIFY_RPC_HANDLE phNotify
,
5332 return ERROR_CALL_NOT_IMPLEMENTED
;
5337 DWORD
RControlServiceExA(
5338 SC_RPC_HANDLE hService
,
5343 return ERROR_CALL_NOT_IMPLEMENTED
;
5348 DWORD
RControlServiceExW(
5349 SC_RPC_HANDLE hService
,
5354 return ERROR_CALL_NOT_IMPLEMENTED
;
5359 DWORD
RSendPnPMessage(
5360 handle_t BindingHandle
) /* FIXME */
5363 return ERROR_CALL_NOT_IMPLEMENTED
;
5368 DWORD
RValidatePnPService(
5369 handle_t BindingHandle
) /* FIXME */
5372 return ERROR_CALL_NOT_IMPLEMENTED
;
5377 DWORD
ROpenServiceStatusHandle(
5378 handle_t BindingHandle
) /* FIXME */
5381 return ERROR_CALL_NOT_IMPLEMENTED
;
5387 handle_t BindingHandle
) /* FIXME */
5390 return ERROR_CALL_NOT_IMPLEMENTED
;
5394 void __RPC_FAR
* __RPC_USER
midl_user_allocate(SIZE_T len
)
5396 return HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY
, len
);
5400 void __RPC_USER
midl_user_free(void __RPC_FAR
* ptr
)
5402 HeapFree(GetProcessHeap(), 0, ptr
);
5406 void __RPC_USER
SC_RPC_HANDLE_rundown(SC_RPC_HANDLE hSCObject
)
5411 void __RPC_USER
SC_RPC_LOCK_rundown(SC_RPC_LOCK Lock
)
5416 void __RPC_USER
SC_NOTIFY_RPC_HANDLE_rundown(SC_NOTIFY_RPC_HANDLE hNotify
)