https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a6a3aa0f0dbbc9901a9d7…
commit a6a3aa0f0dbbc9901a9d74da419800bf8c064620
Author: Victor Perevertkin <victor.perevertkin(a)reactos.org>
AuthorDate: Fri Nov 20 18:51:33 2020 +0300
Commit: Victor Perevertkin <victor.perevertkin(a)reactos.org>
CommitDate: Mon Jan 4 16:50:32 2021 +0300
[NTOS:IO] Refactor IopLoadUnloadDriver
- Split IopLoadUnloadDriver into IopLoadDriver and calling DriverUnload
- Schedule the worker for (un)loading driver in a separate routine
(IopDoLoadUnloadDriver) this allows IopLoadDriver to be called
separately (if we are sure that we're in the system process)
---
ntoskrnl/include/internal/io.h | 15 +----
ntoskrnl/io/iomgr/driver.c | 144 +++++++++++++++++++++++++++--------------
2 files changed, 96 insertions(+), 63 deletions(-)
diff --git a/ntoskrnl/include/internal/io.h b/ntoskrnl/include/internal/io.h
index 47d587d413c..5da5950ba67 100644
--- a/ntoskrnl/include/internal/io.h
+++ b/ntoskrnl/include/internal/io.h
@@ -391,18 +391,6 @@ typedef struct _OPEN_PACKET
PDEVICE_OBJECT TopDeviceObjectHint;
} OPEN_PACKET, *POPEN_PACKET;
-//
-// Parameters packet for Load/Unload work item's context
-//
-typedef struct _LOAD_UNLOAD_PARAMS
-{
- NTSTATUS Status;
- PCUNICODE_STRING RegistryPath;
- WORK_QUEUE_ITEM WorkItem;
- KEVENT Event;
- PDRIVER_OBJECT DriverObject;
-} LOAD_UNLOAD_PARAMS, *PLOAD_UNLOAD_PARAMS;
-
//
// Boot Driver List Entry
//
@@ -1138,8 +1126,7 @@ IopLoadServiceModule(
);
NTSTATUS
-NTAPI
-IopLoadUnloadDriver(
+IopLoadDriver(
_In_opt_ PCUNICODE_STRING RegistryPath,
_Inout_ PDRIVER_OBJECT *DriverObject
);
diff --git a/ntoskrnl/io/iomgr/driver.c b/ntoskrnl/io/iomgr/driver.c
index 0451064f6bc..a4b39b77f6d 100644
--- a/ntoskrnl/io/iomgr/driver.c
+++ b/ntoskrnl/io/iomgr/driver.c
@@ -41,6 +41,24 @@ extern KEVENT PiEnumerationFinished;
USHORT IopGroupIndex;
PLIST_ENTRY IopGroupTable;
+/* TYPES *********************************************************************/
+
+// Parameters packet for Load/Unload work item's context
+typedef struct _LOAD_UNLOAD_PARAMS
+{
+ NTSTATUS Status;
+ PCUNICODE_STRING RegistryPath;
+ WORK_QUEUE_ITEM WorkItem;
+ KEVENT Event;
+ PDRIVER_OBJECT DriverObject;
+ BOOLEAN SetEvent;
+} LOAD_UNLOAD_PARAMS, *PLOAD_UNLOAD_PARAMS;
+
+NTSTATUS
+IopDoLoadUnloadDriver(
+ _In_opt_ PCUNICODE_STRING RegistryPath,
+ _Inout_ PDRIVER_OBJECT *DriverObject);
+
/* PRIVATE FUNCTIONS **********************************************************/
NTSTATUS
@@ -1395,7 +1413,9 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN
UnloadPnpDrivers)
PreviousMode,
DriverServiceName);
if (!NT_SUCCESS(Status))
+ {
return Status;
+ }
DPRINT("IopUnloadDriver('%wZ', %u)\n", &CapturedServiceName,
UnloadPnpDrivers);
@@ -1562,7 +1582,7 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN
UnloadPnpDrivers)
/* Set the unload invoked flag and call the unload routine */
DriverObject->Flags |= DRVO_UNLOAD_INVOKED;
- Status = IopLoadUnloadDriver(NULL, &DriverObject);
+ Status = IopDoLoadUnloadDriver(NULL, &DriverObject);
ASSERT(Status == STATUS_SUCCESS);
/* Mark the driver object temporary, so it could be deleted later */
@@ -2028,22 +2048,8 @@ IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject,
return DriverExtensions + 1;
}
-VOID
-NTAPI
-IopLoadUnloadDriverWorker(
- _Inout_ PVOID Parameter)
-{
- PLOAD_UNLOAD_PARAMS LoadParams = Parameter;
-
- ASSERT(PsGetCurrentProcess() == PsInitialSystemProcess);
- LoadParams->Status = IopLoadUnloadDriver(LoadParams->RegistryPath,
- &LoadParams->DriverObject);
- KeSetEvent(&LoadParams->Event, 0, FALSE);
-}
-
NTSTATUS
-NTAPI
-IopLoadUnloadDriver(
+IopLoadDriver(
_In_opt_ PCUNICODE_STRING RegistryPath,
_Inout_ PDRIVER_OBJECT *DriverObject)
{
@@ -2056,38 +2062,6 @@ IopLoadUnloadDriver(
PVOID BaseAddress;
WCHAR *cur;
- /* Load/Unload must be called from system process */
- if (PsGetCurrentProcess() != PsInitialSystemProcess)
- {
- LOAD_UNLOAD_PARAMS LoadParams;
-
- /* Prepare parameters block */
- LoadParams.RegistryPath = RegistryPath;
- LoadParams.DriverObject = *DriverObject;
- KeInitializeEvent(&LoadParams.Event, NotificationEvent, FALSE);
-
- /* Initialize and queue a work item */
- ExInitializeWorkItem(&LoadParams.WorkItem,
- IopLoadUnloadDriverWorker,
- &LoadParams);
- ExQueueWorkItem(&LoadParams.WorkItem, DelayedWorkQueue);
-
- /* And wait till it completes */
- KeWaitForSingleObject(&LoadParams.Event,
- UserRequest,
- KernelMode,
- FALSE,
- NULL);
- return LoadParams.Status;
- }
-
- /* Check if it's an unload request */
- if (*DriverObject)
- {
- (*DriverObject)->DriverUnload(*DriverObject);
- return STATUS_SUCCESS;
- }
-
RtlInitUnicodeString(&ImagePath, NULL);
/*
@@ -2210,6 +2184,76 @@ IopLoadUnloadDriver(
return Status;
}
+static
+VOID
+NTAPI
+IopLoadUnloadDriverWorker(
+ _Inout_ PVOID Parameter)
+{
+ PLOAD_UNLOAD_PARAMS LoadParams = Parameter;
+
+ ASSERT(PsGetCurrentProcess() == PsInitialSystemProcess);
+
+ if (LoadParams->DriverObject)
+ {
+ // unload request
+ LoadParams->DriverObject->DriverUnload(LoadParams->DriverObject);
+ LoadParams->Status = STATUS_SUCCESS;
+ }
+ else
+ {
+ // load request
+ LoadParams->Status = IopLoadDriver(LoadParams->RegistryPath,
&LoadParams->DriverObject);
+ }
+
+ if (LoadParams->SetEvent)
+ {
+ KeSetEvent(&LoadParams->Event, 0, FALSE);
+ }
+}
+
+/**
+ * @brief Process load and unload driver operations. This is mostly for
NtLoadDriver
+ * and NtUnloadDriver, because their code should run inside
PsInitialSystemProcess
+ *
+ * @param[in] RegistryPath The registry path
+ * @param DriverObject The driver object
+ *
+ * @return Status of the operation
+ */
+NTSTATUS
+IopDoLoadUnloadDriver(
+ _In_opt_ PCUNICODE_STRING RegistryPath,
+ _Inout_ PDRIVER_OBJECT *DriverObject)
+{
+ LOAD_UNLOAD_PARAMS LoadParams;
+
+ /* Prepare parameters block */
+ LoadParams.RegistryPath = RegistryPath;
+ LoadParams.DriverObject = *DriverObject;
+
+ if (PsGetCurrentProcess() != PsInitialSystemProcess)
+ {
+ LoadParams.SetEvent = TRUE;
+ KeInitializeEvent(&LoadParams.Event, NotificationEvent, FALSE);
+
+ /* Initialize and queue a work item */
+ ExInitializeWorkItem(&LoadParams.WorkItem, IopLoadUnloadDriverWorker,
&LoadParams);
+ ExQueueWorkItem(&LoadParams.WorkItem, DelayedWorkQueue);
+
+ /* And wait till it completes */
+ KeWaitForSingleObject(&LoadParams.Event, UserRequest, KernelMode, FALSE,
NULL);
+ }
+ else
+ {
+ /* If we're already in a system process, call it right here */
+ LoadParams.SetEvent = FALSE;
+ IopLoadUnloadDriverWorker(&LoadParams);
+ }
+
+ return LoadParams.Status;
+}
+
/*
* NtLoadDriver
*
@@ -2249,7 +2293,9 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
PreviousMode,
DriverServiceName);
if (!NT_SUCCESS(Status))
+ {
return Status;
+ }
DPRINT("NtLoadDriver('%wZ')\n", &CapturedServiceName);
@@ -2262,7 +2308,7 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
/* Load driver and call its entry point */
DriverObject = NULL;
- Status = IopLoadUnloadDriver(&CapturedServiceName, &DriverObject);
+ Status = IopDoLoadUnloadDriver(&CapturedServiceName, &DriverObject);
ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
return Status;