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
184
185
186
187
188
189
190
191
192
193
194
195
196
197
|
//KdPrint类似于 控制台的printf
//DriverEntry类似于 C / C++里的main
#include <ntifs.h>
#pragma code_seg("PAGE")
//创建驱动设备对象
NTSTATUS CreateDevice(PDRIVER_OBJECT driver)
{
NTSTATUS status;
UNICODE_STRING uzDriverName;
PDEVICE_OBJECT device;
RtlInitUnicodeString(&uzDriverName, L"\\DEVICE\\uzDriverName001");
//创建驱动设备
status = IoCreateDevice(driver, sizeof(driver->DriverExtension), &uzDriverName, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &device);
if (status == STATUS_SUCCESS)
{
KdPrint(("yjx:驱动设备对象 %wZ 创建成功,OK -----------\n", &uzDriverName));
//为设备对象绑定一个符号链接
UNICODE_STRING uzSymbolName; //符号链接名字
RtlInitUnicodeString(&uzSymbolName, L"\\??\\uzDriverName001"); //CreateFile
status = IoCreateSymbolicLink(&uzSymbolName, &uzDriverName);
if (status==STATUS_SUCCESS)
{
KdPrint(("yjx:创建符号链接 %wZ 成功 ", &uzSymbolName));
}
else
{
KdPrint(("yjx:创建符号链接 %wZ 失败 ", &uzSymbolName));
}
}
else
{
KdPrint(("yjx:驱动设备对象 %wZ 创建失败,准备删除Device -----------\n", &uzDriverName));
IoDeleteDevice(device);
}
return status;
}
//驱动卸载例程
void UnLoad(PDRIVER_OBJECT driver)
{
NTSTATUS status = 0;
IoDeleteDevice(driver->DeviceObject); //删除设备对象,如果此处不删除 卸载不干净 再次用IoCreateDevice创建同名驱动 会蓝屏
//删除符号链接
UNICODE_STRING uzSymbolName; //符号链接名字
RtlInitUnicodeString(&uzSymbolName, L"\\??\\uzDriverName001");
status=IoDeleteSymbolicLink(&uzSymbolName);
if (!status) //if(status == STATUS_SUCCESS)
{
KdPrint(("yjx:删除符号链接 %wZ 成功 ",&uzSymbolName));
}
else
{
KdPrint(("yjx:删除符号链接 %wZ 失败 ", &uzSymbolName));
}
KdPrint(("yjx:驱动卸载成功\n"));
}
NTSTATUS DriverEntry(PDRIVER_OBJECT driver,PVOID szReg) //main
{
KdPrint(("yjx:进入了我们的驱动 \n")); //printf
driver->DriverUnload = UnLoad;
NTSTATUS status=CreateDevice(driver);//创建了设备对象
return STATUS_SUCCESS;
}
IRP 派遣函数
driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DeviceIrpCtl;//DeviceIoControl
driver->MajorFunction[IRP_MJ_CREATE] = DeviceIrpCtl; //CreateFile
driver->MajorFunction[IRP_MJ_CLOSE] = DeviceIrpCtl;//卸载驱动 CloseHandle
NTSTATUS DeviceIrpCtl(PDEVICE_OBJECT device,PIRP pirp)
{
KdPrint(("yjx:进入派遣函数"));
PIO_STACK_LOCATION irpStackL;
ULONG CtlCode;
ULONG InputBuffLength;
irpStackL=IoGetCurrentIrpStackLocation(pirp); //获取应用层传来的参数
switch(irpStackL->MajorFunction)
{
IRP_MJ_DEVICE_CONTROL;
IRP_MJ_CREATE;
IRP_MJ_CLOSE;
}
pirp->IoStatus.Status = STATUS_SUCCESS;
pirp->IoStatus.Information = 4;//返回给DeviceIoControl中的 倒数第二个参数lpBytesReturned
IoCompleteRequest(pirp, IO_NO_INCREMENT);//调用方已完成所有I/O请求处理操作 并且不增加优先级
KdPrint(("yjx:离开派遣函数"));
return STATUS_SUCCESS;
}
//打开驱动设备
void CIoControlIrpDlg::OnBnClickedCreate()
{
// TODO: 在此添加控件通知处理程序代码
DeviceHandle = CreateFileW(
L"\\??\\uzDriverName001",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
}
void CIoControlIrpDlg::OnBnClickedButtonClose()
{
// TODO: 在此添加控件通知处理程序代码
if (DeviceHandle)
{
CloseHandle(DeviceHandle);
DeviceHandle = NULL;
}
}
R3应用层与R0驱动层简单通信
#define IO_IS_OK_TEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED,FILE_ANY_ACCESS) //测试
//WriteFile ReadFile
BOOL DeviceIoControl(
HANDLE hDevice, // 设备驱动的句柄 由CreateFile获取
DWORD dwIoControlCode, // 操作控制码
LPVOID lpInBuffer, // 输入缓冲区指针 要传入驱动的 参数
DWORD nInBufferSize, // 输入缓冲区大小
LPVOID lpOutBuffer, // 输出缓冲区指针
DWORD nOutBufferSize, // 输出缓冲区大小
LPDWORD lpBytesReturned, // 存放返回的字节数的指针
LPOVERLAPPED lpOverlapped // 异步结构指针,同步或者异步
);
BOOL WINAPI IoControlIsOK()
{
DWORD nTypeCode = IO_IS_OK_TEST;
ULONG64 BufferInData = 0;;
DWORD NumberOfBytesRead = 0;
BOOL IsOK = DeviceIoControl(
GetDeviceHandle(), //CreateFile函数打开的设备句柄
nTypeCode,//自定义的控制码
&BufferInData,//输入缓冲区
sizeof(BufferInData),//输入缓冲区大小
&BufferInData,////输出缓冲区
sizeof(BufferInData),//输出缓冲区的大小
&NumberOfBytesRead,//实际返回的字节数,对应驱动程序中pIrp->IoStatus.Information。
NULL); ////重叠操作结构指针。同步设为NULL,DeviceIoControl将进行阻塞调用;否则,应在编程时按异步操作设计
DbgPrintA("yjx:IsOK=%d,NumberOfBytesRead=%d BufferInData=%d", IsOK, NumberOfBytesRead, BufferInData);
return NumberOfBytesRead;
}
#include
#define IO_IS_OK_TEST CTL_CODE(FILE_DEVICE_UNKNOWN, 0x803, METHOD_BUFFERED,FILE_ANY_ACCESS) //测试
void CMFCIRPCTRLDlg::OnBnClickedButtonIoCtl()
{
// TODO: 在此添加控件通知处理程序代码
INT64 InBuf[3] = { 0x123456,0x123456789ABCDEF,0x888888ABC }; //输入缓冲区
INT64 OutBuf[6] = { 0 };
DWORD dwSize = 0;
DeviceIoControl(
DeviceHandle,
IO_IS_OK_TEST,
InBuf,//输入缓冲区指针
sizeof(InBuf),//2*8,//输入缓冲区大小
OutBuf,//输出缓冲区
sizeof(OutBuf), //输出缓冲区大小 6*8 =48
&dwSize,//返回 字节数 pIrp->IoStatus.Information //IRP.IOStatus.InforMation
NULL //同步异步
);
CString csStr;
csStr.Format(L"yjx:EXE:%llx,%llx,%llx,%llx,%llx,%llx dwSize=%llx .....OK\n", OutBuf[0], OutBuf[1], OutBuf[2], OutBuf[3], OutBuf[4], OutBuf[5], dwSize);
OutputDebugStringW(csStr);
}
//驱动层 获取用户层参数
Irp->AssociatedIrp.SystemBuffer;
driver->Flags |= DO_BUFFERED_IO; //IO访问方式 重要 对应 METHOD_BUFFERED
inBufLength = irpStack->Parameters.DeviceIoControl.InputBufferLength;
outBufLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength;
ioControlCode = irpStack->Parameters.DeviceIoControl.IoControlCode;
|