Книга: Writing Windows WDM Device Drivers
Creating and Deleting Device Objects
Разделы на этой странице:
Creating and Deleting Device Objects
Wdm1 creates and deletes devices in the Pnp.cpp module as shown in Listing 5.2. The chapter on Plug and Play explains when the Wdm1AddDevice and Wdm1Pnp routines are called.
The NT_SUCCESS macro is used to test whether the IoCreateDevice kernel call has completed. Do not forget to check that all calls to the kernel succeed. The NT_ERROR macro is not equivalent to !NT_SUCCESS. It is better to use !NT_SUCCESS, as it catches warning status values as well as errors.
Listing 5.2 Wdm1 Pnp.cpp Create and Delete device code
NTSTATUS Wdm1AddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT pdo) {
…
NTSTATUS status;
PDEVICE_OBJECT fdo;
// Create our Functional Device Object in fdo
status = IoCreateDevice(DriverObject, sizeof(WDM1_DEVICE_EXTENSION),
NULL, // No Name
FILE_DEVICE_UNKNOWN, 0,
FALSE, // Not exclusive
&fdo);
if (!NT_SUCCESS(status)) return status;
// 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;
}
Creating Devices
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 IoCreateDevice function
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 IoRegisterDeviceInterface function
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. |
If IoCreateDevice returns successfully, the DeviceObject parameter is set to point to the new device object. Wdm1 calls this its Functional Device Object (FDO). The Plug and Play chapter explains FDOs and PDOs in detail. Wdm1AddDevice returns an error if IoCreateDevice fails.
The Wdm1 device extension is now available through the FDO DeviceExtension field. Wdm1AddDevice stores a pointer to the FDO in its device extension.
Wdm1AddDevice now attaches the Wdm1 device to the device stack using IoAttachDeviceToDeviceStack, which must be called at PASSIVE_LEVEL[11]. The FDO and the given PDO are passed to this function. It returns a pointer to yet another device object that is also stored in the Wdm1 device extension. All this shenanigans are explained in the Plug and Play chapters.
Finally, two bits in the FDO Flags field must be changed. AddDevice routines must clear the DO_DEVICE_INITIALIZING flag. You do not need to clear this flag if you call IoCreateDevice in your DriverEntry routine. The DO_BUFFERED_IO flag is set in the Flags field. Again, this is covered later.
Deleting Devices
The Wdm1 driver must delete its FDO if it receives a Remove Device request. This is an IRP_ MJ_PNP_IRP with an IRP_MN_REMOVE_DEVICE minor version code. The code in Wdm1Pnp first calls IoDetachDevice to detach the FDO from the device stack. Finally, IoDeleteDevice is called to delete the FDO and its device extension.
IoDetachDevice and IoDeleteDevice must be called at IRQL PASSIVE_LEVEL
- Deleting Users
- Using Exception Objects
- Chapter 5 Device Interfaces
- Creating a Custom CETK Test Solution
- Function Objects
- Predefined function objects
- Разработка приложений баз данных InterBase на Borland Delphi
- Open Source Insight and Discussion
- Introduction to Microprocessors and Microcontrollers
- Chapter 6. Traversing of tables and chains
- Chapter 8. Saving and restoring large rule-sets
- Chapter 11. Iptables targets and jumps