https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9d91a2e8cea8b17fdf641…
commit 9d91a2e8cea8b17fdf64171724ed07fda4546aab
Author: Pierre Schweitzer <pierre(a)reactos.org>
AuthorDate: Fri Dec 8 22:45:04 2017 +0100
[SERVICES] Fix querying the status of a registered but not started driver.
The current implementation was broken and some dead code was never called; always
failing before.
This fix revives this dead code!
Extra fix: avoid derefencing potential null-ptr.
And also, as bonus, comment the function so that logic can be easily understood.
CORE-14062
---
base/system/services/driver.c | 28 ++++++++++++++++++++++++++--
1 file changed, 26 insertions(+), 2 deletions(-)
diff --git a/base/system/services/driver.c b/base/system/services/driver.c
index 34be894659..4248ac95c9 100644
--- a/base/system/services/driver.c
+++ b/base/system/services/driver.c
@@ -140,8 +140,13 @@ ScmGetDriverStatus(PSERVICE lpService,
DPRINT1("ScmGetDriverStatus() called\n");
- memset(lpServiceStatus, 0, sizeof(SERVICE_STATUS));
+ /* Zero output buffer if any */
+ if (lpServiceStatus != NULL)
+ {
+ memset(lpServiceStatus, 0, sizeof(SERVICE_STATUS));
+ }
+ /* Select the appropriate object directory based on driver type */
if (lpService->Status.dwServiceType == SERVICE_KERNEL_DRIVER)
{
RtlInitUnicodeString(&DirName, L"\\Driver");
@@ -158,6 +163,7 @@ ScmGetDriverStatus(PSERVICE lpService,
NULL,
NULL);
+ /* Open the object directory where loaded drivers are */
Status = NtOpenDirectoryObject(&DirHandle,
DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
&ObjectAttributes);
@@ -167,12 +173,14 @@ ScmGetDriverStatus(PSERVICE lpService,
return RtlNtStatusToDosError(Status);
}
+ /* Allocate a buffer big enough for querying the object */
BufferLength = sizeof(OBJECT_DIRECTORY_INFORMATION) +
2 * MAX_PATH * sizeof(WCHAR);
DirInfo = (OBJECT_DIRECTORY_INFORMATION*) HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
BufferLength);
+ /* Now, start browsing entry by entry */
Index = 0;
while (TRUE)
{
@@ -183,19 +191,23 @@ ScmGetDriverStatus(PSERVICE lpService,
FALSE,
&Index,
&DataLength);
+ /* End of enumeration, the driver was not found */
if (Status == STATUS_NO_MORE_ENTRIES)
{
DPRINT("No more services\n");
break;
}
+ /* Other error, fail */
if (!NT_SUCCESS(Status))
break;
DPRINT("Comparing: '%S' '%wZ'\n",
lpService->lpServiceName, &DirInfo->Name);
+ /* Compare names to check whether it matches our driver */
if (_wcsicmp(lpService->lpServiceName, DirInfo->Name.Buffer) == 0)
{
+ /* That's our driver, bail out! */
DPRINT1("Found: '%S' '%wZ'\n",
lpService->lpServiceName, &DirInfo->Name);
bFound = TRUE;
@@ -204,17 +216,27 @@ ScmGetDriverStatus(PSERVICE lpService,
}
}
+ /* Release resources we don't need */
HeapFree(GetProcessHeap(),
0,
DirInfo);
NtClose(DirHandle);
- if (!NT_SUCCESS(Status))
+ /* Only quit if there's a failure
+ * Not having found the driver is legit!
+ * It means the driver was registered as a service, but not loaded
+ * We have not to fail in that situation, but to return proper status
+ */
+ if (!NT_SUCCESS(Status) && Status != STATUS_NO_MORE_ENTRIES)
{
DPRINT1("Status: %lx\n", Status);
return RtlNtStatusToDosError(Status);
}
+ /* Now, we have two cases:
+ * 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))
{
@@ -235,6 +257,7 @@ ScmGetDriverStatus(PSERVICE lpService,
lpService->Status.dwWin32ExitCode = ERROR_SUCCESS;
}
}
+ /* Not found, return it's stopped */
else
{
lpService->Status.dwCurrentState = SERVICE_STOPPED;
@@ -248,6 +271,7 @@ ScmGetDriverStatus(PSERVICE lpService,
lpService->Status.dwWin32ExitCode = ERROR_GEN_FAILURE;
}
+ /* Copy service status if required */
if (lpServiceStatus != NULL)
{
memcpy(lpServiceStatus,