找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 201|回复: 0

【驱动笔记11】使用DeviceIoControl通信

[复制链接]

210

主题

371

回帖

0

积分

管理员

积分
0
发表于 2013-10-16 23:32:16 | 显示全部楼层 |阅读模式
[bgcolor=#ffffff]在我昨日发布的《驱动学习笔记系列文章汇总(PDF)》第11.2节中,我没有给出使用DeviceIoControl通信的演示源码,附录中附带的程序是我尚未调试好的,因此没有达到通信的目的。[/bgcolor]
[bgcolor=#ffffff]      今天又认真阅读了下张帆的《Windows驱动开发技术详解》第7章的内容,并对它给出的示例程序多次调试,总算把这个通信过程给理解了,下面我们先来看看应用层程序的代码:[/bgcolor]

[bgcolor=#ffffff]#include <windows.h>[/bgcolor]
[bgcolor=#ffffff]#include <stdio.h>[/bgcolor]
[bgcolor=#ffffff]#include <winioctl.h>[/bgcolor]
[bgcolor=#ffffff]#include "..\Ioctls.h"[/bgcolor]
[bgcolor=#ffffff][/bgcolor][bgcolor=#ffffff][/bgcolor]
[bgcolor=#ffffff]#define SYMBOL_LINK "\\\\.\\Test"[/bgcolor]
[bgcolor=#ffffff][/bgcolor][bgcolor=#ffffff][/bgcolor]
[bgcolor=#ffffff]int main()[/bgcolor]
[bgcolor=#ffffff]{[/bgcolor]
[bgcolor=#ffffff]    HANDLE hDevice = ::CreateFile(SYMBOL_LINK, [/bgcolor]
[bgcolor=#ffffff]                                GENERIC_READ | GENERIC_WRITE,[/bgcolor]
[bgcolor=#ffffff]                                0,    [/bgcolor]
[bgcolor=#ffffff]                                NULL,[/bgcolor]
[bgcolor=#ffffff]                                OPEN_EXISTING,[/bgcolor]
[bgcolor=#ffffff]                                FILE_ATTRIBUTE_NORMAL,[/bgcolor]
[bgcolor=#ffffff]                                NULL );[/bgcolor]
[bgcolor=#ffffff]    if (hDevice == INVALID_HANDLE_VALUE)[/bgcolor]
[bgcolor=#ffffff]    {[/bgcolor]
[bgcolor=#ffffff]        printf("Failed to Open Device : %d\n", ::GetLastError());[/bgcolor]
[bgcolor=#ffffff]        return -1;[/bgcolor]
[bgcolor=#ffffff]    }[/bgcolor]
[bgcolor=#ffffff][/bgcolor][bgcolor=#ffffff][/bgcolor]
[bgcolor=#ffffff]    UCHAR InputBuffer[10];[/bgcolor]
[bgcolor=#ffffff]    UCHAR OutputBuffer[10];[/bgcolor]
[bgcolor=#ffffff]    DWORD dwOutput;[/bgcolor]
[bgcolor=#ffffff]    [/bgcolor]
[bgcolor=#ffffff]    memset(InputBuffer, 0xAA, 10);[/bgcolor]
[bgcolor=#ffffff]    BOOL bRet = :eviceIoControl(hDevice, IOCTL_TEST, InputBuffer, 10, &OutputBuffer, 10, &dwOutput, NULL);[/bgcolor]
[bgcolor=#ffffff]    if (bRet)[/bgcolor]
[bgcolor=#ffffff]    {[/bgcolor]
[bgcolor=#ffffff]        printf("Output buffer:%d bytes\n",dwOutput);[/bgcolor]
[bgcolor=#ffffff]        for (int i=0;i<(int)dwOutput;i++)[/bgcolor]
[bgcolor=#ffffff]        {[/bgcolor]
[bgcolor=#ffffff]            printf("%02X ",OutputBuffer);[/bgcolor]
        }
        printf("\n");
    }

    CloseHandle(hDevice);
    return 0;
}
      其中Ioctls.h这个头文件没有实质作用,它是为了在驱动程序和应用层程序之间共享IOCTL定义而设立的,内容很简单,如下所示:
#ifndef IOCTLS_H
#define IOCTLS_H

#ifndef CTL_CODE
    #pragma message("CTL_CODE undefined. Include winioctl.h or wdm.h")
#endif

#define IOCTL_TEST \
            CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)

#endif
      我们再来看驱动程序,这里的xxxxDispatchDeviceControl函数需要作适当修改,如下所示:

NTSTATUS
TestDispatchDeviceControl(
    IN PDEVICE_OBJECT        DeviceObject,
    IN PIRP                    Irp
)
{
    NTSTATUS            Status = STATUS_SUCCESS;
    PIO_STACK_LOCATION    irpStack;
    ULONG                inBufLength, outBufLength;
    ULONG                i = 0;
    ULONG                ioControlCode;
    UCHAR                *InputBuffer, *OutputBuffer;
   
    irpStack = IoGetCurrentIrpStackLocation(Irp);
   
    inBufLength = irpStack->arameters.DeviceIoControl.InputBufferLength;
    outBufLength = irpStack->arameters.DeviceIoControl.OutputBufferLength;
    ioControlCode = irpStack->arameters.DeviceIoControl.IoControlCode;
   
    if (ioControlCode == IOCTL_TEST)
    {
        KdPrint(("[Test] IOCTL_TEST : 0x%X", ioControlCode));
        // 读取数据
        InputBuffer = (UCHAR *)Irp->AssociatedIrp.SystemBuffer;
        for (i = 0; i < inBufLength; i++)
        {
            KdPrint(("[Test] %X\n", InputBuffer));
        }
        
        // 写入数据
        OutputBuffer = (UCHAR *)Irp->AssociatedIrp.SystemBuffer;
        memset(OutputBuffer, 0xBB, outBufLength);
        
        Irp->IoStatus.Information = outBufLength;
    }
    else
    {
        KdPrint(("[Test] Unknown IOCTL: 0x%X (%04X,%04X)", \
                    ioControlCode, DEVICE_TYPE_FROM_CTL_CODE(ioControlCode), IoGetFunctionCodeFromCtlCode(ioControlCode)));

        Status = STATUS_INVALID_PARAMETER;
        Irp->IoStatus.Information = 0;
    }   
    // 完成IRP
    Irp->IoStatus.Status = Status;
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
   
    return Status;
}
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

果子博客
扫码关注微信公众号

Archiver|手机版|小黑屋|风叶林

GMT+8, 2026-2-1 15:12 , Processed in 0.075793 second(s), 20 queries .

Powered by 风叶林

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表