Книга: Writing Windows WDM Device Drivers

Device Creation and Deletion

Device Creation and Deletion

The PHDIo DriverEntry routine delegates its device object creation to PHDIoCreateDevice, also in Init.cpp.

Listing 18.1 shows how PHDIo creates its device in PHDIoCreateDevice. Its kernel device name is DevicePHDIo and the Win32 symbolic link name is ??PHDIo. This is used by Win32 programs with a CreateFile filename of .PHDIo.

PHDIoCreateDevice first sets up UNICODE_STRINGs for the kernel and symbolic link names. It then calls IoCreateDevice in the same way as before. This creates the phddo device object and its associated device extension. The IoCreateDevice Exclusive parameter is TRUE indicating that only one Win32 application can open this device at a time.

All the appropriate fields are set up in the device extension, including the phddo field. The device timer is initialized with IoInitializeTimer and the device Deferred Procedure Call is initialized with IoInitializeDpcRequest. Finally, an explicit symbolic link is set up using IoCreateSymbolicLink. Device interfaces are not used.

Listing 18.1 NT style device creation

PDEVICE_OBJECT phddo = NULL;
#define NT_DEVICE_NAME L"DevicePHDIo"
#define SYM_LINK_NAME L"DosDevicesPHDIo"
NTSTATUS PHDIoCreateDevice(IN PDRIVER_OBJECT DriverObject {
 NTSTATUS status = STATUS_SUCCESS;
 // Initialise NT and Symbolic link names
 UNICODE_STRING deviceName, linkName;
 RtlInitUnicodeString(&deviceName, NT_DEVICE_NAME);
 RtlInitUnicodeString(&linkName, SYM_LINK_NAME);
 // Create our device
 DebugPrint("Creating device %T",&deviceName);
 status = IoCreateDevice(
  DriverObject,
  sizeof(PHDIO_DEVICE_EXTENSION),
  &deviceName,
  FILE_DEVICE_UNKNOWN,
  0,
  TRUE, // Exclusive
  &phddo);
 if (!NT_SUCCESS(status)) {
  DebugPrintMsg("Could not create device");
  return status;
 }
 phddo->Flags |= DO_BUFFEREO_IO;
 // Initialise device extension
 PPHDIO_DEVICE_EXTENSION dx = (PPHDIO_DEVICE_EXTENSION)phddo->DeviceExtension;
 dx->phddo = phddo;
 dx->UsageCount = 1;
 KeInitializeEvent(&dx->StoppingEvent, NotificationEvent, FALSE);
 dx->Stopping = false;
 dx->GotPortOrMemory = false;
 dx->GotInterrupt = false;
 dx->ConnectedToInterrupt = false;
 dx->SetTimeout = 10;
 dx->Timeout = –1;
 dx->StopTimer = false;
 dx->WriteCmds = NULL;
 dx->ReadCmds = NULL;
 dx->StartReadCmds = NULL;
 // Initialise timer for this device (but do not start)
 status = IoInitializeTimer(phddo, (PIO_TIMER_ROUTINE)Timeout1s, dx);
 if (!NT_SUCCESS(status)) {
  DebugPrintMsg("Could not initialise timer");
  IoDeleteDevice(phddo);
  return status;
 }
 // Create a symbolic link so our device is visible to Win32…
 DebugPrint("Creating symbolic link %T", &linkName);
 status = IoCreateSymbolicLink(&linkName, &deviceName);
 if (!NT_SUCCESS(status)) {
  DebugPrintMsg("Could not create symbolic link");
  IoDeleteDevice(phddo);
  return status;
 }
 // Initialise our DPC for IRQ completion processing
 IoInitializeDpcRequest(phddo, PHDIoDpcForIsr);
 return status;
}

When PHDIo is unloaded, its PHDIoUnload routine is called. This runs PHDIoDeleteDevice to stop the PHDIo device, remove its symbolic link, and delete its device object.

If a driver makes a variable number of devices, the unload routine could use the following technique to find all the devices to remove. The kernel sets the driver object DeviceObject field to point to the first device that belongs to the driver. The NextDevice field in each device object points to the next device. It is, therefore, a simple task to traverse this chain of device objects and delete them. The only catch is that you still have to generate the correct symbolic link name for each device so the symbolic link can be removed.

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


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