用DeviceIoControl实现与驱动的交互(包含exe和sys两部分)

主要实现的功能是:

通过调用驱动,实现相应的功能,并把结果返回给调用者

(1)这里是通过应用程序出入两个参数a和b,

(2)然后调用驱动,在驱动里面实现这里个数的相加

(3)驱动把相加的结果作为参数通过缓冲区返回给应用程序

1.缓冲区内存模式IOCTL



/*************************************************************exe部分***************************************************/

/********************************ioctl_test.h*************************/

#ifndef CTL_CODE
#pragma message("\n\n --------EXE模式 . Include winioctl.h ")
#include<winioctl.h>    // <NTDDK.H> <WDM.H>包含CTL_CODE
#else
#pragma message("\n\n --------SYS模式 . Include winioctl.h ")
#endif
#define add_code CTL_CODE(FILE_DEVICE_UNKNOWN,\
0x800, METHOD_BUFFERED,FILE_ANY_ACCESS)
#define sub_code CTL_CODE(FILE_DEVICE_UNKNOWN,\
  0x801, METHOD_BUFFERED,FILE_ANY_ACCESS)


/********************************************************************/

/*****************************ioctl_test.cpp*************************/

#include "stdafx.h"
#include <windows.h>
#include "ioctl_test.h"


int Add(HANDLE hDevice,int a,int b)
{
int inputBuffer[2];
int OutBuf;
DWORD dwWrite;
inputBuffer[0]=a;
inputBuffer[1]=b;
DeviceIoControl(
hDevice,         // handle to device
add_code,        // operation control code
&inputBuffer,    // input data buffer
8,               // size of input data buffer
&OutBuf,         // output data buffer
4,               // size of output data buffer
&dwWrite,        // byte count
NULL);           // overlapped information


return OutBuf; //return the result
}
int main(int argc, char* argv[])
{
HANDLE hDevice =  CreateFile(
"\\\\.\\junHelloDDK",            // file name
GENERIC_READ | GENERIC_WRITE,    // access mode
0, // share mode
NULL,                            // SD
OPEN_EXISTING,                   // how to create
FILE_ATTRIBUTE_NORMAL,           // file attributes
NULL);                           // handle to template file


printf("start\n");
if (hDevice == INVALID_HANDLE_VALUE)
{
printf("调用CreateFile失败 %s with Win32 error code: %d\n","MyDriver", GetLastError());
getchar(); //suspend
return -1;
}
int a = 55;
int b = 33;
int r =Add(hDevice,a,b);
printf("%d+%d=%d\n",a,b,r);
CloseHandle(hDevice);  
getchar(); //suspend
return 0;
}


/********************************************************************/
/**********************************************************************************************************************/

/*************************************************************sys部分***************************************************/

只贴处理IRP_MJ_DEVICE_CONTROL部分:

NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp) 
{
NTSTATUS status = STATUS_SUCCESS;
KdPrint(("进入派遣函数 ******\n"));
ULONG info = 0;
//得到当前堆栈
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
UCHAR mf = stack->MajorFunction; //区分IRP
switch(mf)
{
case IRP_MJ_DEVICE_CONTROL:
{
KdPrint(("Enter myDriver_DeviceIOControl\n"));
//得到输入缓冲区大小
ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
//得到输出缓冲区大小
ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;
//得到IOCTL码
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
switch(code)
{
case add_code:
{
KdPrint(("add_code....\n"));
//缓冲区方式IOCTL
//显示输入缓冲区数据
int *InputBuffer = (int*) pIrp->AssociatedIrp.SystemBuffer;
int a,b,sum;
a = InputBuffer[0];
b = InputBuffer[1];
KdPrint(("a=%d,b=%d\n",a,b));
sum = a+b;
int *OutputBuffer = (int *)pIrp->AssociatedIrp.SystemBuffer;
*OutputBuffer = sum;
KdPrint(("a+b=%d\n",sum));
//设置实际操作输出缓冲区长度
info = cbout;
break;
}
case sub_code:
{
info = cbout;
break;
}
default:
status = STATUS_INVALID_VARIANT;
}
break;
}
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
case IRP_MJ_WRITE:
case IRP_MJ_READ:
break;
}

// 完成IRP 
pIrp->IoStatus.Status = status;     // 设置IRP的状态为成功 
pIrp->IoStatus.Information = info;         // 设置操作的字节数为0 
IoCompleteRequest( pIrp, IO_NO_INCREMENT ); // 指示完成此IRP
KdPrint(("离开派遣函数......\n"));          // 打印调试信息 
return status; // 返回成功 
}



