Author: fireball
Date: Wed Oct 3 14:17:04 2007
New Revision: 29370
URL:
http://svn.reactos.org/svn/reactos?rev=29370&view=rev
Log:
- NtLoadDriver APIs refactor/improvent:
* Move loading of a driver to the common (in future) routine IopLoadUnloadDriver (name
taken from
http://wasm.ru/forum/viewtopic.php?pid=166891).
* Fix a bug: NtLoadDriver should always load drivers in a context of the system process,
explanation here:
http://www.osronline.com/showthread.cfm?link=114687
* Reformat NtLoadDriver's code.
Modified:
trunk/reactos/ntoskrnl/include/internal/io.h
trunk/reactos/ntoskrnl/io/iomgr/driver.c
Modified: trunk/reactos/ntoskrnl/include/internal/io.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/include/internal/…
==============================================================================
--- trunk/reactos/ntoskrnl/include/internal/io.h (original)
+++ trunk/reactos/ntoskrnl/include/internal/io.h Wed Oct 3 14:17:04 2007
@@ -350,6 +350,17 @@
} OPEN_PACKET, *POPEN_PACKET;
//
+// Parameters packet for Load/Unload work item's context
+//
+typedef struct _LOAD_UNLOAD_PARAMS
+{
+ NTSTATUS Status;
+ PUNICODE_STRING ServiceName;
+ WORK_QUEUE_ITEM WorkItem;
+ KEVENT Event;
+} LOAD_UNLOAD_PARAMS, *PLOAD_UNLOAD_PARAMS;
+
+//
// List of Bus Type GUIDs
//
typedef struct _IO_BUS_TYPE_GUID_LIST
Modified: trunk/reactos/ntoskrnl/io/iomgr/driver.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/io/iomgr/driver.c…
==============================================================================
--- trunk/reactos/ntoskrnl/io/iomgr/driver.c (original)
+++ trunk/reactos/ntoskrnl/io/iomgr/driver.c Wed Oct 3 14:17:04 2007
@@ -1465,29 +1465,12 @@
return DriverExtensions + 1;
}
-/*
- * NtLoadDriver
- *
- * Loads a device driver.
- *
- * Parameters
- * DriverServiceName
- * Name of the service to load (registry key).
- *
- * Return Value
- * Status
- *
- * Status
- * implemented
- */
-NTSTATUS STDCALL
-NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
+VOID NTAPI
+IopLoadUnloadDriver(PLOAD_UNLOAD_PARAMS LoadParams)
{
RTL_QUERY_REGISTRY_TABLE QueryTable[3];
UNICODE_STRING ImagePath;
UNICODE_STRING ServiceName;
- UNICODE_STRING CapturedDriverServiceName = {0};
- KPROCESSOR_MODE PreviousMode;
NTSTATUS Status;
ULONG Type;
PDEVICE_NODE DeviceNode;
@@ -1495,50 +1478,24 @@
PDRIVER_OBJECT DriverObject;
WCHAR *cur;
- PAGED_CODE();
-
- PreviousMode = KeGetPreviousMode();
-
- /*
- * Check security privileges
- */
-
-/* FIXME: Uncomment when privileges will be correctly implemented. */
-#if 0
- if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
- {
- DPRINT("Privilege not held\n");
- return STATUS_PRIVILEGE_NOT_HELD;
- }
-#endif
-
- Status = ProbeAndCaptureUnicodeString(&CapturedDriverServiceName,
- PreviousMode,
- DriverServiceName);
- if (!NT_SUCCESS(Status))
- {
- return Status;
- }
-
- DPRINT("NtLoadDriver('%wZ')\n", &CapturedDriverServiceName);
-
RtlInitUnicodeString(&ImagePath, NULL);
/*
* Get the service name from the registry key name.
*/
- ASSERT(CapturedDriverServiceName.Length >= sizeof(WCHAR));
-
- ServiceName = CapturedDriverServiceName;
- cur = CapturedDriverServiceName.Buffer + (CapturedDriverServiceName.Length /
sizeof(WCHAR)) - 1;
- while (CapturedDriverServiceName.Buffer != cur)
+ ASSERT(LoadParams->ServiceName->Length >= sizeof(WCHAR));
+
+ ServiceName = *LoadParams->ServiceName;
+ cur = LoadParams->ServiceName->Buffer +
+ (LoadParams->ServiceName->Length / sizeof(WCHAR)) - 1;
+ while (LoadParams->ServiceName->Buffer != cur)
{
if(*cur == L'\\')
{
ServiceName.Buffer = cur + 1;
- ServiceName.Length = CapturedDriverServiceName.Length -
+ ServiceName.Length = LoadParams->ServiceName->Length -
(USHORT)((ULONG_PTR)ServiceName.Buffer -
- (ULONG_PTR)CapturedDriverServiceName.Buffer);
+
(ULONG_PTR)LoadParams->ServiceName->Buffer);
break;
}
cur--;
@@ -1561,13 +1518,15 @@
QueryTable[1].EntryContext = &ImagePath;
Status = RtlQueryRegistryValues(RTL_REGISTRY_ABSOLUTE,
- CapturedDriverServiceName.Buffer, QueryTable, NULL, NULL);
+ LoadParams->ServiceName->Buffer, QueryTable, NULL, NULL);
if (!NT_SUCCESS(Status))
{
DPRINT("RtlQueryRegistryValues() failed (Status %lx)\n", Status);
ExFreePool(ImagePath.Buffer);
- goto ReleaseCapturedString;
+ LoadParams->Status = Status;
+ (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
+ return;
}
/*
@@ -1579,7 +1538,9 @@
if (!NT_SUCCESS(Status))
{
DPRINT("IopNormalizeImagePath() failed (Status %x)\n", Status);
- goto ReleaseCapturedString;
+ LoadParams->Status = Status;
+ (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
+ return;
}
DPRINT("FullImagePath: '%wZ'\n", &ImagePath);
@@ -1595,7 +1556,9 @@
if (!NT_SUCCESS(Status))
{
DPRINT("IopCreateDeviceNode() failed (Status %lx)\n", Status);
- goto ReleaseCapturedString;
+ LoadParams->Status = Status;
+ (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
+ return;
}
/* Get existing DriverObject pointer (in case the driver has
@@ -1617,7 +1580,9 @@
{
DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status);
IopFreeDeviceNode(DeviceNode);
- goto ReleaseCapturedString;
+ LoadParams->Status = Status;
+ (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
+ return;
}
/*
@@ -1644,7 +1609,9 @@
DPRINT("IopInitializeDriver() failed (Status %lx)\n", Status);
MmUnloadSystemImage(ModuleObject);
IopFreeDeviceNode(DeviceNode);
- goto ReleaseCapturedString;
+ LoadParams->Status = Status;
+ (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
+ return;
}
}
@@ -1653,13 +1620,88 @@
}
IopInitializeDevice(DeviceNode, DriverObject);
- Status = IopStartDevice(DeviceNode);
-
-ReleaseCapturedString:
- ReleaseCapturedUnicodeString(&CapturedDriverServiceName,
- PreviousMode);
-
- return Status;
+ LoadParams->Status = IopStartDevice(DeviceNode);
+ (VOID)KeSetEvent(&LoadParams->Event, 0, FALSE);
+}
+
+/*
+ * NtLoadDriver
+ *
+ * Loads a device driver.
+ *
+ * Parameters
+ * DriverServiceName
+ * Name of the service to load (registry key).
+ *
+ * Return Value
+ * Status
+ *
+ * Status
+ * implemented
+ */
+NTSTATUS STDCALL
+NtLoadDriver(IN PUNICODE_STRING DriverServiceName)
+{
+ UNICODE_STRING CapturedDriverServiceName = {0};
+ KPROCESSOR_MODE PreviousMode;
+ LOAD_UNLOAD_PARAMS LoadParams;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ PreviousMode = KeGetPreviousMode();
+
+ /*
+ * Check security privileges
+ */
+
+ /* FIXME: Uncomment when privileges will be correctly implemented. */
+#if 0
+ if (!SeSinglePrivilegeCheck(SeLoadDriverPrivilege, PreviousMode))
+ {
+ DPRINT("Privilege not held\n");
+ return STATUS_PRIVILEGE_NOT_HELD;
+ }
+#endif
+
+ Status = ProbeAndCaptureUnicodeString(&CapturedDriverServiceName,
+ PreviousMode,
+ DriverServiceName);
+ if (!NT_SUCCESS(Status))
+ {
+ return Status;
+ }
+
+ DPRINT("NtLoadDriver('%wZ')\n", &CapturedDriverServiceName);
+
+ LoadParams.ServiceName = &CapturedDriverServiceName;
+ KeInitializeEvent(&LoadParams.Event, NotificationEvent, FALSE);
+
+ /* Call the load/unload routine, depending on current process */
+ if (PsGetCurrentProcess() == PsInitialSystemProcess)
+ {
+ /* Just call right away */
+ IopLoadUnloadDriver(&LoadParams);
+ }
+ else
+ {
+ /* Load/Unload must be called from system process */
+ ExInitializeWorkItem(&LoadParams.WorkItem,
+ (PWORKER_THREAD_ROUTINE)IopLoadUnloadDriver,
+ (PVOID)&LoadParams);
+
+ /* Queue it */
+ ExQueueWorkItem(&LoadParams.WorkItem, DelayedWorkQueue);
+
+ /* And wait when it completes */
+ KeWaitForSingleObject(&LoadParams.Event, UserRequest, KernelMode,
+ FALSE, NULL);
+ }
+
+ ReleaseCapturedUnicodeString(&CapturedDriverServiceName,
+ PreviousMode);
+
+ return LoadParams.Status;
}
/*