tiechui_lesson02_创建设备与简单通信

学习了驱动对象与设备对象的关系以及创建对象和符号连接与应用层通信的方式。

在驱动层的代码设置:

#include <ntifs.h>

#define DEVICE_NAME L"\\Device\\MyFirstDevice"		//设备名称
#define SYM_NAME	L"\\??\\MyFirstDevice"			//符号链接


//分发函数
NTSTATUS MyCreate(PDEVICE_OBJECT pdevice, PIRP pirp)
{
	UNREFERENCED_PARAMETER(pdevice);
	NTSTATUS status = STATUS_SUCCESS;
	DbgPrint("My Device has be opened!");
	pirp->IoStatus.Status = status;
	pirp->IoStatus.Information = 0;
	IoCompleteRequest(pirp, IO_NO_INCREMENT);

	return status;
}
NTSTATUS MyClearUp(PDEVICE_OBJECT pdevice, PIRP pirp)
{
	UNREFERENCED_PARAMETER(pdevice);
	NTSTATUS status = STATUS_SUCCESS;
	DbgPrint("My Device MyClearUp!");
	pirp->IoStatus.Status = status;
	pirp->IoStatus.Information = 0;
	IoCompleteRequest(pirp, IO_NO_INCREMENT);

	return status;
}
NTSTATUS MyClose(PDEVICE_OBJECT	pdevice, PIRP pirp)
{
	UNREFERENCED_PARAMETER(pdevice);
	NTSTATUS status = STATUS_SUCCESS;
	DbgPrint("My Device MyClose!");
	pirp->IoStatus.Status = status;
	pirp->IoStatus.Information = 0;
	IoCompleteRequest(pirp, IO_NO_INCREMENT);

	return status;
}


//卸载函数
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
	DbgPrint("basedriver 卸载驱动\n");
	if (DriverObject->DeviceObject)
	{
		IoDeleteDevice(DriverObject->DeviceObject);
	}
	UNICODE_STRING symLink = RTL_CONSTANT_STRING(SYM_NAME);
	IoDeleteSymbolicLink(&symLink);
}

//入口函数
NTSTATUS DriverEntry(
	IN PDRIVER_OBJECT DriverObject, 
	IN PUNICODE_STRING RegistryPath
)
{
	UNREFERENCED_PARAMETER(RegistryPath);
	//注册卸载函数
	DriverObject->DriverUnload = DriverUnload;

	NTSTATUS status = STATUS_SUCCESS;
	PDEVICE_OBJECT pdevice = NULL;		// 用来接收创建的设备对象
	UNICODE_STRING devicename = { 0 };
	RtlInitUnicodeString(&devicename, DEVICE_NAME);

	//创建设备对象
	status = IoCreateDevice(DriverObject, 
							0, 
							&devicename, 
							FILE_DEVICE_UNKNOWN, 
							0, 
							TRUE, 
							&pdevice);

	if (!NT_SUCCESS(status))
	{
		KdPrint(("IoCreateDevice 虚拟设备打开失败 状态码 (0x%08X)\n",status));
		DbgPrint("IoCreateDevice 虚拟设备打开失败 状态码 (0x%08X)\n", status);
	}

	//
	//创建成功,创建符号链接
	//
	UNICODE_STRING symname = { 0 };
	RtlInitUnicodeString(&symname, SYM_NAME);
	status = IoCreateSymbolicLink(&symname, &devicename);	// 符号链接名 设备名
	if (!NT_SUCCESS(status))
	{
		KdPrint(("IoCreateSymbolicLink 符号链接创建失败 状态码 (0x%08X)", status));
		DbgPrint("IoCreateSymbolicLink 符号链接创建失败 状态码 (0x%08X)", status);
	}

	//设置分发例程
	DriverObject->MajorFunction[IRP_MJ_CREATE] = MyCreate;
	DriverObject->MajorFunction[IRP_MJ_CLEANUP] = MyClearUp;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = MyClose;

	return 0;
}

 在应用层的操作

设备对象可以在内核中暴露出来给应用层,应用层可以像操作文件一样操作它):

#include <stdio.h>
#include <windows.h>
#include <winioctl.h>
#include <stdlib.h>

int main()
{
	HANDLE hdevice = NULL;

	hdevice = CreateFile(L"\\\\.\\MyFirstDevice", GENERIC_WRITE | GENERIC_READ, 0
		, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

	if (hdevice != INVALID_HANDLE_VALUE)
	{
		printf("打开设备SUCCESS!\n");
	}
	else {
		printf("打开设备失败!\n");

		system("pause");
	}
	system("pause");

	if (hdevice != nullptr)
	{
		CloseHandle(hdevice);
		printf("关闭句柄!\n");
	}

	system("pause");

	return 0;
}

注意,判断是否成功打开驱动对象句柄要通过这样判断:

hdevice != INVALID_HANDLE_VALUE

 执行结果:

通过DeviceTree可以看到驱动对象和它支持的IRP请求:

通过WinObj可以看到我们设置的符号链接名:

小结:

1、设备对象在应用层可以像文件那样被操作。

2、驱动工具的使用,可以更直观的获取信息。

3、有个疑问,为什么分发函数只对应用程序的打开关闭有响应?这个通信并不是双向的,而是应用层一直在访问。

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值