windows内核-驱动设备与符号链接 (二)

创建驱动设备与符号链接


#include<ntifs.h> //ntddk.h

//创建驱动设备对象
NTSTATUS CreateDevice(PDRIVER_OBJECT driver)
{
	NTSTATUS status;
	UNICODE_STRING MyDriver;
	PDEVICE_OBJECT device;//用于存放设备对象
	RtlInitUnicodeString(&MyDriver, L"\\DEVICE\\MyDriver");//驱动设备名字

	status = IoCreateDevice(driver, sizeof(driver->DriverExtension), &MyDriver, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &device);

	if (status == STATUS_SUCCESS)//STATUS_SUCCESS)
	{
		KdPrint(("驱动设备对象创建成功,OK \n"));
		//创建符号链接
		UNICODE_STRING uzSymbolName; //符号链接名字		 
		RtlInitUnicodeString(&uzSymbolName, L"\\??\\MyDriver"); //CreateFile
		status = IoCreateSymbolicLink(&uzSymbolName, &MyDriver);
		if (status == STATUS_SUCCESS)
		{
			KdPrint(("创建符号链接 %wZ 成功 ", &uzSymbolName));
		}
		else
		{
			KdPrint(("创建符号链接 %wZ 失败 status=%X", &uzSymbolName, status));
		}
	}
	else
	{

		KdPrint(("驱动设备对象创建失败,删除设备\n"));
		IoDeleteDevice(device);
	}
	return status;
}

NTSTATUS IRP_CALL(PDEVICE_OBJECT device, PIRP pirp)
{
	device;
	KdPrint(("进入派遣函数"));
	PIO_STACK_LOCATION irpStackL;

	irpStackL = IoGetCurrentIrpStackLocation(pirp); //获取应用层传来的参数

	switch (irpStackL->MajorFunction)
	{
	case IRP_MJ_DEVICE_CONTROL: //DeviceIoControl
	{
		KdPrint(("用户层调用了 DeviceIoControl"));
		break;
	}
	case IRP_MJ_CREATE: //CreateFile
	{
		KdPrint(("用户层调用了 CreateFile"));
		break;
	}
	case IRP_MJ_CLOSE: //CloseHandle
	{
		KdPrint(("用户层调用了 CloseHandle"));
		break;
	}
	}

	pirp->IoStatus.Status = STATUS_SUCCESS;
//	pirp->IoStatus.Information = 4;//返回给DeviceIoControl中的 倒数第二个参数lpBytesReturned
	IoCompleteRequest(pirp, IO_NO_INCREMENT);//调用方已完成所有I/O请求处理操作 并且不增加优先级 
	KdPrint(("离开派遣函数"));
	return STATUS_SUCCESS;  //0 返回成功
}


//卸载驱动时会被调用
void DriverUnload(PDRIVER_OBJECT DriverObject)
{
	KdPrint(("进入卸载例程DriverObject=%p 行号=%d ", DriverObject, __LINE__));
	if (DriverObject->DeviceObject)
	{
		//删除符号链接
		UNICODE_STRING uzSymbolName; //符号链接名字		 
		RtlInitUnicodeString(&uzSymbolName, L"\\??\\MyDriver"); //CreateFile
		KdPrint(("删除符号链接=%wZ", &uzSymbolName));
		IoDeleteSymbolicLink(&uzSymbolName);
		//
		KdPrint(("删除驱动设备"));
		IoDeleteDevice(DriverObject->DeviceObject);//删除设备对象
	}
	KdPrint(("退出 DriverUnLoad例程"));
}

//加载驱动时 会被调用
NTSTATUS
DriverEntry(
	_In_ PDRIVER_OBJECT  DriverObject,
	_In_ PUNICODE_STRING RegistryPath
)
{
	KdPrint(("进入 DriverEntry入口点 DriverObject=%p 行号=%d\n", DriverObject, __LINE__)); //Debug

	DriverObject->DriverUnload = DriverUnload; //注册卸载例程 回调函数
	
	NTSTATUS status = CreateDevice(DriverObject);为驱动对象创建一个设备
	status;

	DriverObject->MajorFunction[IRP_MJ_CREATE] = IRP_CALL;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = IRP_CALL;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IRP_CALL;

	
	//KdPrint((" RegistryPath=%s\n", RegistryPath->Buffer)); //多字节字符集
	KdPrint((" RegistryPath=%ws\n", RegistryPath->Buffer)); //Unicode 宽字符
	return 0; //成功
}

        
        
windows下的设备是以"/Device/[设备名]”形式命名的。

例如磁盘分区的c盘,d盘的设备名称就是"/Device/HarddiskVolume1”,"/Device/HarddiskVolume2”, 当然也可以不指定设备名称。如果IoCreateDevice中没有指定设备名称,那么I/O管理器会自动分配一个数字作为设备的名称。例如"/Device/00000001"。/Device/[设备名],不容易记忆,通常符号链接可以理解为设备的别名,更重要的是设备名,只能被内核模式下的其他驱动所识别,而别名可以被用户模式下的应用程序识别,例如c盘,就是名为"c:"的符号链接,其真正的设备对象是"/Device/HarddiskVolume1”,所以在写驱动时候,一般我们创建符号链接,即使驱动中没有用到,这也算是一个好的习惯吧。


驱动中符号链接名是这样写的
L"//??//HelloDDK" --->/??/HelloDDK
L"//DosDevices//HelloDDK"--->/DosDevices/HelloDDK
在应用程序中,符号链接名:
L".//HelloDDK"-->//./HelloDDK

winobj和DeviceTree可以用来查看这些信息。

DosDevices的符号链接名就是??, 所以"//DosDevices//XXXX"其实就是"//??//XXXX"

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值