mirror of
https://github.com/reactos/reactos.git
synced 2025-06-09 20:11:14 +00:00
[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)
This commit is contained in:
parent
e18a32df3a
commit
a6a3aa0f0d
2 changed files with 96 additions and 63 deletions
|
@ -391,18 +391,6 @@ typedef struct _OPEN_PACKET
|
||||||
PDEVICE_OBJECT TopDeviceObjectHint;
|
PDEVICE_OBJECT TopDeviceObjectHint;
|
||||||
} OPEN_PACKET, *POPEN_PACKET;
|
} 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
|
// Boot Driver List Entry
|
||||||
//
|
//
|
||||||
|
@ -1138,8 +1126,7 @@ IopLoadServiceModule(
|
||||||
);
|
);
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
NTAPI
|
IopLoadDriver(
|
||||||
IopLoadUnloadDriver(
|
|
||||||
_In_opt_ PCUNICODE_STRING RegistryPath,
|
_In_opt_ PCUNICODE_STRING RegistryPath,
|
||||||
_Inout_ PDRIVER_OBJECT *DriverObject
|
_Inout_ PDRIVER_OBJECT *DriverObject
|
||||||
);
|
);
|
||||||
|
|
|
@ -41,6 +41,24 @@ extern KEVENT PiEnumerationFinished;
|
||||||
USHORT IopGroupIndex;
|
USHORT IopGroupIndex;
|
||||||
PLIST_ENTRY IopGroupTable;
|
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 **********************************************************/
|
/* PRIVATE FUNCTIONS **********************************************************/
|
||||||
|
|
||||||
NTSTATUS
|
NTSTATUS
|
||||||
|
@ -1395,7 +1413,9 @@ IopUnloadDriver(PUNICODE_STRING DriverServiceName, BOOLEAN UnloadPnpDrivers)
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
DriverServiceName);
|
DriverServiceName);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
return Status;
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT("IopUnloadDriver('%wZ', %u)\n", &CapturedServiceName, UnloadPnpDrivers);
|
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 */
|
/* Set the unload invoked flag and call the unload routine */
|
||||||
DriverObject->Flags |= DRVO_UNLOAD_INVOKED;
|
DriverObject->Flags |= DRVO_UNLOAD_INVOKED;
|
||||||
Status = IopLoadUnloadDriver(NULL, &DriverObject);
|
Status = IopDoLoadUnloadDriver(NULL, &DriverObject);
|
||||||
ASSERT(Status == STATUS_SUCCESS);
|
ASSERT(Status == STATUS_SUCCESS);
|
||||||
|
|
||||||
/* Mark the driver object temporary, so it could be deleted later */
|
/* Mark the driver object temporary, so it could be deleted later */
|
||||||
|
@ -2028,22 +2048,8 @@ IoGetDriverObjectExtension(IN PDRIVER_OBJECT DriverObject,
|
||||||
return DriverExtensions + 1;
|
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
|
NTSTATUS
|
||||||
NTAPI
|
IopLoadDriver(
|
||||||
IopLoadUnloadDriver(
|
|
||||||
_In_opt_ PCUNICODE_STRING RegistryPath,
|
_In_opt_ PCUNICODE_STRING RegistryPath,
|
||||||
_Inout_ PDRIVER_OBJECT *DriverObject)
|
_Inout_ PDRIVER_OBJECT *DriverObject)
|
||||||
{
|
{
|
||||||
|
@ -2056,38 +2062,6 @@ IopLoadUnloadDriver(
|
||||||
PVOID BaseAddress;
|
PVOID BaseAddress;
|
||||||
WCHAR *cur;
|
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);
|
RtlInitUnicodeString(&ImagePath, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2210,6 +2184,76 @@ IopLoadUnloadDriver(
|
||||||
return Status;
|
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
|
* NtLoadDriver
|
||||||
*
|
*
|
||||||
|
@ -2249,7 +2293,9 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
|
||||||
PreviousMode,
|
PreviousMode,
|
||||||
DriverServiceName);
|
DriverServiceName);
|
||||||
if (!NT_SUCCESS(Status))
|
if (!NT_SUCCESS(Status))
|
||||||
|
{
|
||||||
return Status;
|
return Status;
|
||||||
|
}
|
||||||
|
|
||||||
DPRINT("NtLoadDriver('%wZ')\n", &CapturedServiceName);
|
DPRINT("NtLoadDriver('%wZ')\n", &CapturedServiceName);
|
||||||
|
|
||||||
|
@ -2262,7 +2308,7 @@ NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
|
||||||
|
|
||||||
/* Load driver and call its entry point */
|
/* Load driver and call its entry point */
|
||||||
DriverObject = NULL;
|
DriverObject = NULL;
|
||||||
Status = IopLoadUnloadDriver(&CapturedServiceName, &DriverObject);
|
Status = IopDoLoadUnloadDriver(&CapturedServiceName, &DriverObject);
|
||||||
|
|
||||||
ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
|
ReleaseCapturedUnicodeString(&CapturedServiceName, PreviousMode);
|
||||||
return Status;
|
return Status;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue