must be called at DISPATCH_LEVEL IRQL or lower.

PnpDefaultHandler therefore simply sets up the stack location and passes the IRP to the next lower driver in the device stack. It does not wait for the IRP to complete. It returns the status code that IoCallDriver returns.

Listing 9.4 Wdm2 PnpDefaultHandler

NTSTATUS PnpDefaultHandler(IN PDEVICE_OBJECT fdo, IN PIRP Irp) {

 DebugPrintMsg('PnpDefaultHandler');

 PWDM2_DEVICE_EXTENSI0N dx=(PWDM2_DEVICE_EXTENSION)fdo->DeviceExtension;

 IoSkipCurrentIrpStackLocation(Irp);

 return IoCallDriver(dx->NextStackDevice, Irp);

}

PnP States and Messages

Before continuing with the rest of the PnP implementation, it is worth looking again at the Plug and Play message and state diagram that was shown in the last chapter.

Figure 9.1 shows the main theoretical device states that a device can be in and the messages that are sent to change between these states. As mentioned before, a message such as START_DEVICE in this diagram corresponds to a PnP IRP with a minor code of IRP_MN_START_ DEVICE.

Note that I said 'theoretical' device states. There are no visible flags in the kernel device structure that say which state a device is in. Wdm2 has to maintain its own state variables.

Another important point to note is that your code should be prepared to accept more-or-less any message from any state. The DDK documentation says in at least two places that an unexpected message may occasionally be sent when in one particular state.

Figure 9.1 Plug and Play device states and messages

State Flags

The device extension for Wdm2 device objects is shown in Listing 9.5. Four state flags are used to ensure that I/O requests are only begun when the device is in the Started state.

Paused Device has a remove pending or stop pending
GotResources Device running normally or paused (i.e., not stopped)
IODisabled Paused or stopped
Stopping Device is in process of being removed or stopped

The GotResources flag is set when the device has retrieved and allocated any hardware resources that it needs. In Figure 9.1, the GotResources flag is set when the device is in the Started, Stop pending, and Remove Pending states.

The Paused flag is set when the device is in the Stop Pending or Remove Pending States.

The IODisabled flag is set when GotResources is false or Paused is true (i.e., in the Stoppending, Remove Pending, Stopped, and Surprise removed states).

The Stopping flag is used during the processing of Remove Device and Stop Device messages, as described in the following text.

In the Device not present state, a device object and its flags simply do not exist.

Some devices may want to have an InterruptsEnabled flag, as well, to indicate when device interrupts are enabled.

Listing 9.5 Wdm2 device extension

typedef struct _WDM2_DEVICE_EXTENSION {

 PDEVICE_OBJECT fdo;

 PDEVICE_OBJECT NextStackDevice;

 UNICODE_STRING ifSymLinkName;

 bool GotResources; // Not stopped

 bool Paused; // Stop or remove pending

 bool IODisabled; // Paused or stopped

 LONG OpenHandleCount; // Count of open handles

 LONG UsageCount; // Pending I/O Count

 bool Stopping; // In process of stopping

 KEVENT StoppingEvent; // Set when all pending I/O complete

 DEVICE_POWER_STATE PowerState; // Our device power state

 PULONG PowerIdleCounter; // Device idle counter

 // Resource allocations

 bool GotPortOrMemory;

 bool PortInIOSpace;

 bool PortNeedsMapping;

 PUCHAR PortBase;

 PHYSICAL_ADDRESS PortStartAddress;

 ULONG PortLength;

 bool GotInterrupt;

 ULONG Vector;

 KIRQL Irql;

 KINTERRUPT_MODE Mode;

 KAFFINITY Affinity;

 PKINTERRUPT InterruptObject;

} WDM2_DEVICE_EXTENSION, *PWDM2_DEVICE_EXTENSION;

The GotResources flag indicates that Wdm2 has been assigned its resources. Wdm2 does not use any hardware resources. However, it still needs this flag to indicate the state it is in.

The Paused flag has no hardware interpretation. It is simply a way of stopping IRPs from starting when in the Stop Pending or Remove Pending states. In a full PnP implementation, IRPs must be queued while the Paused flag is set. Wdm2 should never get in the Stop Pending state, as it has no resources to reallocate. It should only be in the Remove Pending state briefly. For simplicity sake, Wdm2 does not queue IRPs. Chapter 16 gives this subject the full airing it deserves.

The IODisabled flag is provided so that the dispatch routines have to check only one flag quickly, not both GotResources and Paused. Each normal IRP dispatch routine, therefore, has the following code at the top that fails the IRP straightaway with an appropriate error code if the device is disabled.

if (dx->IODisabled) return CompleteIrp(Irp, STATUS_DEVICE_NOT_CONNECTED, 0);

To recap, three flags in the Wdm2 device extension are used to ensure that normal I/O requests are permitted only when the Wdm2 device is fully started. In fact, there will be very few times in the life of a Wdm2 device when I/O requests are not permitted. (Strictly speaking, I could have combined the Paused and IODisabled flags, but it is clearer to have them

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату
×