Index: include/internal/io.h =================================================================== --- ntoskrnl/include/internal/io.h (revision 64944) +++ ntoskrnl/include/internal/io.h (working copy) @@ -1277,6 +1277,8 @@ extern PVOID IopTriageDumpDataBlocks[64]; extern PIO_BUS_TYPE_GUID_LIST PnpBusTypeGuidList; extern PDRIVER_OBJECT IopRootDriverObject; +extern KSPIN_LOCK IopDeviceRelationsSpinLock; +extern LIST_ENTRY IopDeviceRelationsRequestList; // // Inlined Functions Index: io/iomgr/driver.c =================================================================== --- ntoskrnl/io/iomgr/driver.c (revision 64946) +++ ntoskrnl/io/iomgr/driver.c (working copy) @@ -16,6 +16,8 @@ /* GLOBALS ********************************************************************/ +ERESOURCE IopDriverLoadResource; + LIST_ENTRY DriverReinitListHead; KSPIN_LOCK DriverReinitListLock; PLIST_ENTRY DriverReinitTailEntry; @@ -113,6 +115,7 @@ DPRINT("IopGetDriverObject(%p '%wZ' %x)\n", DriverObject, ServiceName, FileSystem); + ASSERT(ExIsResourceAcquiredExclusiveLite(&IopDriverLoadResource)); *DriverObject = NULL; /* Create ModuleName string */ @@ -313,6 +316,7 @@ HANDLE CCSKey, ServiceKey; PVOID BaseAddress; + ASSERT(ExIsResourceAcquiredExclusiveLite(&IopDriverLoadResource)); ASSERT(ServiceName->Length); DPRINT("IopLoadServiceModule(%wZ, 0x%p)\n", ServiceName, ModuleObject); @@ -567,6 +571,8 @@ ServiceName.MaximumLength = ServiceName.Length = (USHORT)wcslen(Filters) * sizeof(WCHAR); + KeEnterCriticalRegion(); + ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE); Status = IopGetDriverObject(&DriverObject, &ServiceName, FALSE); @@ -575,7 +581,11 @@ /* Load and initialize the filter driver */ Status = IopLoadServiceModule(&ServiceName, &ModuleObject); if (!NT_SUCCESS(Status)) + { + ExReleaseResourceLite(&IopDriverLoadResource); + KeLeaveCriticalRegion(); return Status; + } Status = IopInitializeDriverModule(DeviceNode, ModuleObject, @@ -583,9 +593,16 @@ FALSE, &DriverObject); if (!NT_SUCCESS(Status)) + { + ExReleaseResourceLite(&IopDriverLoadResource); + KeLeaveCriticalRegion(); return Status; + } } + ExReleaseResourceLite(&IopDriverLoadResource); + KeLeaveCriticalRegion(); + Status = IopInitializeDevice(DeviceNode, DriverObject); /* Remove extra reference */ @@ -930,7 +947,6 @@ if (!NT_SUCCESS(Status)) { - IopFreeDeviceNode(DeviceNode); return Status; } @@ -994,7 +1010,6 @@ if (!NT_SUCCESS(Status)) { /* Fail */ - IopFreeDeviceNode(DeviceNode); return; } @@ -1003,7 +1018,6 @@ if (!NT_SUCCESS(Status)) { /* Fail */ - IopFreeDeviceNode(DeviceNode); ObDereferenceObject(DriverObject); return; } @@ -1013,7 +1027,6 @@ if (!NT_SUCCESS(Status)) { /* Fail */ - IopFreeDeviceNode(DeviceNode); ObDereferenceObject(DriverObject); return; } @@ -1975,6 +1988,8 @@ DPRINT("FullImagePath: '%wZ'\n", &ImagePath); DPRINT("Type: %lx\n", Type); + KeEnterCriticalRegion(); + ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE); /* * Get existing DriverObject pointer (in case the driver * has already been loaded and initialized). @@ -1994,6 +2009,8 @@ if (!NT_SUCCESS(Status)) { DPRINT("MmLoadSystemImage() failed (Status %lx)\n", Status); + ExReleaseResourceLite(&IopDriverLoadResource); + KeLeaveCriticalRegion(); return Status; } @@ -2004,6 +2021,8 @@ if (!NT_SUCCESS(Status)) { DPRINT1("IopCreateDeviceNode() failed (Status %lx)\n", Status); + ExReleaseResourceLite(&IopDriverLoadResource); + KeLeaveCriticalRegion(); MmUnloadSystemImage(ModuleObject); return Status; } @@ -2019,17 +2038,24 @@ if (!NT_SUCCESS(Status)) { DPRINT1("IopInitializeDriverModule() failed (Status %lx)\n", Status); + ExReleaseResourceLite(&IopDriverLoadResource); + KeLeaveCriticalRegion(); MmUnloadSystemImage(ModuleObject); - IopFreeDeviceNode(DeviceNode); return Status; } + ExReleaseResourceLite(&IopDriverLoadResource); + KeLeaveCriticalRegion(); + /* Initialize and start device */ IopInitializeDevice(DeviceNode, *DriverObject); Status = IopStartDevice(DeviceNode); } else { + ExReleaseResourceLite(&IopDriverLoadResource); + KeLeaveCriticalRegion(); + DPRINT("DriverObject already exist in ObjectManager\n"); Status = STATUS_IMAGE_ALREADY_LOADED; Index: io/iomgr/iomgr.c =================================================================== --- ntoskrnl/io/iomgr/iomgr.c (revision 64944) +++ ntoskrnl/io/iomgr/iomgr.c (working copy) @@ -54,6 +54,7 @@ extern POBJECT_TYPE IoAdapterObjectType; extern ERESOURCE IopDatabaseResource; ERESOURCE IopSecurityResource; +extern ERESOURCE IopDriverLoadResource; extern KGUARDED_MUTEX PnpNotifyListLock; extern LIST_ENTRY IopDiskFileSystemQueueHead; extern LIST_ENTRY IopCdRomFileSystemQueueHead; @@ -476,8 +477,9 @@ IopInitLookasideLists(); /* Initialize all locks and lists */ - ExInitializeResource(&IopDatabaseResource); - ExInitializeResource(&IopSecurityResource); + ExInitializeResourceLite(&IopDatabaseResource); + ExInitializeResourceLite(&IopSecurityResource); + ExInitializeResourceLite(&IopDriverLoadResource); KeInitializeGuardedMutex(&PnpNotifyListLock); InitializeListHead(&IopDiskFileSystemQueueHead); InitializeListHead(&IopCdRomFileSystemQueueHead); Index: io/pnpmgr/pnpinit.c =================================================================== --- ntoskrnl/io/pnpmgr/pnpinit.c (revision 64944) +++ ntoskrnl/io/pnpmgr/pnpinit.c (working copy) @@ -385,6 +385,8 @@ /* Initialize locks and such */ KeInitializeSpinLock(&IopDeviceTreeLock); + KeInitializeSpinLock(&IopDeviceRelationsSpinLock); + InitializeListHead(&IopDeviceRelationsRequestList); /* Get the default interface */ PnpDefaultInterfaceType = IopDetermineDefaultInterfaceType(); Index: io/pnpmgr/pnpmgr.c =================================================================== --- ntoskrnl/io/pnpmgr/pnpmgr.c (revision 64944) +++ ntoskrnl/io/pnpmgr/pnpmgr.c (working copy) @@ -21,6 +21,7 @@ KGUARDED_MUTEX PpDeviceReferenceTableLock; RTL_AVL_TABLE PpDeviceReferenceTable; +extern ERESOURCE IopDriverLoadResource; extern ULONG ExpInitializationPhase; extern BOOLEAN ExpInTextModeSetup; extern BOOLEAN PnpSystemInit; @@ -29,12 +30,16 @@ PDRIVER_OBJECT IopRootDriverObject; PIO_BUS_TYPE_GUID_LIST PnpBusTypeGuidList = NULL; +LIST_ENTRY IopDeviceRelationsRequestList; +WORK_QUEUE_ITEM IopDeviceRelationsWorkItem; +BOOLEAN IopDeviceRelationsRequestInProgress; +KSPIN_LOCK IopDeviceRelationsSpinLock; typedef struct _INVALIDATE_DEVICE_RELATION_DATA { + LIST_ENTRY RequestListEntry; PDEVICE_OBJECT DeviceObject; DEVICE_RELATION_TYPE Type; - PIO_WORKITEM WorkItem; } INVALIDATE_DEVICE_RELATION_DATA, *PINVALIDATE_DEVICE_RELATION_DATA; /* FUNCTIONS *****************************************************************/ @@ -889,20 +894,34 @@ return Status; } -static VOID NTAPI -IopAsynchronousInvalidateDeviceRelations( - IN PDEVICE_OBJECT DeviceObject, - IN PVOID InvalidateContext) +static +VOID +NTAPI +IopDeviceRelationsWorker( + _In_ PVOID Context) { - PINVALIDATE_DEVICE_RELATION_DATA Data = InvalidateContext; + PLIST_ENTRY ListEntry; + PINVALIDATE_DEVICE_RELATION_DATA Data; + KIRQL OldIrql; - IoSynchronousInvalidateDeviceRelations( - Data->DeviceObject, - Data->Type); + KeAcquireSpinLock(&IopDeviceRelationsSpinLock, &OldIrql); + while (!IsListEmpty(&IopDeviceRelationsRequestList)) + { + ListEntry = RemoveHeadList(&IopDeviceRelationsRequestList); + KeReleaseSpinLock(&IopDeviceRelationsSpinLock, OldIrql); + Data = CONTAINING_RECORD(ListEntry, + INVALIDATE_DEVICE_RELATION_DATA, + RequestListEntry); - ObDereferenceObject(Data->DeviceObject); - IoFreeWorkItem(Data->WorkItem); - ExFreePool(Data); + IoSynchronousInvalidateDeviceRelations(Data->DeviceObject, + Data->Type); + + ObDereferenceObject(Data->DeviceObject); + ExFreePool(Data); + KeAcquireSpinLock(&IopDeviceRelationsSpinLock, &OldIrql); + } + IopDeviceRelationsRequestInProgress = FALSE; + KeReleaseSpinLock(&IopDeviceRelationsSpinLock, OldIrql); } NTSTATUS @@ -1023,8 +1042,8 @@ DPRINT("ParentNode 0x%p PhysicalDeviceObject 0x%p ServiceName %wZ\n", ParentNode, PhysicalDeviceObject, ServiceName); - - Node = (PDEVICE_NODE)ExAllocatePool(NonPagedPool, sizeof(DEVICE_NODE)); +#define TAG_IO_DEVNODE 'donD' + Node = ExAllocatePoolWithTag(NonPagedPool, sizeof(DEVICE_NODE), TAG_IO_DEVNODE); if (!Node) { return STATUS_INSUFFICIENT_RESOURCES; @@ -1044,7 +1063,7 @@ FullServiceName.Buffer = ExAllocatePool(PagedPool, FullServiceName.MaximumLength); if (!FullServiceName.Buffer) { - ExFreePool(Node); + ExFreePoolWithTag(Node, TAG_IO_DEVNODE); return STATUS_INSUFFICIENT_RESOURCES; } @@ -1055,7 +1074,7 @@ if (!NT_SUCCESS(Status)) { DPRINT1("PnpRootCreateDevice() failed with status 0x%08X\n", Status); - ExFreePool(Node); + ExFreePoolWithTag(Node, TAG_IO_DEVNODE); return Status; } @@ -1064,7 +1083,7 @@ if (!NT_SUCCESS(Status)) { ZwClose(InstanceHandle); - ExFreePool(Node); + ExFreePoolWithTag(Node, TAG_IO_DEVNODE); ExFreePool(FullServiceName.Buffer); return Status; } @@ -1073,7 +1092,7 @@ if (!Node->ServiceName.Buffer) { ZwClose(InstanceHandle); - ExFreePool(Node); + ExFreePoolWithTag(Node, TAG_IO_DEVNODE); ExFreePool(FullServiceName.Buffer); return Status; } @@ -1122,7 +1141,7 @@ if (!NT_SUCCESS(Status)) { - ExFreePool(Node); + ExFreePoolWithTag(Node, TAG_IO_DEVNODE); return Status; } @@ -1225,7 +1244,8 @@ ExFreePool(DeviceNode->BootResources); } - ExFreePool(DeviceNode); + ((PEXTENDED_DEVOBJ_EXTENSION)DeviceNode->PhysicalDeviceObject->DeviceObjectExtension)->DeviceNode = (PVOID)0xfabbabad; + ExFreePoolWithTag(DeviceNode, TAG_IO_DEVNODE); return STATUS_SUCCESS; } @@ -2560,7 +2580,7 @@ DPRINT("IopActionInitChildServices(%p, %p)\n", DeviceNode, Context); - ParentDeviceNode = (PDEVICE_NODE)Context; + ParentDeviceNode = Context; /* * We are called for the parent too, but we don't need to do special @@ -2610,6 +2630,8 @@ PLDR_DATA_TABLE_ENTRY ModuleObject; PDRIVER_OBJECT DriverObject; + KeEnterCriticalRegion(); + ExAcquireResourceExclusiveLite(&IopDriverLoadResource, TRUE); /* Get existing DriverObject pointer (in case the driver has already been loaded and initialized) */ Status = IopGetDriverObject( @@ -2641,6 +2663,8 @@ if (!BootDrivers) DeviceNode->Problem = CM_PROB_DRIVER_FAILED_LOAD; } } + ExReleaseResourceLite(&IopDriverLoadResource); + KeLeaveCriticalRegion(); /* Driver is loaded and initialized at this point */ if (NT_SUCCESS(Status)) @@ -4664,29 +4688,32 @@ IN PDEVICE_OBJECT DeviceObject, IN DEVICE_RELATION_TYPE Type) { - PIO_WORKITEM WorkItem; PINVALIDATE_DEVICE_RELATION_DATA Data; + KIRQL OldIrql; Data = ExAllocatePool(NonPagedPool, sizeof(INVALIDATE_DEVICE_RELATION_DATA)); if (!Data) return; - WorkItem = IoAllocateWorkItem(DeviceObject); - if (!WorkItem) - { - ExFreePool(Data); - return; - } ObReferenceObject(DeviceObject); Data->DeviceObject = DeviceObject; Data->Type = Type; - Data->WorkItem = WorkItem; - IoQueueWorkItem( - WorkItem, - IopAsynchronousInvalidateDeviceRelations, - DelayedWorkQueue, - Data); + KeAcquireSpinLock(&IopDeviceRelationsSpinLock, &OldIrql); + InsertTailList(&IopDeviceRelationsRequestList, &Data->RequestListEntry); + if (IopDeviceRelationsRequestInProgress) + { + KeReleaseSpinLock(&IopDeviceRelationsSpinLock, OldIrql); + return; + } + IopDeviceRelationsRequestInProgress = TRUE; + KeReleaseSpinLock(&IopDeviceRelationsSpinLock, OldIrql); + + ExInitializeWorkItem(&IopDeviceRelationsWorkItem, + IopDeviceRelationsWorker, + NULL); + ExQueueWorkItem(&IopDeviceRelationsWorkItem, + DelayedWorkQueue); } /*