#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"));
}