https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a8d256bf23cefe9e8d163…
commit a8d256bf23cefe9e8d163e1a6522928e63796a16
Author: Eric Kohl <eric.kohl(a)reactos.org>
AuthorDate: Sun Feb 18 18:47:42 2018 +0100
Commit: Eric Kohl <eric.kohl(a)reactos.org>
CommitDate: Mon Feb 19 00:14:58 2018 +0100
[SERVICES] Update a drivers status properly
- ScmUnloadDriver: Handle failed unload properly.
- ScmGetDriverStatus: A driver is running when its driver object was found. Otherwise
it has been stopped.
- ScmControlDriver: Check a drivers status before and after unloading.
CORE-14317
---
base/system/services/driver.c | 91 +++++++++++++++++++++++++++++--------------
1 file changed, 61 insertions(+), 30 deletions(-)
diff --git a/base/system/services/driver.c b/base/system/services/driver.c
index 819183e5c0..2293acd053 100644
--- a/base/system/services/driver.c
+++ b/base/system/services/driver.c
@@ -71,6 +71,7 @@ done:
return RtlNtStatusToDosError(Status);
}
+
static
DWORD
ScmUnloadDriver(PSERVICE lpService)
@@ -79,6 +80,7 @@ ScmUnloadDriver(PSERVICE lpService)
BOOLEAN WasPrivilegeEnabled = FALSE;
PWSTR pszDriverPath;
UNICODE_STRING DriverPath;
+ DWORD dwError;
/* Build the driver path */
/* 52 =
wcslen(L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\") */
@@ -107,10 +109,15 @@ ScmUnloadDriver(PSERVICE lpService)
{
/* We encountered a failure, exit properly */
DPRINT1("SERVICES: Cannot acquire driver-unloading privilege, Status =
0x%08lx\n", Status);
+ dwError = RtlNtStatusToDosError(Status);
goto done;
}
Status = NtUnloadDriver(&DriverPath);
+ if (Status == STATUS_INVALID_DEVICE_REQUEST)
+ dwError = ERROR_INVALID_SERVICE_CONTROL;
+ else
+ dwError = RtlNtStatusToDosError(Status);
/* Release driver-unloading privilege */
RtlAdjustPrivilege(SE_LOAD_DRIVER_PRIVILEGE,
@@ -120,7 +127,7 @@ ScmUnloadDriver(PSERVICE lpService)
done:
HeapFree(GetProcessHeap(), 0, pszDriverPath);
- return RtlNtStatusToDosError(Status);
+ return dwError;
}
@@ -139,6 +146,7 @@ ScmGetDriverStatus(PSERVICE lpService,
ULONG Index;
DWORD dwError = ERROR_SUCCESS;
BOOLEAN bFound = FALSE;
+ DWORD dwPreviousState;
DPRINT1("ScmGetDriverStatus() called\n");
@@ -239,46 +247,61 @@ ScmGetDriverStatus(PSERVICE lpService,
* We found the driver: it means it's running
* We didn't find the driver: it wasn't running
*/
- if ((bFound != FALSE) &&
- (lpService->Status.dwCurrentState != SERVICE_STOP_PENDING))
+ if (bFound)
{
- if (lpService->Status.dwCurrentState == SERVICE_STOPPED)
+ /* Found, return it's running */
+
+ dwPreviousState = lpService->Status.dwCurrentState;
+
+ /* It is running */
+ lpService->Status.dwCurrentState = SERVICE_RUNNING;
+
+ if (dwPreviousState == SERVICE_STOPPED)
{
+ /* Make it run if it was stopped before */
lpService->Status.dwWin32ExitCode = ERROR_SUCCESS;
lpService->Status.dwServiceSpecificExitCode = ERROR_SUCCESS;
+ lpService->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
lpService->Status.dwCheckPoint = 0;
lpService->Status.dwWaitHint = 0;
- lpService->Status.dwControlsAccepted = 0;
}
- else
- {
- lpService->Status.dwCurrentState = SERVICE_RUNNING;
- lpService->Status.dwControlsAccepted = SERVICE_ACCEPT_STOP;
- if (lpService->Status.dwWin32ExitCode == ERROR_SERVICE_NEVER_STARTED)
- lpService->Status.dwWin32ExitCode = ERROR_SUCCESS;
- }
+ if (lpService->Status.dwWin32ExitCode == ERROR_SERVICE_NEVER_STARTED)
+ lpService->Status.dwWin32ExitCode = ERROR_SUCCESS;
}
- /* Not found, return it's stopped */
else
{
- lpService->Status.dwCurrentState = SERVICE_STOPPED;
- lpService->Status.dwControlsAccepted = 0;
- lpService->Status.dwCheckPoint = 0;
- lpService->Status.dwWaitHint = 0;
+ /* Not found, return it's stopped */
if (lpService->Status.dwCurrentState == SERVICE_STOP_PENDING)
+ {
+ /* Stopped successfully */
lpService->Status.dwWin32ExitCode = ERROR_SUCCESS;
+ lpService->Status.dwCurrentState = SERVICE_STOPPED;
+ lpService->Status.dwControlsAccepted = 0;
+ lpService->Status.dwCheckPoint = 0;
+ lpService->Status.dwWaitHint = 0;
+ }
+ else if (lpService->Status.dwCurrentState == SERVICE_STOPPED)
+ {
+ /* Don't change the current status */
+ }
else
+ {
lpService->Status.dwWin32ExitCode = ERROR_GEN_FAILURE;
+ lpService->Status.dwCurrentState = SERVICE_STOPPED;
+ lpService->Status.dwControlsAccepted = 0;
+ lpService->Status.dwCheckPoint = 0;
+ lpService->Status.dwWaitHint = 0;
+ }
}
/* Copy service status if required */
if (lpServiceStatus != NULL)
{
- memcpy(lpServiceStatus,
- &lpService->Status,
- sizeof(SERVICE_STATUS));
+ RtlCopyMemory(lpServiceStatus,
+ &lpService->Status,
+ sizeof(SERVICE_STATUS));
}
DPRINT1("ScmGetDriverStatus() done (Error: %lu)\n", dwError);
@@ -320,26 +343,34 @@ ScmControlDriver(PSERVICE lpService,
switch (dwControl)
{
case SERVICE_CONTROL_STOP:
+ /* Check the drivers status */
+ dwError = ScmGetDriverStatus(lpService,
+ lpServiceStatus);
+ if (dwError != ERROR_SUCCESS)
+ goto done;
+
+ /* Fail, if it is not running */
if (lpService->Status.dwCurrentState != SERVICE_RUNNING)
{
dwError = ERROR_INVALID_SERVICE_CONTROL;
goto done;
}
+ /* Unload the driver */
dwError = ScmUnloadDriver(lpService);
- if (dwError == ERROR_SUCCESS)
+ if (dwError == ERROR_INVALID_SERVICE_CONTROL)
{
- lpService->Status.dwCurrentState = SERVICE_STOPPED;
+ /* The driver cannot be stopped, mark it non-stoppable */
lpService->Status.dwControlsAccepted = 0;
- lpService->Status.dwWin32ExitCode = ERROR_SUCCESS;
-
- if (lpServiceStatus != NULL)
- {
- RtlCopyMemory(lpServiceStatus,
- &lpService->Status,
- sizeof(SERVICE_STATUS));
- }
+ goto done;
}
+
+ /* Make the driver 'stop pending' */
+ lpService->Status.dwCurrentState = SERVICE_STOP_PENDING;
+
+ /* Check the drivers status again */
+ dwError = ScmGetDriverStatus(lpService,
+ lpServiceStatus);
break;
case SERVICE_CONTROL_INTERROGATE: