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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
|
/*
Windows内核下模拟文件的读写操作, IRP的处理(使用MDL的IO方式) 0环代码
编译方法参见makefile. TAB = 8
*/
#include <ntddk.h>
#define DEVICE_NAME L"\\Device\\DevJoenDevice"
#define SYS_LINK_NAME L"\\??\\SysLinkJoenDevice"
#define MAX_LENGTH 1024
typedef struct tagDEVICEEXT {
CHAR* pBuf;
ULONG ulCurFileLength;
PDEVICE_OBJECT pDeviceObj;
UNICODE_STRING USzDeviceName;
UNICODE_STRING USzSysLinkName;
}DEVICEEXT, *PDEVICEEXT;
//===========================================================================
//驱动卸载例程
VOID DriverUnLoad( PDRIVER_OBJECT pDriverObj ) {
PDEVICEEXT pDriveExt;
PDEVICE_OBJECT pNextDeviceObj;
pNextDeviceObj = pDriverObj->DeviceObject;
while ( pNextDeviceObj != NULL ) {
pDriveExt = (PDEVICEEXT)pNextDeviceObj->DeviceExtension;
//删除设备和符号链接
IoDeleteDevice(pNextDeviceObj);
IoDeleteSymbolicLink(&pDriveExt->USzSysLinkName);
KdPrint(( "删除%wZ设备成功!\n", &pDriveExt->USzDeviceName ));
pNextDeviceObj = pNextDeviceObj->NextDevice;
}
}
//===========================================================================
//其他一概不关心的IRP处理
NTSTATUS DispatchRoutin( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
pIrp->IoStatus.Status = STATUS_SUCCESS;
pIrp->IoStatus.Information = 0;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return STATUS_SUCCESS;
}
//===========================================================================
//读请求处理例程
NTSTATUS DispatchRead( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
ULONG ulReadLength;
ULONG ulReadOffset;
ULONG ulMdlLength;
ULONG ulMdlOffset;
PVOID ulMdlAddress;
CHAR* pBuf;
NTSTATUS Status;
PDEVICEEXT pDeviceExt;
PIO_STACK_LOCATION Stack;
pDeviceExt = (PDEVICEEXT)pDeviceObj->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(pIrp);
//读取长度和偏移
ulReadOffset = (ULONG)Stack->Parameters.Read.ByteOffset.QuadPart;
ulReadLength = Stack->Parameters.Read.Length;
ulMdlAddress = MmGetMdlVirtualAddress( pIrp->MdlAddress );
ulMdlLength = MmGetMdlByteCount( pIrp->MdlAddress );
ulMdlOffset = MmGetMdlByteOffset( pIrp->MdlAddress );
//要读取长度大于最大长度, 返回失败
if ( ulReadLength + ulReadOffset > MAX_LENGTH ) {
Status = STATUS_FILE_INVALID;
ulReadLength = 0;
}else {
//获取到那个MDL对应的内核地址, 都是这么用. 回头搞明白到底做了什么?
pBuf = MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
KdPrint(( "内核下的映射地址%p\n", pBuf ));
//写会3环那边
RtlCopyMemory(pBuf, pDeviceExt->pBuf+ulReadOffset,ulReadLength );
Status = STATUS_SUCCESS;
}
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return Status;
}
//===========================================================================
//写请求处理例程
NTSTATUS DispatchWrite( PDEVICE_OBJECT pDeviceObj, PIRP pIrp ) {
CHAR* pBuf;
NTSTATUS Status;
ULONG ulWriteLength;
ULONG ulMdlLength;
ULONG ulWriteOffset;
PVOID ulMdlAddress;
ULONG ulMdlOffset;
PDEVICEEXT pDeviceExt;
PIO_STACK_LOCATION Stack;
pDeviceExt = (PDEVICEEXT)pDeviceObj->DeviceExtension;
Stack = IoGetCurrentIrpStackLocation(pIrp);
ulWriteLength = Stack ->Parameters.Write.Length;
ulWriteOffset = (ULONG)Stack->Parameters.Write.ByteOffset.QuadPart;
//目前不了解Windows的内存管理, 先这样用着
ulMdlLength = MmGetMdlByteCount( pIrp->MdlAddress );
ulMdlOffset = MmGetMdlByteOffset( pIrp->MdlAddress );
ulMdlAddress = MmGetMdlVirtualAddress( pIrp->MdlAddress );
//如果要写入的长度达到了最大长度, 返回无效.
if ( ulWriteOffset + ulWriteLength > MAX_LENGTH ) {
Status = STATUS_FILE_INVALID;
ulWriteLength = 0;
}
//MDL的长度应该和读取的长度相等. 否则就有问题了
if ( ulMdlLength != ulWriteLength ) {
pIrp->IoStatus.Information= 0;
Status = STATUS_UNSUCCESSFUL;
}else {
//获取到那个MDL对应的内核地址, 都是这么用. 回头搞明白到底做了什么?
pBuf = MmGetSystemAddressForMdlSafe( pIrp->MdlAddress, NormalPagePriority );
KdPrint(( "内核下的映射地址%p\n", pBuf ));
//将3环那边的数据存储在缓冲区中
RtlCopyMemory(pDeviceExt->pBuf+ulWriteOffset,pBuf,ulWriteLength );
if ( ulWriteLength + ulWriteOffset > pDeviceExt->ulCurFileLength ) {
pDeviceExt->ulCurFileLength = ulWriteLength + ulWriteOffset;
}
pIrp->IoStatus.Information = ulWriteLength;
Status = STATUS_SUCCESS;
}
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return Status;
}
//===========================================================================
//驱动入口
#pragma code_seg( "INIT" )
NTSTATUS DriverEntry( PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pUSzRegPath ) {
ULONG i;
NTSTATUS Status;
PDEVICEEXT pDeviceExt;
PDEVICE_OBJECT pDeviceObj;
UNICODE_STRING USzSysLinkName = RTL_CONSTANT_STRING( SYS_LINK_NAME );
UNICODE_STRING USzDeviceName = RTL_CONSTANT_STRING( DEVICE_NAME );
//创建设备
Status = IoCreateDevice( pDriverObj, sizeof(DEVICEEXT),&USzDeviceName,
FILE_DEVICE_UNKNOWN, 0, TRUE, &pDeviceObj );
if ( !NT_SUCCESS(Status) ) {
KdPrint(( "创建设备失败!\n" ));
return Status;
}
//创建符号链接
Status = IoCreateSymbolicLink(&USzSysLinkName, &USzDeviceName );
if ( !NT_SUCCESS(Status) ) {
KdPrint(( "创建符号链接失败!\n" ));
IoDeleteDevice( pDeviceObj );
return Status;
}
//直接缓冲区方式
pDeviceObj->Flags |= DO_DIRECT_IO;
pDeviceExt = (PDEVICEEXT)pDeviceObj->DeviceExtension;
pDeviceExt->pDeviceObj = pDeviceObj;
pDeviceExt->USzDeviceName = USzDeviceName;
pDeviceExt->USzSysLinkName = USzSysLinkName;
pDeviceExt->pBuf = ExAllocatePool(PagedPool, MAX_LENGTH );
RtlZeroMemory(pDeviceExt->pBuf, MAX_LENGTH );
//设置分发函数和卸载函数
for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ ) {
pDriverObj->MajorFunction[i] = &DispatchRoutin;
}
pDriverObj->MajorFunction[IRP_MJ_READ] = &DispatchRead;
pDriverObj->MajorFunction[IRP_MJ_WRITE]= &DispatchWrite;
pDriverObj->DriverUnload = &DriverUnLoad;
return Status;
}
|