From 6f0e37b042414a5b4530b89f1bf2b719a6e9147f Mon Sep 17 00:00:00 2001 From: Victor Perevertkin Date: Sun, 15 Nov 2020 17:33:42 +0300 Subject: [PATCH] [NTOS:PNP][NTOS:IO] Do not create a device object + node on every driver load - Remove the usage of IopCreateDeviceNode and change it to PipAllocateDeviceNode where required --- ntoskrnl/include/internal/io.h | 13 ++---- ntoskrnl/io/iomgr/driver.c | 85 ++++------------------------------ ntoskrnl/io/pnpmgr/devaction.c | 16 +++---- ntoskrnl/io/pnpmgr/devnode.c | 40 +++++++++++++--- ntoskrnl/io/pnpmgr/pnpreport.c | 13 +++--- 5 files changed, 61 insertions(+), 106 deletions(-) diff --git a/ntoskrnl/include/internal/io.h b/ntoskrnl/include/internal/io.h index 628929f1cff..4e81a6f1c83 100644 --- a/ntoskrnl/include/internal/io.h +++ b/ntoskrnl/include/internal/io.h @@ -615,18 +615,14 @@ IopGetSystemPowerDeviceObject( ); PDEVICE_NODE -NTAPI PipAllocateDeviceNode( IN PDEVICE_OBJECT PhysicalDeviceObject ); -NTSTATUS -IopCreateDeviceNode( - IN PDEVICE_NODE ParentNode, - IN PDEVICE_OBJECT PhysicalDeviceObject, - IN PUNICODE_STRING ServiceName, - OUT PDEVICE_NODE *DeviceNode -); +VOID +PiInsertDevNode( + _In_ PDEVICE_NODE DeviceNode, + _In_ PDEVICE_NODE ParentNode); NTSTATUS IopFreeDeviceNode( @@ -1160,7 +1156,6 @@ IopLoadUnloadDriver( NTSTATUS FASTCALL IopInitializeDriverModule( - IN PDEVICE_NODE DeviceNode, IN PLDR_DATA_TABLE_ENTRY ModuleObject, IN PUNICODE_STRING ServiceName, IN BOOLEAN FileSystemDriver, diff --git a/ntoskrnl/io/iomgr/driver.c b/ntoskrnl/io/iomgr/driver.c index 3b033f9ab32..f3f4c5a79a8 100644 --- a/ntoskrnl/io/iomgr/driver.c +++ b/ntoskrnl/io/iomgr/driver.c @@ -464,10 +464,6 @@ MmFreeDriverInitialization(IN PLDR_DATA_TABLE_ENTRY LdrEntry); * * Initialize a loaded driver. * - * Parameters - * DeviceNode - * Pointer to device node. - * * ModuleObject * Module object representing the driver. It can be retrieve by * IopLoadServiceModule. @@ -485,7 +481,6 @@ MmFreeDriverInitialization(IN PLDR_DATA_TABLE_ENTRY LdrEntry); NTSTATUS FASTCALL IopInitializeDriverModule( - IN PDEVICE_NODE DeviceNode, IN PLDR_DATA_TABLE_ENTRY ModuleObject, IN PUNICODE_STRING ServiceName, IN BOOLEAN FileSystemDriver, @@ -626,8 +621,7 @@ IopAttachFilterDriversCallback( return Status; } - Status = IopInitializeDriverModule(DeviceNode, - ModuleObject, + Status = IopInitializeDriverModule(ModuleObject, &ServiceName, FALSE, &DriverObject); @@ -827,7 +821,6 @@ NTSTATUS NTAPI IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY BootLdrEntry) { - PDEVICE_NODE DeviceNode; PDRIVER_OBJECT DriverObject; NTSTATUS Status; PWCHAR Buffer, FileNameWithoutPath; @@ -885,21 +878,6 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY BootLdrEntry) FileExtension[0] = UNICODE_NULL; } - /* - * Determine the right device object - */ - /* Use IopRootDeviceNode for now */ - Status = IopCreateDeviceNode(IopRootDeviceNode, - NULL, - &ServiceName, - &DeviceNode); - RtlFreeUnicodeString(&ServiceName); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status); - return Status; - } - /* Lookup the new Ldr entry in PsLoadedModuleList */ NextEntry = PsLoadedModuleList.Flink; while (NextEntry != &PsLoadedModuleList) @@ -919,23 +897,18 @@ IopInitializeBuiltinDriver(IN PLDR_DATA_TABLE_ENTRY BootLdrEntry) /* * Initialize the driver */ - Status = IopInitializeDriverModule(DeviceNode, - LdrEntry, - &DeviceNode->ServiceName, + Status = IopInitializeDriverModule(LdrEntry, + &ServiceName, FALSE, &DriverObject); + RtlFreeUnicodeString(&ServiceName); if (!NT_SUCCESS(Status)) { + DPRINT1("Driver '%wZ' load failed, status (%x)\n", ModuleName, Status); return Status; } - Status = IopInitializeDevice(DeviceNode, DriverObject); - if (NT_SUCCESS(Status)) - { - Status = IopStartDevice(DeviceNode); - } - /* Remove extra reference from IopInitializeDriverModule */ ObDereferenceObject(DriverObject); @@ -960,7 +933,6 @@ IopInitializeBootDrivers(VOID) { PLIST_ENTRY ListHead, NextEntry, NextEntry2; PLDR_DATA_TABLE_ENTRY LdrEntry; - PDEVICE_NODE DeviceNode; PDRIVER_OBJECT DriverObject; LDR_DATA_TABLE_ENTRY ModuleObject; NTSTATUS Status; @@ -971,10 +943,6 @@ IopInitializeBootDrivers(VOID) PBOOT_DRIVER_LIST_ENTRY BootEntry; DPRINT("IopInitializeBootDrivers()\n"); - /* Use IopRootDeviceNode for now */ - Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, NULL, &DeviceNode); - if (!NT_SUCCESS(Status)) return; - /* Setup the module object for the RAW FS Driver */ ModuleObject.DllBase = NULL; ModuleObject.SizeOfImage = 0; @@ -982,8 +950,7 @@ IopInitializeBootDrivers(VOID) RtlInitUnicodeString(&DriverName, L"RAW"); /* Initialize it */ - Status = IopInitializeDriverModule(DeviceNode, - &ModuleObject, + Status = IopInitializeDriverModule(&ModuleObject, &DriverName, TRUE, &DriverObject); @@ -993,24 +960,6 @@ IopInitializeBootDrivers(VOID) return; } - /* Now initialize the associated device */ - Status = IopInitializeDevice(DeviceNode, DriverObject); - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ObDereferenceObject(DriverObject); - return; - } - - /* Start it up */ - Status = IopStartDevice(DeviceNode); - if (!NT_SUCCESS(Status)) - { - /* Fail */ - ObDereferenceObject(DriverObject); - return; - } - /* Get highest group order index */ IopGroupIndex = PpInitGetGroupOrderIndex(NULL); if (IopGroupIndex == 0xFFFF) ASSERT(FALSE); @@ -1943,7 +1892,6 @@ IopLoadUnloadDriver( UNICODE_STRING ServiceName; NTSTATUS Status; ULONG Type; - PDEVICE_NODE DeviceNode; PLDR_DATA_TABLE_ENTRY ModuleObject; PVOID BaseAddress; WCHAR *cur; @@ -2069,21 +2017,10 @@ IopLoadUnloadDriver( /* * Initialize the driver module if it's loaded for the first time */ - Status = IopCreateDeviceNode(IopRootDeviceNode, NULL, &ServiceName, &DeviceNode); - if (!NT_SUCCESS(Status)) - { - DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status); - ExReleaseResourceLite(&IopDriverLoadResource); - KeLeaveCriticalRegion(); - MmUnloadSystemImage(ModuleObject); - return Status; - } + IopDisplayLoadingMessage(&ServiceName); - IopDisplayLoadingMessage(&DeviceNode->ServiceName); - - Status = IopInitializeDriverModule(DeviceNode, - ModuleObject, - &DeviceNode->ServiceName, + Status = IopInitializeDriverModule(ModuleObject, + &ServiceName, (Type == SERVICE_FILE_SYSTEM_DRIVER || Type == SERVICE_RECOGNIZER_DRIVER), DriverObject); @@ -2098,10 +2035,6 @@ IopLoadUnloadDriver( ExReleaseResourceLite(&IopDriverLoadResource); KeLeaveCriticalRegion(); - - /* Initialize and start device */ - IopInitializeDevice(DeviceNode, *DriverObject); - Status = IopStartDevice(DeviceNode); } else { diff --git a/ntoskrnl/io/pnpmgr/devaction.c b/ntoskrnl/io/pnpmgr/devaction.c index 34d71e18a2e..99e4e2b944d 100644 --- a/ntoskrnl/io/pnpmgr/devaction.c +++ b/ntoskrnl/io/pnpmgr/devaction.c @@ -1079,8 +1079,10 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode, if (NT_SUCCESS(Status) || Status == STATUS_IMAGE_ALREADY_LOADED) { /* Initialize the driver */ - Status = IopInitializeDriverModule(DeviceNode, ModuleObject, - &DeviceNode->ServiceName, FALSE, &DriverObject); + Status = IopInitializeDriverModule(ModuleObject, + &DeviceNode->ServiceName, + FALSE, + &DriverObject); if (!NT_SUCCESS(Status)) DeviceNode->Problem = CM_PROB_FAILED_DRIVER_ENTRY; } @@ -2183,13 +2185,11 @@ PipEnumerateDevice( if (!ChildDeviceNode) { /* One doesn't exist, create it */ - Status = IopCreateDeviceNode( - DeviceNode, - ChildDeviceObject, - NULL, - &ChildDeviceNode); - if (NT_SUCCESS(Status)) + ChildDeviceNode = PipAllocateDeviceNode(ChildDeviceObject); + if (ChildDeviceNode) { + PiInsertDevNode(ChildDeviceNode, DeviceNode); + /* Mark the node as enumerated */ ChildDeviceNode->Flags |= DNF_ENUMERATED; diff --git a/ntoskrnl/io/pnpmgr/devnode.c b/ntoskrnl/io/pnpmgr/devnode.c index 230fcce100b..0442e1765c2 100644 --- a/ntoskrnl/io/pnpmgr/devnode.c +++ b/ntoskrnl/io/pnpmgr/devnode.c @@ -31,7 +31,6 @@ IopGetDeviceNode( } PDEVICE_NODE -NTAPI PipAllocateDeviceNode( _In_opt_ PDEVICE_OBJECT PhysicalDeviceObject) { @@ -39,19 +38,22 @@ PipAllocateDeviceNode( PAGED_CODE(); /* Allocate it */ - DeviceNode = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_NODE), TAG_IO_DEVNODE); - if (!DeviceNode) return DeviceNode; + DeviceNode = ExAllocatePoolZero(NonPagedPool, sizeof(DEVICE_NODE), TAG_IO_DEVNODE); + if (!DeviceNode) + { + return NULL; + } /* Statistics */ InterlockedIncrement(&IopNumberDeviceNodes); /* Set it up */ - RtlZeroMemory(DeviceNode, sizeof(DEVICE_NODE)); DeviceNode->InterfaceType = InterfaceTypeUndefined; DeviceNode->BusNumber = -1; DeviceNode->ChildInterfaceType = InterfaceTypeUndefined; DeviceNode->ChildBusNumber = -1; DeviceNode->ChildBusTypeIndex = -1; + DeviceNode->State = DeviceNodeUninitialized; // KeInitializeEvent(&DeviceNode->EnumerationMutex, SynchronizationEvent, TRUE); InitializeListHead(&DeviceNode->DeviceArbiterList); InitializeListHead(&DeviceNode->DeviceTranslatorList); @@ -72,6 +74,32 @@ PipAllocateDeviceNode( return DeviceNode; } +VOID +PiInsertDevNode( + _In_ PDEVICE_NODE DeviceNode, + _In_ PDEVICE_NODE ParentNode) +{ + KIRQL oldIrql; + + ASSERT(DeviceNode->Parent == NULL); + + KeAcquireSpinLock(&IopDeviceTreeLock, &oldIrql); + DeviceNode->Parent = ParentNode; + DeviceNode->Sibling = NULL; + if (ParentNode->LastChild == NULL) + { + ParentNode->Child = DeviceNode; + ParentNode->LastChild = DeviceNode; + } + else + { + ParentNode->LastChild->Sibling = DeviceNode; + ParentNode->LastChild = DeviceNode; + } + KeReleaseSpinLock(&IopDeviceTreeLock, oldIrql); + DeviceNode->Level = ParentNode->Level + 1; +} + /** * @brief Creates a device node * @@ -84,7 +112,7 @@ PipAllocateDeviceNode( * * @return Status, indicating the result of an operation */ - +#if 0 NTSTATUS IopCreateDeviceNode( _In_ PDEVICE_NODE ParentNode, @@ -94,7 +122,6 @@ IopCreateDeviceNode( { PDEVICE_NODE Node; NTSTATUS Status; - KIRQL OldIrql; UNICODE_STRING FullServiceName; UNICODE_STRING LegacyPrefix = RTL_CONSTANT_STRING(L"LEGACY_"); UNICODE_STRING UnknownDeviceName = RTL_CONSTANT_STRING(L"UNKNOWN"); @@ -249,6 +276,7 @@ IopCreateDeviceNode( return STATUS_SUCCESS; } +#endif NTSTATUS IopFreeDeviceNode( diff --git a/ntoskrnl/io/pnpmgr/pnpreport.c b/ntoskrnl/io/pnpmgr/pnpreport.c index ae0ac9566d3..4c5e36cb147 100644 --- a/ntoskrnl/io/pnpmgr/pnpreport.c +++ b/ntoskrnl/io/pnpmgr/pnpreport.c @@ -242,16 +242,15 @@ IoReportDetectedDevice(IN PDRIVER_OBJECT DriverObject, } /* Create the device node for the new PDO */ - Status = IopCreateDeviceNode(IopRootDeviceNode, - Pdo, - NULL, - &DeviceNode); - if (!NT_SUCCESS(Status)) + DeviceNode = PipAllocateDeviceNode(Pdo); + if (!DeviceNode) { - DPRINT("IopCreateDeviceNode() failed (Status 0x%08lx)\n", Status); - return Status; + DPRINT("PipAllocateDeviceNode() failed\n"); + return STATUS_INSUFFICIENT_RESOURCES; } + PiInsertDevNode(DeviceNode, IopRootDeviceNode); + /* We're enumerated already */ IopDeviceNodeSetFlag(DeviceNode, DNF_ENUMERATED);