驱动层与应用层通信的实现

来源:互联网 发布:怎么网络报警电话 编辑:程序博客网 时间:2024/04/30 20:52
WDK环境搭建http://blog.csdn.net/spiderlily/article/details/8516439
通信的实现参照了这个帖子http://bbs.pediy.com/showthread.php?p=446641
我的第一个驱动层与应用层的通信程序实现搞了好长时间,同时鉴于我太菜,太官方的东西有时候需要把问题搞定了回头才能看懂,所以此篇记录本着通俗易懂非专业形式写出来,对于像这我样菜级别的希望能有所帮助。
新建个ddk项目,头文件中添加以下类似如下的项:
const ULONG IOCTL_IN= (ULONG)CTL_CODE(FILE_DEVICE_DRIVER17, 0x800, METHOD_IN_DIRECT, FILE_ANY_ACCESS)&0x0000FFFF;
const ULONG IOCTL_OUT =(ULONG)CTL_CODE(FILE_DEVICE_DRIVER17, 0x801, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)&0x0000FFFF;
const ULONG IOCTL_BUFFERED  =(ULONG)CTL_CODE(FILE_DEVICE_DRIVER17, 0x802, METHOD_BUFFERED, FILE_ANY_ACCESS)&0x0000FFFF;
const ULONG IOCTL_NEITHER=  (ULONG)CTL_CODE(FILE_DEVICE_DRIVER17, 0x803, METHOD_NEITHER, FILE_ANY_ACCESS)&0x0000FFFF;
关于CTL_CODE函数:
第一个参数根据头文件中自动生成的#define FILE_DEVICE_DRIVER17 0x8000来的;
第二个参数由我们自己定义,范围在0x800—0xfff之间就好;
第三个参数有四个选项,上面都包含了,具体说明和区别请参考(别人的博客)http://blog.csdn.net/lujunql/article...46901#comments
第四个参数有FILE_ANY_ACCESS、FILE_READ_ACCESS、FILE_WRITE_ACCESS,看词面就知道什么意思了;
这里的第三个与第四个参数有多种组合,只要把第二个参数设置成不同的就行。
这个函数返回的是一个ULONG型的数据,高16位表示设备类型,低16位是属性之类的定义,所以用&0x0000ffff目的在于仅保留低16位,因为在应用层,我调用设备时的设备类型选的是UNKNOWN,所以仅要低16位;应用层与驱动层通信要调用DeviceIoControl,而DeviceIoControl的第二个参数就是此处CTL_CODE返回的ULONG值,注意这里,由于设备类型我选的是UNKNOWN(0x22),所以这个返回值只有低16位与驱动层是一致的,所以判断的时候要减去0x00220000;

头文件好了,下面是在cpp文件中添加以下几个函数,我理解就是驱动层接到应用层命令后对应的分发处理函数,跟头文件对应;
NTSTATUS DirectOutIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *sizeofWrite);
NTSTATUS DirectInIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *sizeofWrite);
NTSTATUS BufferedIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *sizeofWrite);
NTSTATUS NeitherIo(PIRP Irp, PIO_STACK_LOCATION pIoStackIrp, UINT *sizeofWrite);
关键的地方在DRIVER17_DispatchDeviceControl函数里的如下部分,驱动层接到应用层的消息后,应该就是在这里处理的:
    irpStack = IoGetCurrentIrpStackLocation(Irp);    
    if(irpStack)
    {
    DbgPrint("irpStack\r\n");
    DbgPrint("%u",irpStack->Parameters.DeviceIoControl.IoControlCode);
        switch(irpStack->Parameters.DeviceIoControl.IoControlCode-0x00220000)  
        {
            case IOCTL_IN:          
                 status = DirectInIo(Irp, irpStack, &sizeofWrite);
                 break;

            case IOCTL_OUT:         
                 status = DirectOutIo(Irp, irpStack, &sizeofWrite);
                 break;

        case IOCTL_BUFFERED:          
                 status = BufferedIo(Irp, irpStack, &sizeofWrite);
                 break;

            case IOCTL_NEITHER:         
                 status = NeitherIo(Irp, irpStack, &sizeofWrite);
                 break;

      default:
        break;
        }
    }
应用层调用DeviceIoControl,关键在于第2个参数,也是通过CTL_CODE获取,这里的第二、三、四个参数要与驱动层的定义一致,否则会有各种错误出现
(ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, 0x802,METHOD_BUFFERED,
  FILE_ANY_ACCESS);这些东西弄明白了,实现两层的通信应该就没问题了,要下班了,写的有点乱,把代码上传了。
原创粉丝点击