Книга: 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

Оглавление книги


Генерация: 1.005. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз