分享

应用层程序与驱动层即内核程序通信示例DeviceIoControl

 山峰云绕 2023-06-01 发布于贵州

https://blog.csdn.net/cosmoslife/article/details/7698710?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-5-7698710-blog-106835990.235^v36^pc_relevant_anti_vip&spm=1001.2101.3001.4242.4&utm_relevant_index=6

刚学习驱动编程,看了相关的应用层程序和驱动层程序通信的例子后,就自己动手开始写一个代码作为学习的总结。其间碰到一些弱智的问题,到最后的解决,现在总结在这里供日后引以为戒。

运行效果图:


//驱动源代码如下:

//文件名:AppDriver.c


//总结:
/*  这里只是一个简单的通信示例,即打开驱动创建的设备,并发送控制信息,最后关闭驱动创建的设备。
这里没有进行应用层和驱动层的数据交换,以后在这个基础上再添加数据交换,数据交换模式有:
缓冲模式(METHOD_BUFFERED )
直接输入\输出模式(METHOD_IN_DIRECT or METHOD_OUT_DIRECT )
前两都不是的模式(METHOD_NEITHER)

这里有篇关于三种模式的文章可以补习补习:http://blog.csdn.net/cosmoslife/article/details/7698688

以上三种模式与CTL_CODE这个宏的第三个参数相关,在这里指定采用哪种方式进行数据交换
*/
#include <ntddk.h>


//自定义控制码,这个控制码是应用程序中DeviceIoControl中要用到的一个重要的与驱动成功通信的参数
#define Msg CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)


//#pragma code_seg("PAGE")
NTSTATUS MessageProcRoutine(IN PDEVICE_OBJECT pDevobj,IN PIRP pIrp)
{
PIO_STACK_LOCATION stack;
ULONG mf;

ULONG uIoControlCode;

DbgPrint("进入控制派遣例程函数..................................!\n");
stack = IoGetCurrentIrpStackLocation(pIrp); //得到当前栈指针
mf = stack->MajorFunction;//区分IRP

switch(mf)
{
case IRP_MJ_DEVICE_CONTROL:
{
//得到IOCTL码
uIoControlCode = stack->Parameters.DeviceIoControl.IoControlCode;
DbgPrint("控制码为: 0x%0x", uIoControlCode);//打印控制码,正确的话应该是上面MESSAGE宏中定义的0x801
switch(uIoControlCode)
{
case Msg:
DbgPrint("这句话打印出来的话就证明我们的应用程序成功与我们的驱动程序进行了通信连接.....\r\n");
break;
}
}
break;
case IRP_MJ_CREATE:
{
DbgPrint(".............设备被应用程序成功打开!\r\n");
break;
}
case IRP_MJ_CLOSE:
{
DbgPrint(".............设备被应用程序成功关闭!\r\n");
break;
}
default:
break;
}

pIrp->IoStatus.Status=STATUS_SUCCESS;//返回成功
IoCompleteRequest(pIrp,IO_NO_INCREMENT);//指示完成此IRP
KdPrint(("离开派遣函数\n\n\n\n"));//调试信息
return STATUS_SUCCESS; //返回成功
}


//#pragma code_seg("PAGE")
VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
//这里的卸载例程要对创建的设备与设备符号链接名进行删除
PDEVICE_OBJECT pDeviceObject;
UNICODE_STRING SymbolicLinksName;

pDeviceObject = pDriverObject->DeviceObject;//设置设备变量值
RtlInitUnicodeString(&SymbolicLinksName, L"\\??\\ZhangHengLinks");//初始化设备符号链接名

IoDeleteDevice(pDeviceObject);//删除设备

IoDeleteSymbolicLink(&SymbolicLinksName);//删除设备符号链接名
DbgPrint("驱动卸载成功--------------\r\n");
}


