Windows驱动
+ -

Windows应用层写数据到驱动

2021-07-01 484 1

应用层传入信息的时候,可以使用WriteFile,也可以使用DeviceIoControl。DeviceIoControl是双向的,在读取设备的信息也可以使用。因此本书以DeviceIoControl为例子进行说明。DeviceIoControl称为设备控制接口。其特点是可以发送一个带有特定控制码的IRP。同时提供输入和输出缓冲区。应用程序可以定义一个控制码,然后把相应的参数填写在输入缓冲区中。同时可以从输出缓冲区得到返回的更多信息。

当驱动得到一个DeviceIoControl产生的IRP的时候,需要了解的有当前的控制码、输入缓冲区的位置和长度,以及输出缓冲区的位置和长度。其中控制码必须预先用一个宏定义。定义的示例如下:

    #define MY_DVC_IN_CODE \
        (ULONG)CTL_CODE(FILE_DEVICE_UNKNOWN, \
            0xa01, \
            METHOD_BUFFERED, \
            FILE_READ_DATA|FILE_WRITE_DATA)

其中0xa01这个数字是用户可以自定义的。其他的参数请照抄。
下面是获得这三个要素的例子:

    NTSTATUS MyDeviceIoControl(
        PDEVICE_OBJECT    dev,
        PIRP    irp)
    {
        // 得到irpsp的目的是为了得到功能号、输入输出缓冲
        // 长度等信息。
        PIO_STACK_LOCATION irpsp = 
            IoGetCurrentIrpStackLocation(irp);
        // 首先要得到功能号
        ULONG code = irpsp->Parameters.DeviceIoControl.IoControlCode;
        // 得到输入输出缓冲长度
        ULONG in_len = 
            irpsp->Parameters.DeviceIoControl.InputBufferLength;
        ULONG out_len =
            irpsp->Parameters.DeviceIoControl.OutputBufferLength;
        // 请注意输入输出缓冲是公用内存空间的
        PVOID buffer = irp->AssociatedIrp.SystemBuffer;

        // 如果是符合定义的控制码,处理完后返回成功
        if(code == MY_DVC_IN_CODE)
        {
            … 在这里进行需要的处理动作

            // 因为不返回信息给应用,所以直接返回成功即可。
            // 没有用到输出缓冲
            irp->IoStatus.Information = 0;
            irp->IoStatus.Status = STATUS_SUCCESS;            
        }
        else
        {
            // 其他的请求不接受。直接返回错误。请注意这里返
            // 回错误和前面返回成功的区别。
            irp->IoStatus.Information = 0;
            irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
        }
           IoCompleteRequest (irp,IO_NO_INCREMENT);
        return irp->IoStatus.Status;
    }

在前面设置分发函数的时候,要加上:

    DriverObject->MajorFunctions[IRP_MJ_DEVICE_CONTROL] = MyCreateClose;
应用程序方面,进行DeviceIoControl的代码如下:
    HANDLE device=CreateFile("\\\\.\\MyCDOSL",
        GENERIC_READ|GENERIC_WRITE,0,0,
        OPEN_EXISTING,
        FILE_ATTRIBUTE_SYSTEM,0);
    BOOL ret;
    DWORD length = 0;            // 返回的长度

if (device == INVALID_HANDLE_VALUE)
{
    // … 打开失败,说明驱动没加载,报错即可
}

    BOOL ret = DeviceIoControl(device,
        MY_DVC_IN_CODE,        // 功能号
        in_buffer,            // 输入缓冲,要传递的信息,预先填好
        in_buffer_len,        // 输入缓冲长度
        NULL,                // 没有输出缓冲
        0,                    // 输出缓冲的长度为0
        &length,            // 返回的长度    
        NULL);                

if(!ret)
{
    // … DeviceIoControl失败。报错。
}

// 关闭
CloseHandle(device);

0 篇笔记 写笔记

作者信息
我爱内核
Windows驱动开发,网站开发
好好学习,天天向上。
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!