Home > Articles > Operating Systems, Server > Microsoft Windows Desktop

  • Print
  • + Share This
Like this article? We recommend

Like this article? We recommend

Creating the Device Object, Device Interface, and I/O Queue: EvtDriverDeviceAdd

Every KMDF driver that supports Plug and Play must have an EvtDriverDeviceAdd callback function, which is called each time the system enumerates a device that belongs to the driver. This callback performs actions required at device enumeration, such as the following:

  • Creates and initializes a device object (WDFDEVICE) and corresponding context area.
  • Sets entry points for the driver’s Plug and Play and power management callbacks.
  • Creates a device interface.
  • Configures and creates one or more I/O queues.
  • Creates an interrupt object, if the device controls physical hardware that generates interrupts.

The EvtDriverDeviceAdd function is called with two parameters: a handle to the WDFDRIVER object that the driver created during DriverEntry and a handle to a WDFDEVICE_INIT object.

The Simple Toaster does not control hardware, so it does not set Plug and Play or power management callbacks, nor does it create an interrupt object. Its EvtDriverDeviceAdd callback creates the device object and context areas, device interface, and a single default I/O queue. The following shows the source code for this function:

NTSTATUS
ToasterEvtDeviceAdd(
    IN WDFDRIVER                Driver,
    IN PWDFDEVICE_INIT   DeviceInit
    )
{
    NTSTATUS                                   status = STATUS_SCCESS;
    PFDO_DATA                               fdoData;
    WDF_IO_QUEUE_CONFIG      queueConfig;
    WDF_OBJECT_ATTRIBUTES    fdoAttributes;
    WDFDEVICE                              hDevice;
    WDFQUEUE                               queue;
    UNREFERENCED_PARAMETER(Driver);

    PAGED_CODE();
    KdPrint ((“ToasterEvtDeviceAdd called\n”));
    //
    // Initialize attributes and a context area for the device object.
    //

    WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE (
              &fdoAttributes, FDO_DATA);
    //
    // Create a framework device object.
    //
    status = WdfDeviceCreate(&DeviceInit, &fdoAttributes, &hDevice);
    if (!NT_SUCCESS(status)) {
        KdPrint ((“WdfDeviceCreate failed with status code” “0x%x\n”, status));
        return status
    }
    //
    // Get the device context by using the accessor function
    // specified in the WDF_DECLARE_CONTEXT_TYPE_WITH_NAME
    // macro for FDO_DATA.
    //
    fdoData = ToasterFdoGetData(hDevice);
    //
    // Create device interface.
    //
   status = WdfDevice(CreateDeviceInterface (
                     hDevice,
                     (LPUID &GUID)DEVINTERFACE_TOASTER,
                     NULL              // Reference String
                     );

    If (!NT_SUCCESS(status)) {
       KdPrint ((“WdfDeviceCreateDeviceInterface failed “0x%x\n”, status));
       return status;
    }
    //
    // Configure the default I/O queue.
    //
   WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(&queueConfig,
               WdfIoQueueDispatchParallel);
   //
   // Register I/O callbacks for IRP_MJ_READ, IRP_MJ_WRITE,
   // and IRP_MJ_DEVICE_CONTROL request.
   //
   queueConfig.EvtIoRead = ToasterEvtIoRead;
   queueConfig.EvtIoWrite = ToasterEvtIoWrite;
    queueConfig.EvtIoDeviceControl = ToasterEvtIoDeviceControl;
    //
    // Create the queue.
    //
    status = WdfIoQueueCreate (
           hDevice,
           &queueConfig,
          WDF_NO_OBJECT_ATTRIBUTES,
          &queue
          );

   If (!NT_SUCCESS(status)) {
      KdPrint ((“WdfIoQueueCreate failed 0x%x\n, status));
      return status;
   }
return status;
}

Conclusion

You can see from this article’s discussion that the sample drivers can give you a good place to start the development of your Kernel Mode driver.

  • + Share This
  • 🔖 Save To Your Account