/********************************************************************************/
/** 第一步:创建设备 第二步:创建设备符号链接名 第三步:设置相应的派遣例程 **/
/********************************************************************************/
//#pragma code_seg("INIT") //表示代码只在加载时运行完毕即从内存卸载
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegsiterPath)
{
NTSTATUS status;
UNICODE_STRING DeviceName;//设备名
UNICODE_STRING SymbolicLinksName;//设备符号链接名
PDEVICE_OBJECT pDeviceObject;//设备对象


DbgPrint("驱动加载成功++++++++++++++\r\n");

RtlInitUnicodeString(&DeviceName, L"\\Device\\ZhangHeng");
RtlInitUnicodeString(&SymbolicLinksName, L"\\??\\ZhangHengLinks");

//创建设备
status = IoCreateDevice( pDriverObject, 0, &DeviceName, FILE_DEVICE_UNKNOWN, 0, FALSE, &pDeviceObject);
if (!NT_SUCCESS(status))
{
if (status==STATUS_INSUFFICIENT_RESOURCES)
{
KdPrint(("资源不足 STATUS_INSUFFICIENT_RESOURCES"));
}
if (status==STATUS_OBJECT_NAME_EXISTS )
{
KdPrint(("指定对象名存在"));
}
if (status==STATUS_OBJECT_NAME_COLLISION)
{
KdPrint(("//对象名有冲突"));
}
KdPrint(("设备创建失败...++++++++\r\n"));
return status;
}
KdPrint(("设备创建成功...++++++++\r\n"));

//根据创建好的设备创建一个设备符号链接名
pDeviceObject->Flags |= DO_BUFFERED_IO;
pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;  //设备初始化完成标记
status = IoCreateSymbolicLink( &SymbolicLinksName,&DeviceName );
if (!NT_SUCCESS(status)) /*status等于0*/
{
//如果失败则删除创建好的设备
IoDeleteDevice( pDeviceObject );
KdPrint(("设备符号链接名创建失败...++++++++\r\n"));
return status;
}
else
{
KdPrint(("设备符号链接名创建成功 ....++++++++\r\n"));
DbgPrint("设备符号链接名为: %wZ\r\n", &SymbolicLinksName);
}

//设置IRP_MJ_DEVICE_CONTROL派遣例程
/*设备控制请求,对应Ring3 DeviceIoControl*/  
    pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = MessageProcRoutine;


/*如果要与应用层进行通信就必须要有打开和关闭请求,
我因为当时没有弄这两个请求结果就是应用层的CreateFile总是返回错误号1表示功能错误,(有兴趣的可以注释掉
pDriverObject->MajorFunction[IRP_MJ_CREATE] = MessageProcRoutine;进行测试,应用程序就会返回错误号1)
纠结了一天才弄清是这个没有响应,一看就知道是保菜鸟在写驱动了啊,哈哈,不过还是希望菜鸟的问题也能提醒大家啊*/
    /*设备打开请求,对应Ring3 CreateFile*/                      //   
    pDriverObject->MajorFunction[IRP_MJ_CREATE] = MessageProcRoutine; //  要与应用层通信,   
    /*设备关闭请求,对应Ring3 CloseHandle*/                     //  必须有打开、关闭请求!   
    pDriverObject->MajorFunction[IRP_MJ_CLOSE] = MessageProcRoutine;  //   


//设置驱动卸载例程
pDriverObject->DriverUnload = DriverUnload;

return STATUS_SUCCESS;
}

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

//应用程序源代码:

#include "stdafx.h"
#include <windows.h>
#include <winioctl.h> //CTL_CODE宏相关


#define Msg CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)


int _tmain(int argc, _TCHAR* argv[])
{
//CreateFile 打开设备 获取hDevice
HANDLE hDevice = CreateFile("\\\\.\\ZhangHengLinks",GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL );// no template
Sleep(5000);
//printf("start\n");
if (hDevice == INVALID_HANDLE_VALUE)
{
printf("获取驱动句柄失败: %s with Win32 error code: %d\n","AppDriver", GetLastError() );
getchar();
return -1;
}
else
{
printf("获取驱动句柄成功: %s with Win32\n","AppDriver" );
}


int port[2];
int bufret;
ULONG dwWrite;


int Result = DeviceIoControl(hDevice, Msg, &port, 8, &bufret, 4, &dwWrite, NULL);
if( Result == 0 )
{
printf("DeviceIoControl函数执行失败: error code: %d\n", GetLastError() );
getchar();
return -1;
}
Sleep(5000);
CloseHandle(hDevice);
getchar();
return 0;
}

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多