Windows驱动设备栈疑问

在一个驱动创建多个设备对象 都是用的同一个派遣函数,IRP传递到设备栈,那到派遣函数里时候怎么区分是哪个目标设备请求的呢?,比如我应用程序是操作A设备,但是A的设备栈顶是B设备,在B派遣函数中(A和B实际是同一个派遣函数)怎么知道我是发给A的呢?就是在派遣函数里还要实现 多个设备的判断呢?

DEVICE_OBJECT 结构体中有个成员是 DeviceExtension, 这个成员就是给你自定义用的, 你在用 IoCreateDevice 创建设备时指定创建DeviceExtension的大小, 系统会自动给你创建内存,然后你自己初始化,并设置用于区分不同设备的字段, 然后在执行IRP请求时取出用来区分

typedef struct {
    char name;
}MY_DEVICE_EXTENSION ;

// 添加时
status = IoCreateDevice(DriverObject, sizeof(MY_DEVICE_EXTENSION),
                           &deviceObjName, device_type,
                           device_characteristics, TRUE, &deviceObject);

   MY_DEVICE_EXTENSION*  pDevExt = deviceObject->DeviceExtension;
   RtlZeroMemory(pDevExt, sizeof(MY_DEVICE_EXTENSION ));
pDevExt->name = 'A'; 

// 处理时
MY_DEVICE_EXTENSION*  pDevExt = deviceObject->DeviceExtension;
if( pDevExt->name == 'A' ){
    .....
}else if( ... ) ...

在驱动程序中,可以通过使用设备对象来区分不同的设备请求。每个设备对象代表一个具体的设备实例,并且设备对象会在IRP传递到设备栈时作为参数传递给派遣函数。通过检查设备对象,可以确定请求是来自哪个设备。
假设你的驱动创建了多个设备对象,且它们共用同一个派遣函数。在派遣函数中,你可以获取IRP所关联的设备对象,并根据这个设备对象来区分是哪个设备请求的。在IRP传递到设备栈的过程中,设备对象会在每个驱动层级中被逐层更新,以指向当前处理该IRP的设备对象。
以下是一个简单的示例代码片段,演示了如何在派遣函数中区分多个设备:

NTSTATUS DispatchRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
    // 获取当前处理的设备对象
    PDEVICE_OBJECT currentDevice = DeviceObject;

    // 根据设备对象区分设备
    if (currentDevice == A_Device_Object) {
        // 处理 A 设备的请求
    } else if (currentDevice == B_Device_Object) {
        // 处理 B 设备的请求
    } else {
        // 未知的设备对象,可能发生错误
        // 可以选择直接完成IRP或者传递给下一层驱动
    }

    // 继续处理IRP(例如传递给下一层驱动)
    IoSkipCurrentIrpStackLocation(Irp);
    return IoCallDriver(DeviceObject, Irp);
}

在这个示例中,A_Device_Object和B_Device_Object是你在驱动中保存的指向A设备和B设备的设备对象指针。通过比较DeviceObject与这些设备对象指针,你可以确定IRP是来自哪个设备,并做出相应的处理。
当然,实际的驱动开发可能更为复杂,涉及更多的设备对象和设备栈操作。但核心的思想仍然是通过设备对象来区分不同的设备请求。

参考 https://blog.csdn.net/qq_42814021/article/details/121008646

引用GPT: 在一个驱动中创建多个设备对象,并且它们共享同一个派遣函数时,可以使用以下方法来区分目标设备请求:

  1. 在每个设备对象的扩展(Extension)结构中添加一个标识符字段,用于唯一标识设备对象。这个标识符可以是设备的硬件ID、设备名称或其他唯一标识符。在处理IRP时,通过检查IRP所属的设备对象的标识符,来判断是哪个设备发起的请求。

  2. 在派遣函数中,通过访问当前IRP所附加的设备对象,获取设备对象的扩展结构。然后,从扩展结构中提取设备标识符并与预先保存的标识符进行比较,以确定是哪个设备发起的请求。例如,可以在初始化设备对象时将设备标识符保存到设备对象的扩展结构中。

下面是一个示例代码,展示了如何在驱动中处理多个设备对象的请求:

// 定义设备扩展结构
typedef struct _DEVICE_EXTENSION {
    // 设备标识符
    ULONG DeviceId;
    // 其他设备相关的字段
    // ...
} DEVICE_EXTENSION, * PDEVICE_EXTENSION;

// 派遣函数
NTSTATUS DispatchRoutine(PDEVICE_OBJECT DeviceObject, PIRP Irp) {
    PDEVICE_EXTENSION deviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension;
    ULONG deviceId = deviceExtension->DeviceId;
    
    // 根据设备标识符deviceId,判断是哪个设备发起的请求,执行相应的逻辑

    return STATUS_SUCCESS;
}