diff --git a/reactos/ntoskrnl/include/internal/io.h b/reactos/ntoskrnl/include/internal/io.h index dc80ff249a5..4f2b236156c 100644 --- a/reactos/ntoskrnl/include/internal/io.h +++ b/reactos/ntoskrnl/include/internal/io.h @@ -509,6 +509,14 @@ typedef struct _DEVICETREE_TRAVERSE_CONTEXT // // PNP Routines // +NTSTATUS +NTAPI +PipCallDriverAddDevice( + IN PDEVICE_NODE DeviceNode, + IN BOOLEAN LoadDriver, + IN PDRIVER_OBJECT DriverObject +); + VOID PnpInit( VOID @@ -563,6 +571,15 @@ IopFreeDeviceNode( ); NTSTATUS +NTAPI +IopSynchronousCall( + IN PDEVICE_OBJECT DeviceObject, + IN PIO_STACK_LOCATION IoStackLocation, + OUT PVOID *Information +); + +NTSTATUS +NTAPI IopInitiatePnpIrp( IN PDEVICE_OBJECT DeviceObject, IN PIO_STATUS_BLOCK IoStatusBlock, @@ -694,6 +711,12 @@ IoInitSystem( // // Device/Volume Routines // +VOID +NTAPI +IopReadyDeviceObjects( + IN PDRIVER_OBJECT Driver +); + NTSTATUS FASTCALL IopInitializeDevice( diff --git a/reactos/ntoskrnl/io/iomgr/device.c b/reactos/ntoskrnl/io/iomgr/device.c index 7434970734f..b9176ce276b 100644 --- a/reactos/ntoskrnl/io/iomgr/device.c +++ b/reactos/ntoskrnl/io/iomgr/device.c @@ -25,6 +25,24 @@ extern LIST_ENTRY IopTapeFsListHead; /* PRIVATE FUNCTIONS **********************************************************/ +VOID +NTAPI +IopReadyDeviceObjects(IN PDRIVER_OBJECT Driver) +{ + PAGED_CODE(); + PDEVICE_OBJECT DeviceObject; + + /* Set the driver as initialized */ + Driver->Flags |= DRVO_INITIALIZED; + DeviceObject = Driver->DeviceObject; + while (DeviceObject) + { + /* Set every device as initialized too */ + DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; + DeviceObject = DeviceObject->NextDevice; + } +} + VOID NTAPI IopDeleteDevice(IN PVOID ObjectBody) diff --git a/reactos/ntoskrnl/io/iomgr/driver.c b/reactos/ntoskrnl/io/iomgr/driver.c index 18202bfd5e4..1ab54458526 100644 --- a/reactos/ntoskrnl/io/iomgr/driver.c +++ b/reactos/ntoskrnl/io/iomgr/driver.c @@ -438,7 +438,6 @@ IopInitializeDriverModule( UNICODE_STRING RegistryKey; PDRIVER_INITIALIZE DriverEntry; PDRIVER_OBJECT Driver; - PDEVICE_OBJECT DeviceObject; NTSTATUS Status; DriverEntry = ModuleObject->EntryPoint; @@ -495,14 +494,7 @@ IopInitializeDriverModule( } /* Set the driver as initialized */ - Driver->Flags |= DRVO_INITIALIZED; - DeviceObject = Driver->DeviceObject; - while (DeviceObject) - { - /* Set every device as initialized too */ - DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; - DeviceObject = DeviceObject->NextDevice; - } + IopReadyDeviceObjects(Driver); if (PnpSystemInit) IopReinitializeDrivers(); diff --git a/reactos/ntoskrnl/io/pnpmgr/pnpinit.c b/reactos/ntoskrnl/io/pnpmgr/pnpinit.c index 8c5607289a6..24c8ba6753c 100644 --- a/reactos/ntoskrnl/io/pnpmgr/pnpinit.c +++ b/reactos/ntoskrnl/io/pnpmgr/pnpinit.c @@ -219,4 +219,116 @@ Quickie: return i; } +NTSTATUS +NTAPI +PipCallDriverAddDevice(IN PDEVICE_NODE DeviceNode, + IN BOOLEAN LoadDriver, + IN PDRIVER_OBJECT DriverObject) +{ + NTSTATUS Status; + HANDLE EnumRootKey, SubKey, ControlKey, ClassKey, PropertiesKey; + UNICODE_STRING ClassGuid, Properties; + UNICODE_STRING EnumRoot = RTL_CONSTANT_STRING(ENUM_ROOT); + UNICODE_STRING ControlClass = + RTL_CONSTANT_STRING(L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Class"); + PKEY_VALUE_FULL_INFORMATION KeyValueInformation = NULL; + PWCHAR Buffer; + + /* Open enumeration root key */ + Status = IopOpenRegistryKeyEx(&EnumRootKey, + NULL, + &EnumRoot, + KEY_READ); + if (!NT_SUCCESS(Status)) + { + DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); + return Status; + } + + /* Open instance subkey */ + Status = IopOpenRegistryKeyEx(&SubKey, + EnumRootKey, + &DeviceNode->InstancePath, + KEY_READ); + if (!NT_SUCCESS(Status)) + { + DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); + ZwClose(EnumRootKey); + return Status; + } + + /* Get class GUID */ + Status = IopGetRegistryValue(SubKey, + REGSTR_VAL_CLASSGUID, + &KeyValueInformation); + if (NT_SUCCESS(Status)) + { + /* Convert to unicode string */ + Buffer = (PVOID)((ULONG_PTR)KeyValueInformation + KeyValueInformation->DataOffset); + PnpRegSzToString(Buffer, KeyValueInformation->DataLength, &ClassGuid.Length); + ClassGuid.MaximumLength = KeyValueInformation->DataLength; + ClassGuid.Buffer = Buffer; + + /* Open the key */ + Status = IopOpenRegistryKeyEx(&ControlKey, + NULL, + &ControlClass, + KEY_READ); + if (!NT_SUCCESS(Status)) + { + /* No class key */ + DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); + ClassKey = NULL; + } + else + { + /* Open the class key */ + Status = IopOpenRegistryKeyEx(&ClassKey, + ControlKey, + &ClassGuid, + KEY_READ); + ZwClose(ControlKey); + if (!NT_SUCCESS(Status)) + { + /* No class key */ + DPRINT1("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); + ClassKey = NULL; + } + } + + /* Check if we made it till here */ + if (ClassKey) + { + /* Get the device properties */ + RtlInitUnicodeString(&Properties, REGSTR_KEY_DEVICE_PROPERTIES); + Status = IopOpenRegistryKeyEx(&PropertiesKey, + ClassKey, + &Properties, + KEY_READ); + if (!NT_SUCCESS(Status)) + { + /* No properties */ + DPRINT("IopOpenRegistryKeyEx() failed with Status %08X\n", Status); + PropertiesKey = NULL; + } + } + + /* Free the registry data */ + ExFreePool(KeyValueInformation); + } + + /* Do ReactOS-style setup */ + IopAttachFilterDrivers(DeviceNode, TRUE); + Status = IopInitializeDevice(DeviceNode, DriverObject); + if (NT_SUCCESS(Status)) + { + IopAttachFilterDrivers(DeviceNode, FALSE); + IopDeviceNodeSetFlag(DeviceNode, DNF_STARTED); + Status = IopStartDevice(DeviceNode); + } + + /* Return status */ + return Status; +} + /* EOF */ diff --git a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c index e5aee2001db..8862fd87bcd 100644 --- a/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c +++ b/reactos/ntoskrnl/io/pnpmgr/pnpmgr.c @@ -618,69 +618,90 @@ IopFreeDeviceNode(PDEVICE_NODE DeviceNode) } NTSTATUS -IopInitiatePnpIrp(PDEVICE_OBJECT DeviceObject, - PIO_STATUS_BLOCK IoStatusBlock, - ULONG MinorFunction, - PIO_STACK_LOCATION Stack OPTIONAL) +NTAPI +IopSynchronousCall(IN PDEVICE_OBJECT DeviceObject, + IN PIO_STACK_LOCATION IoStackLocation, + OUT PVOID *Information) { - PDEVICE_OBJECT TopDeviceObject; - PIO_STACK_LOCATION IrpSp; - NTSTATUS Status; - KEVENT Event; - PIRP Irp; - - /* Always call the top of the device stack */ - TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject); - - KeInitializeEvent( - &Event, - NotificationEvent, - FALSE); - - Irp = IoBuildSynchronousFsdRequest( - IRP_MJ_PNP, - TopDeviceObject, - NULL, - 0, - NULL, - &Event, - IoStatusBlock); - - /* PNP IRPs are initialized with a status code of STATUS_NOT_SUPPORTED */ - Irp->IoStatus.Status = STATUS_NOT_SUPPORTED; - Irp->IoStatus.Information = 0; - - if (MinorFunction == IRP_MN_FILTER_RESOURCE_REQUIREMENTS) - { - Irp->IoStatus.Information = (ULONG_PTR)Stack->Parameters.FilterResourceRequirements.IoResourceRequirementList; - } - - IrpSp = IoGetNextIrpStackLocation(Irp); - IrpSp->MinorFunction = (UCHAR)MinorFunction; - - if (Stack) - { - RtlCopyMemory(&IrpSp->Parameters, - &Stack->Parameters, - sizeof(Stack->Parameters)); - } - - Status = IoCallDriver(TopDeviceObject, Irp); - if (Status == STATUS_PENDING) - { - KeWaitForSingleObject(&Event, - Executive, - KernelMode, - FALSE, - NULL); - Status = IoStatusBlock->Status; - } - - ObDereferenceObject(TopDeviceObject); - - return Status; + PIRP Irp; + PIO_STACK_LOCATION IrpStack; + IO_STATUS_BLOCK IoStatusBlock; + KEVENT Event; + NTSTATUS Status; + PDEVICE_OBJECT TopDeviceObject; + PAGED_CODE(); + + /* Call the top of the device stack */ + TopDeviceObject = IoGetAttachedDeviceReference(DeviceObject); + + /* Allocate an IRP */ + Irp = IoAllocateIrp(TopDeviceObject->StackSize, FALSE); + if (!Irp) return STATUS_INSUFFICIENT_RESOURCES; + + /* Initialize to failure */ + Irp->IoStatus.Status = IoStatusBlock.Status = STATUS_NOT_SUPPORTED; + Irp->IoStatus.Information = IoStatusBlock.Information = 0; + + /* Initialize the event */ + KeInitializeEvent(&Event, SynchronizationEvent, FALSE); + + /* Set them up */ + Irp->UserIosb = &IoStatusBlock; + Irp->UserEvent = &Event; + + /* Queue the IRP */ + Irp->Tail.Overlay.Thread = PsGetCurrentThread(); + IoQueueThreadIrp(Irp); + + /* Copy-in the stack */ + IrpStack = IoGetNextIrpStackLocation(Irp); + *IrpStack = *IoStackLocation; + + /* Call the driver */ + Status = IoCallDriver(TopDeviceObject, Irp); + if (Status == STATUS_PENDING) + { + /* Wait for it */ + KeWaitForSingleObject(&Event, + Executive, + KernelMode, + FALSE, + NULL); + Status = IoStatusBlock.Status; + } + + /* Return the information */ + *Information = (PVOID)IoStatusBlock.Information; + return Status; } +NTSTATUS +NTAPI +IopInitiatePnpIrp(IN PDEVICE_OBJECT DeviceObject, + IN OUT PIO_STATUS_BLOCK IoStatusBlock, + IN ULONG MinorFunction, + IN PIO_STACK_LOCATION Stack OPTIONAL) +{ + IO_STACK_LOCATION IoStackLocation; + + /* Fill out the stack information */ + RtlZeroMemory(&IoStackLocation, sizeof(IO_STACK_LOCATION)); + IoStackLocation.MajorFunction = IRP_MJ_PNP; + IoStackLocation.MinorFunction = MinorFunction; + if (Stack) + { + /* Copy the rest */ + RtlCopyMemory(&IoStackLocation.Parameters, + &Stack->Parameters, + sizeof(Stack->Parameters)); + } + + /* Do the PnP call */ + IoStatusBlock->Status = IopSynchronousCall(DeviceObject, + &IoStackLocation, + (PVOID)&IoStatusBlock->Information); + return IoStatusBlock->Status; +} NTSTATUS IopTraverseDeviceTreeNode(PDEVICETREE_TRAVERSE_CONTEXT Context) @@ -2909,29 +2930,8 @@ IopActionInitChildServices(PDEVICE_NODE DeviceNode, /* Driver is loaded and initialized at this point */ if (NT_SUCCESS(Status)) { - /* Attach lower level filter drivers. */ - IopAttachFilterDrivers(DeviceNode, TRUE); - - /* Initialize the function driver for the device node */ - Status = IopInitializeDevice(DeviceNode, DriverObject); - - if (NT_SUCCESS(Status)) - { - /* Attach upper level filter drivers. */ - IopAttachFilterDrivers(DeviceNode, FALSE); - - Status = IopStartDevice(DeviceNode); - if (!NT_SUCCESS(Status)) - { - DPRINT1("IopStartDevice(%wZ) failed with status 0x%08x\n", - &DeviceNode->InstancePath, Status); - } - } - else - { - DPRINT1("IopInitializeDevice(%wZ) failed with status 0x%08x\n", - &DeviceNode->InstancePath, Status); - } + /* Initialize the device, including all filters */ + Status = PipCallDriverAddDevice(DeviceNode, FALSE, DriverObject); } else {