// Remember fdo in our device extension
PWDM1_DEVICE_EXTENSION dx = (PWDM1_DEVICE_EXTENSION)fdo->DeviceExtension;
dx->fdo = fdo;
…
// Attach to the driver stack below us
dx->NextStackDevice = IoAttachDeviceToDeviceStack{fdo,pdo);
// Set fdo flags appropriately
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
fdo->Flags |= DO_BUFFERED_IO;
…
}
NTSTATUS Wdm1Pnp( IN PDEVICE_OBJECT fdo, IN PIRP Irp) {
…
// Device removed
if (MinorFunction==IRP_MN_REMOVE_DEVICE) {
// unattach from stack if (dx->NextStackDevice)
IoDetachDevice(dx->NextStackDevice);
// delete our fdo
IoDeleteDevice(fdo);
}
return status;
}
Wdm1AddDevice is called with two parameters, a pointer to the driver object and a pointer to a device object called the Physical Device Object (PDO).
Wdm1AddDevice calls IoCreateDevice to create the Wdm1 device using the parameters described in Table 5.2. The DeviceName parameter can be used to give a name to the device. However, as Wdm1 uses device interfaces, no name needs to be given, so NULL is passed here. Wdm1 devices do not correspond to any of the hardware device types, so FILE_DEVICE_UNKNOWN is given for DeviceType.
Table 5.1
NTSTATUS IoCreateDevice | (IRQL==PASSIVE_LEVEL) |
---|---|
Parameter | Description |
IN PDRIVER_OBJECT DriverObject | Driver object |
IN ULONG DeviceExtensionSize | Size of device extension required |
IN PUNICODE_STRING DeviceName | Name of device, or NULL |
IN DEVICE_TYPE DeviceType | The type of the device: one of the FILE_DEVICE_xxx values listed in the standard header WDM.H or NTDDK.H |
IN ULONG DeviceCharacteristics | Various constants ORed together to indicate removable media, read only, etc. |
IN BOOLEAN Exclusive | TRUE if only a single thread can access the device at a time |
OUT PDEVICE_OBJECT* DeviceObject | The returned device object. |
Table 5.2
NTSTATUS IoRegisterDeviceInterface | (IRQL==PASSIVE_LEVEL) |
---|---|
Parameter | Description |
IN PDEVICE_OBJECT PhysicalDeviceObject | The device PDO |
IN CONST GUID *InterfaceClassGuid | The GUID being registered |
IN PUNICODE_STRING ReferenceString | Usually NULL. A reference string becomes part of the interface name and so can be used to distinguish between different interfaces to the same device. |
OUT PUNICODE_STRING SymbolicLinkName | The output interface symbolic link name. Do not forget to free the Unicode string buffer using RtlFreeUnicodeString when finished with it. |