首页
社区
课程
招聘
[已解决] [悬赏]内核层使用StartIO例程时遇到的问题 5.00雪花
发表于: 2017-9-26 14:16 2693

[已解决] [悬赏]内核层使用StartIO例程时遇到的问题 5.00雪花

2017-9-26 14:16
2693
在这里纠结了两天,每次在IRP_MJ_READ派遣函数里面调用IoStartPacket的时候就会宕机,错误码0xD1,经查阅文档发现是因为在高中断级访问分页内存所引起的原因,但是我把函数都加上非分页内存标识后依然出现这种问题,求路过的大佬们看看咋回事,以下是源码,感激不尽
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
#include <NTDDK.h>
#ifdef __cplusplus
}
#endif // __cplusplus
#define INITCODE code_seg("INIT")
#define PAGECODE code_seg("PAGE")
#define LOCKEDCODE code_seg()
typedef struct _DEVICE_EXTENSION//设备拓展
{

}DEVICE_EXTENSION, *PDEVICE_EXTENSION;
//函数声明
NTSTATUS CreateDevice(PDRIVER_OBJECT driver);
NTSTATUS StartDispatchRead(PDEVICE_OBJECT device, PIRP irp);
NTSTATUS StartDispatchRoutine(PDEVICE_OBJECT device, PIRP irp);
VOID MyStartIO(PDEVICE_OBJECT device, PIRP irp);
VOID UnLoad(PDRIVER_OBJECT driver);
VOID OnCancel(PDEVICE_OBJECT device, PIRP irp);
//入口函数
#pragma INITCODE
extern "C" NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING rigestrPath)
{
	for (size_t i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
	{
		driver->MajorFunction[i] = StartDispatchRoutine;
	}
	driver->DriverStart = MyStartIO;//设置StartIO例程
	driver->MajorFunction[IRP_MJ_READ] = StartDispatchRead;
	driver->DriverUnload = UnLoad;
	return CreateDevice(driver);
}
#pragma INITCODE
NTSTATUS CreateDevice(PDRIVER_OBJECT driver)//创建设备
{
	UNICODE_STRING deviceName, symbolic;
	PDEVICE_OBJECT dev;
	NTSTATUS status;
	RtlInitUnicodeString(&deviceName, L"\\Device\\test");
	RtlInitUnicodeString(&symbolic, L"\\??\\test");
	status = IoCreateDevice(driver, sizeof(DEVICE_EXTENSION), &deviceName, FILE_DEVICE_UNKNOWN, 0, TRUE, &dev);//创建设备
	IoCreateSymbolicLink(&symbolic, &deviceName);//创建符号链接
	dev->Flags |= DO_BUFFERED_IO;//缓冲区读写方式
	return status;
}
#pragma PAGECODE
NTSTATUS StartDispatchRoutine(PDEVICE_OBJECT device, PIRP irp)//默认处理函数
{
	PAGED_CODE();
	irp->IoStatus.Status = STATUS_SUCCESS;
	irp->IoStatus.Information = 0;
	IoCompleteRequest(irp, IO_NO_INCREMENT);
	return STATUS_SUCCESS;
}
#pragma LOCKEDCODE
VOID MyStartIO(PDEVICE_OBJECT device, PIRP irp)              //StartIO例程
{
	KIRQL irql;
	IoAcquireCancelSpinLock(&irql);//获取全局自旋锁
	if (device->CurrentIrp == irp) //判断该IRP是否即将被StartIO例程处理
	{
		KdPrint(("Good!!!\n"));
		IoSetCancelRoutine(irp, NULL); //如果是则拒绝该IRP调用取消例程
		IoReleaseCancelSpinLock(irql);
	}
	else //如果不是则说明当前有正在处理的IRP,直接简单的返回即可,系统会自动把该IRP放入队列当中
	{
		KdPrint(("Busy!!!\n"));
		IoReleaseCancelSpinLock(irql);
		return;
	}
	KdPrint(("irql:%d\n", irql));//输出当前中断级
	KdPrint(("Processing request...\n"));
	KEVENT event;
	KeInitializeEvent(&event, NotificationEvent, FALSE);
	LARGE_INTEGER time;
	time.QuadPart = -3 * 1000 * 1000 * 10;
	KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, &time);
	irp->IoStatus.Information = 0;
	irp->IoStatus.Status = STATUS_SUCCESS;
	IoCompleteRequest(irp, IO_NO_INCREMENT);
	IoStartNextPacket(device, TRUE);
	KdPrint(("Request complete!!!\n"));
}
#pragma PAGECODE
NTSTATUS StartDispatchRead(PDEVICE_OBJECT device, PIRP irp)      //IRP_MJ_READ处理函数
{
	PAGED_CODE();
	IoMarkIrpPending(irp);						//挂起IRP
	IoStartPacket(device, irp, 0, OnCancel);    //将IRP放入队列
	return STATUS_PENDING;						//返回挂起
}
#pragma PAGECODE
VOID OnCancel(PDEVICE_OBJECT device, PIRP irp)                  //取消例程
{
	if (device->CurrentIrp == irp)				//判断当前IRP是否即将被StartIO例程处理
	{

		KIRQL irql = irp->CancelIrql;			//如果是则直接跳过当前IRP的StartIO处理,直接调取队列的下一个IRP
		KdPrint(("irql:%d\n", irql));
		IoReleaseCancelSpinLock(irp->CancelIrql);//释放取消自旋锁
		ASSERT(KeGetCurrentIrql() == DISPATCH_LEVEL);
		IoStartNextPacket(device, TRUE);
		KeLowerIrql(irql);

	}
	else   //如果不是则从队列中删除该IRP
	{
		KeRemoveEntryDeviceQueue(&device->DeviceQueue, &irp->Tail.Overlay.DeviceQueueEntry);
		IoReleaseCancelSpinLock(irp->CancelIrql);
	}
	irp->IoStatus.Information = 0;
	irp->IoStatus.Status = STATUS_CANCELLED;
	IoCompleteRequest(irp, IO_NO_INCREMENT);
	KdPrint(("Cancel is Over!!!\n"));
}
#pragma PAGECODE
VOID UnLoad(PDRIVER_OBJECT driver)
{
	KdPrint(("UnLoad!!!\n"));
}



[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (7)
雪    币: 172
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
这就很尴尬了,刚刚睡觉的时候突然想到会不会是函数入口没设置正确,仔细一看DriverEntry在设置StartIO函数入口的时候设置错了,DriverStart!=DriverStartIO
2017-9-26 15:17
0
雪    币: 172
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
来个人结贴
2017-9-26 15:18
0
雪    币: 172
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
之前想到过可能是函数入口设置错了,但是觉得编译器又没报错,如果入口函数设置错了应该会报类型不同的错误,结果就是这么巧
2017-9-26 15:20
0
雪    币: 172
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
问题解决了,随便来个人结贴
2017-9-26 16:19
0
雪    币: 27
活跃值: (300)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
辣鸡,这都不会,DriverStart  !=  DriverStartIO
2017-9-26 16:22
0
雪    币: 3700
活跃值: (2659)
能力值: ( LV7,RANK:105 )
在线值:
发帖
回帖
粉丝
7
白丶夜 [em_39]问题解决了,随便来个人结贴
这样都行?
2017-9-26 16:23
0
雪    币: 172
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
yegu 这样都行[em_13]?
毕竟已经解决了
2017-9-26 16:25
0
游客
登录 | 注册 方可回帖
返回
//