2.直接内存模式IOCTL

在1.缓冲区内存模式IOCTL的基础上需要改动的地方:

/************************************************************exe部分***************************************************/

/********************************ioctl_test.h*************************/

将 METHOD_BUFFERED 改为 METHOD_IN_DIRECT

/************************************************************sys部分***************************************************/

int *OutputBuffer = (int *)pIrp->AssociatedIrp.SystemBuffer;

改为

int *OutputBuffer = (int *)MmGetSystemAddressForMdlSafe(pIrp->MdlAddress,NormalPagePriority);


3.其他内存模式IOCTL

在1.缓冲区内存模式IOCTL的基础上需要改动的地方:

/************************************************************exe部分***************************************************/

/********************************ioctl_test.h*************************/

将 METHOD_BUFFERED 改为 METHOD_NEITHER

/************************************************************sys部分***************************************************/

#pragma PAGEDCODE /*表示内存不足时,可以被置换到硬盘 的代码段*/
NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp) 
{
NTSTATUS status = STATUS_SUCCESS;
KdPrint(("进入派遣函数 ******\n"));
ULONG info = 0;
//得到当前堆栈
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(pIrp);
UCHAR mf = stack->MajorFunction; //区分IRP
switch(mf)
{
case IRP_MJ_DEVICE_CONTROL:
{
KdPrint(("Enter myDriver_DeviceIOControl\n"));
//得到输入缓冲区大小
ULONG cbin = stack->Parameters.DeviceIoControl.InputBufferLength;
//得到输出缓冲区大小
ULONG cbout = stack->Parameters.DeviceIoControl.OutputBufferLength;
//得到IOCTL码
ULONG code = stack->Parameters.DeviceIoControl.IoControlCode;
switch(code)
{
case add_code:
{
KdPrint(("add_code....\n"));
//缓冲区方式IOCTL
//显示输入缓冲区数据
int *UserInputBuffer = (int*) stack->Parameters.DeviceIoControl.Type3InputBuffer;
KdPrint(("UserInputBuffer:0x%0X \n",UserInputBuffer));
//得到用户模式地址
int *UserOutputBuffer = (int *)pIrp->UserBuffer;
KdPrint(("UserOutputBuffer:0x%0X \n",UserOutputBuffer));
__try
{
KdPrint(("Entry __try block \n"));
//判断指针是否可读
ProbeForRead(UserInputBuffer,cbin,4);
//显示缓冲区内容

int a,b,sum;
a = UserInputBuffer[0];
b = UserInputBuffer[1];
KdPrint(("a=%d,b=%d\n",a,b));
sum = a+b;
KdPrint(("a+b=%d\n",sum));
sum += 3;
//判断指针是否可写
ProbeForWrite(UserOutputBuffer,cbout,4);
//操作输出缓冲区
*UserOutputBuffer = sum;

info = cbout;
KdPrint(("Leave __try block \n"));

}
__except(EXCEPTION_EXECUTE_HANDLER)
{
KdPrint(("发生异常 缓冲区不可读 或 写 \n"));
status = STATUS_UNSUCCESSFUL;
}
//设置实际操作输出缓冲区长度
info = cbout;
break;
}
case sub_code:
{
info = cbout;
break;
}
default:
status = STATUS_INVALID_VARIANT;
}
break;
}
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
case IRP_MJ_WRITE:
case IRP_MJ_READ:
break;
}

// 完成IRP 
pIrp->IoStatus.Status = status;     // 设置IRP的状态为成功 
pIrp->IoStatus.Information = info;         // 设置操作的字节数为0 
IoCompleteRequest( pIrp, IO_NO_INCREMENT ); // 指示完成此IRP
KdPrint(("离开派遣函数......\n"));          // 打印调试信息 
return status; // 返回成功 
}





















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值