有3种常用方式:METHOD_BUFFERED METHOD_IN_DIRECT METHOD_OUT_DIRECT
还有METHOD_NEITHER,《windows设备驱动WDF开发》描述为:源自win 9x的VxD的模式,不建议读者掌握。这个就不管了。
METHOD_BUFFERED:无论读和写都对应同一缓冲区
METHOD_IN_DIRECT\ METHOD_OUT_DIRECT:输入缓冲区可作为附加输出缓冲区,输出缓冲区可作为附加输入缓冲区,两者区别只在DMA读写要分清,详见《windows设备驱动WDF开发》的DMA_Sample
举简例:
应用层DeviceIoControl传两个UNCHAR数(2 和 4)的地址给驱动。
驱动读取地址提取数值,两数相加完成请求返还给应用层。
以上过程分别以:METHOD_BUFFERED METHOD_IN_DIRECT METHOD_OUT_DIRECT 各执行一次
结果:
驱动层EvtDeviceIoControl例程读取处理部分:
#define IOSample_IOCTL_BUFFERED CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOSample_IOCTL_IN_DIRECT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_IN_DIRECT, FILE_ANY_ACCESS)
#define IOSample_IOCTL_OUT_DIRECT CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
switch(IoControlCode)
{
case IOSample_IOCTL_BUFFERED:
case IOSample_IOCTL_IN_DIRECT:
case IOSample_IOCTL_OUT_DIRECT:
if (InputBufferLength == 0 || OutputBufferLength == 0)
{ //检查输入、输出参数有效性
WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
}
else
{
//METHOD_BUFFERED,METHOD_OUT_DIRECT,METHOD_IN_DIRECT三种方式,
//输入缓冲区地址可通过调用WdfRequestRetrieveInputBuffer函数获得
//输出缓冲区地址可通过调用WdfRequestRetrieveOutputBuffer函数获得
//获取输入缓冲区地址buffer
status = WdfRequestRetrieveInputBuffer(Request, 1, &buffer, NULL);
if (!NT_SUCCESS(status))
{
WdfRequestComplete(Request, STATUS_UNSUCCESSFUL);
break;
}
//buffer表示输入缓冲区地址
//输入x1=应用程序传给驱动程序的数字
x1 = *(UCHAR *)buffer;
//获取输出缓冲区地址buffer
status = WdfRequestRetrieveOutputBuffer(Request, 1, &buffer, NULL);
if (!NT_SUCCESS(status))
{
WdfRequestComplete(Request, STATUS_UNSUCCESSFUL);
break;
}
//输入x2=应用程序通过输出缓冲区传给驱动程序的数字
x2 = *(UCHAR *)buffer;
*(UCHAR *)buffer=x1+x2;
//完成I/O请求,驱动程序传给应用程序的数据长度为1字节
WdfRequestCompleteWithInformation(Request, STATUS_SUCCESS, 1);
}
break;
default :
status = STATUS_INVALID_DEVICE_REQUEST;
WdfRequestCompleteWithInformation(Request, status, 0);
break;
}
分析:对于METHOD_BUFFERED:
驱动层输入输出缓冲区对应应用层的输入缓冲区和输出缓冲区,WdfRequestRetrieveInputBuffer和WdfRequestRetrieveOutputBuffer都读取同一位置,所以2+2=4。那个6的地址在驱动层是不可读的,他只是应用层接受来自驱动的输出结果
对于METHOD_OUT_DIRECT,METHOD_IN_DIRECT:
驱动层输入缓冲区,驱动层输出缓冲区分别于应用层对应。所以那个6的地址对于驱动层是可读的,实际上这就是所谓“输出缓冲区可作为附加的输入缓冲区”