Windows操作系统——NT驱动

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
//Dirver.h
#pragma once

#ifdef __cplusplus
extern "C"
{
#endif
#include <NTDDK.H>
#ifdef __cplusplus
}
#endif

#define PAGEDCODE CODE_SEG("PAGE")
#define LOCKEDCODE code_seg()
#define INITCODE code_seg("INIT")

#define PAGEDDATA data_seg("PAGE")
#define LOCKEDDATA data_seg()
#define INITDATA data_seg("INIT")

#define arraysize(p) (sizeof(p)/sizeof((p)[0]))

typedef struct _DEVICE_EXTENSION {
PDEVICE_OBJECT pDevice;
UNICODE_STRING ustrDeviceName; //设备名称
UNICODE_STRING ustrSymLinkName; //符号连接名
} DEVICE_EXTENSION, *PDEVICE_EXTENSION;

//函数声明

NTSTATUS CreateDevice(IN PDRIVER_OBJECT pDriverObject);
VOID HelloDDKUnload(IN PDRIVER_OBJECT pDriverObject);
NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj,
IN PIRP pIrp);

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
//Dirver.cpp
#include "Driver.h"
////////////////////////初始化驱动程序,定位和申请硬件资源,创建内核对象///////////////////////
#pragma INITCODE
extern "C" NTSTATUS DriverEntry(
IN PDRIVER_OBJECT pDriverObject, //从I/O管理器中传进来的驱动对象
IN PUNICODE_STRING pRegistryPath) //驱动对象在注册表中的路径
{
NTSTATUS status;
KdPrint(("Enter DriverEntry\n"));

//注册其他驱动调用函数入口,又操作系统负责调用
pDriverObject->DriverUnload = HelloDDKUnload;

//简化为一个函数,实际情况复杂
pDriverObject->MajorFunction[IRP_MJ_CREATE] = HelloDDKDispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_CLOSE] = HelloDDKDispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_WRITE] = HelloDDKDispatchRoutine;
pDriverObject->MajorFunction[IRP_MJ_READ] = HelloDDKDispatchRoutine;

//创建设备对象
status = CreateDevice(pDriverObject);

KdPrint(("DriverEntry end\n"));
return status;
}

//////////////////////////////////CreateDevice初始化设备对象//////////////////////////
#pragma INITCODE
NTSTATUS CreateDevice(
IN PDRIVER_OBJECT pDriverObject) //从I/O管理器中传进来的驱动对象
{
NTSTATUS status;
PDEVICE_OBJECT pDevObj;
PDEVICE_EXTENSION pDevExt;

//创建设备名称
UNICODE_STRING devName; //Unicode字符串,存储设备对象名称,设备名称只能在内核态可见
RtlInitUnicodeString(&devName, L"\\Device\\MyDDKDevice");

//创建设备对象
status = IoCreateDevice(pDriverObject,
sizeof(DEVICE_EXTENSION),
&(UNICODE_STRING)devName,
FILE_DEVICE_UNKNOWN, //设备类型
0,
TRUE,
&pDevObj);
if (!NT_SUCCESS(status))
{
return status;
}
pDevObj->Flags |= DO_BUFFERED_IO; //表明为BUFFERED_IO对象,设备对内存的操作有两种BUFFERED_IO和DO_DIRECT_IO
pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
pDevExt->pDevice = pDevObj;
pDevExt->ustrDeviceName = devName;

//创建连接符号
UNICODE_STRING symLinkName; //指向设备名称的符号链接,提供给应用程序
RtlInitUnicodeString(&symLinkName, L"\\??\\HelloDDK");
pDevExt->ustrSymLinkName = symLinkName;
status = IoCreateSymbolicLink(&symLinkName, &devName);
if ( !NT_SUCCESS(status) )
{
IoDeleteDevice(pDevObj);
return status;
}
return STATUS_SUCCESS;
}

/////////////////////////////////////////HelloDDKUnload///////////////////////////////
#pragma PAGEDCODE
VOID HelloDDKUnload(IN PDRIVER_OBJECT pDriverObject) //驱动对象
{
PDEVICE_OBJECT pNextObj;
KdPrint(("Enter DriverUnload\n"));
pNextObj = pDriverObject->DeviceObject; //由驱动对象得到设备对象
while (pNextObj != NULL)
{
PDEVICE_EXTENSION pDevExt = (PDEVICE_EXTENSION)
pNextObj->DeviceExtension;

//删除符号链接
UNICODE_STRING pLinkName = pDevExt->ustrSymLinkName;
IoDeleteSymbolicLink(&pLinkName);

//遍历设备对象并删除
pNextObj = pNextObj->NextDevice;
IoDeleteDevice(pDevExt->pDevice);
}
}

////////////////////////////////对读IRP进行处理////////////////////////////
#pragma
NTSTATUS HelloDDKDispatchRoutine(IN PDEVICE_OBJECT pDevObj, //功能设备对象
IN PIRP pIrp)
{
KdPrint(("Enter HelloDDKDispatchRoutine\n"));
NTSTATUS status = STATUS_SUCCESS;

//完成IRP
pIrp->IoStatus.Status = status; //设置IRP状态为成功
pIrp->IoStatus.Information = 0; // bytes xfered
IoCompleteRequest(pIrp, IO_NO_INCREMENT); //指示完成此IRP
KdPrint(("Leave HelloDDKDispatchRoutine\n"));
return status;
}