实现一个虚拟的驱动设备,实现应用层与驱动设备对象简单的交互

学习自:

B站:写驱动的女装大佬 《–从零开始造核弹—windows驱动程序开发(中级篇-课2)》

知识点:

设备的创建、打开、关闭,应用层怎么把请求传到驱动层

实现效果:

控制台程序运行后,驱动的MyCreate函数开始工作 ,在Debug窗口打印了 My Device has be opende
按任意键后驱动调用了MyCleanUp函数和MyClose,分别打印出了这两个函数设置的打印内容

驱动层(SYS)代码:

/**********************驱动程序学习例程************************
*  平台:visual studio 2019
*  功能:创建驱动虚拟设备(驱动端)
*  编写:逆行者
*  日期:2021-01-15
*  更改记录:未更改
******************************************************************/

#include <ntddk.h>
#define DEVICE_NAME L"\\Device\\MyfirstDevice" //定义一个驱动的名字
#define SYM_NAME    L"\\??\\MyfirstDevice"//定义一个符号链接


VOID nothing(HANDLE ppid, HANDLE mypid, BOOLEAN bcreate)
{
    
    
	//回调函数,有程序打开或关闭显示提示信息
	DbgPrint("ProcessNotify\n");

}

/*
MyCreate自己定义的驱动设备的派遣函数
pdevice:设备对象

*/
NTSTATUS MyCreate(PDEVICE_OBJECT pdevice, PIRP pirp)
{
    
    
	NTSTATUS status = STATUS_SUCCESS;
	DbgPrint("My Device has be opende\n");

	pirp->IoStatus.Status = status; //请求成功
	pirp->IoStatus.Information = 0;//信息处理了0字节
	IoCompleteRequest(pirp,IO_NO_INCREMENT);//完成请求
	return STATUS_SUCCESS;

}

/*
MyClose关闭函数

*/
NTSTATUS MyClose(PDEVICE_OBJECT pdevice, PIRP pirp)
{
    
    
	NTSTATUS status = STATUS_SUCCESS;
	DbgPrint("My Device has be closed\n");

	pirp->IoStatus.Status = status; //请求成功
	pirp->IoStatus.Information = 0;//信息处理了0字节
	IoCompleteRequest(pirp, IO_NO_INCREMENT);//完成请求
	return STATUS_SUCCESS;

}


/*
MyCleanUp清理函数

*/
NTSTATUS MyCleanUp(PDEVICE_OBJECT pdevice, PIRP pirp)
{
    
    
	NTSTATUS status = STATUS_SUCCESS;
	DbgPrint("My Device has be CleanUped\n");

	pirp->IoStatus.Status = status; //请求成功
	pirp->IoStatus.Information = 0;//信息处理了0字节
	IoCompleteRequest(pirp, IO_NO_INCREMENT);//完成请求
	return STATUS_SUCCESS;

}



VOID DrvUnload(PDRIVER_OBJECT pdriver)
{
    
    
	DbgPrint("Unload\n");
	
	if (pdriver->DeviceObject)
	{
    
    
		//删除派遣函数
		IoDeleteDevice(pdriver->DeviceObject);
		
		UNICODE_STRING symname = {
    
     0 };
		RtlInitUnicodeString(&symname, SYM_NAME);
		//删除符号连接
		IoDeleteSymbolicLink(&symname);

	}


	
}



NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
    
    
	NTSTATUS status = STATUS_SUCCESS; //定义一个返回值
	UNICODE_STRING deviceanme = {
    
     0 };//定义设备的名字
	PDEVICE_OBJECT pdevice = NULL; //设备创建后的输出参数,如果不为NULL就表示设备创建成功了
	driver->DriverUnload=DrvUnload;
	RtlInitUnicodeString(&deviceanme, DEVICE_NAME);//初始化一个字符串
	/*
	* IoCreateDevice创建设备 
	    参数1:driver 设备对象;
		参数2:0 设备扩展的大小;
		参数3:&deviceanme 设备名字;
		参数4:FILE_DEVICE_UNKNOWN(未知设备) 设备类型
		参数5:0  默认参数
		参数6:TRUE  默认参数
		参数7:&pdevice 输出参数,设备创建成功后,会把设备对象传出来
	*/
	status = IoCreateDevice(driver, 0, &deviceanme, FILE_DEVICE_UNKNOWN,0,TRUE,&pdevice);

	if (!NT_SUCCESS(status))
	{
    
    
		//如果设备创建设备就打印下面的信息
		DbgPrint("Create Device Failed:%x\n",status);
		//返回错误信息
		return status;
	}

	//到这里 设备就创建成功了
	
	
	UNICODE_STRING symname = {
    
     0 };//定义一个符号连接名称
	RtlInitUnicodeString(&symname, SYM_NAME);//初始化一个字符串
	/*IoCreateSymbolicLink创建符号连接
	
	  参数1:&symname 符号连接名字
	  参数2:&deviceanme 设备名字
	
	*/
	status = IoCreateSymbolicLink(&symname, &deviceanme);
	if (!NT_SUCCESS(status))
	{
    
    
		//如果创建符号连接失败就打印下面的信息
		DbgPrint("Create SymbolicLink Failed:%x\n", status);
		//既然创建符号连接失败,就要删除这个设备
		IoDeleteDevice(pdevice);
		//返回错误信息
		return status;
	}

	//到这里 符号连接就创建成功了

	//打开设备
	driver->MajorFunction[IRP_MJ_CREATE] = MyCreate;
	//关闭设备
	driver->MajorFunction[IRP_MJ_CLOSE] = MyClose;
	//清理设备
	driver->MajorFunction[IRP_MJ_CLEANUP] = MyCleanUp;

	return 0;
}

控制台应用层(EXE)代码:

/**********************驱动程序学习例程************************
*  平台:visual studio 2019
*  功能:CMD控制台程序实现与驱动设备对象简单的交互
*  编写:逆行者
*  日期:2021-01-15
*  更改记录:未更改
******************************************************************/


// MyDriverR3.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <iostream>
#include <Windows.h>
#include <stdlib.h>

int main()
{
    
    

    HANDLE hdevice = NULL; // 建立一个句柄

    /*CreateFile打开一个驱动设备
    * 参数1:\\\\.\\MyfirstDevice 符号连接 
    *       对应驱动程序是这样写的 \\??\\MyfirstDevice
    * 参数2:GENERIC_READ|GENERIC_WRITE 读写方式
    * 参数3:0 是否读栈
    * 参数4:NULL 描述符
    
    */
    hdevice = CreateFile("\\\\.\\MyfirstDevice",GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);

    if (hdevice==INVALID_HANDLE_VALUE)
    {
    
    
        printf("Open Device Faile\n");
        system("pause");
        return 0;

    }
    //到这里驱动设备就打开成功
    printf("Open Sucess\n");
    system("pause");
    CloseHandle(hdevice);
    system("pause");

    return 0;
   
}

// 运行程序: Ctrl + F5 或调试 >“开始执行(不调试)”菜单
// 调试程序: F5 或调试 >“开始调试”菜单

// 入门使用技巧: 
//   1. 使用解决方案资源管理器窗口添加/管理文件
//   2. 使用团队资源管理器窗口连接到源代码管理
//   3. 使用输出窗口查看生成输出和其他消息
//   4. 使用错误列表窗口查看错误
//   5. 转到“项目”>“添加新项”以创建新的代码文件,或转到“项目”>“添加现有项”以将现有代码文件添加到项目
//   6. 将来,若要再次打开此项目,请转到“文件”>“打开”>“项目”并选择 .sln 文件

控制台程序编译设置

在这里插入图片描述

运行结果:

在这里插入图片描述
感谢 B站UP主:写驱动的女装大佬 视频教程!

猜你喜欢

转载自blog.csdn.net/lygl35/article/details/112673856