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
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// #include 


#include


#define NTSTRSAFE_LIB
#include



#define CPP_MAX_COM_ID 32
#define DELAY_ONE_MICROSECOND (-10)
#define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
#define DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)
static PDEVICE_OBJECT s_fltobj[CPP_MAX_COM_ID] = {0};
static PDEVICE_OBJECT s_nextobj[CPP_MAX_COM_ID] = {0};


NTSTATUS ccpAttachDevice(
PDRIVER_OBJECT driver
, PDEVICE_OBJECT oldobj
, PDEVICE_OBJECT *fltobj
, PDEVICE_OBJECT *next)
{
NTSTATUS status;
PDEVICE_OBJECT topdev = NULL;
// IoCreateDevice 创建设备对象
// driver 驱动程序对象 , oldobj->DeviceType设备的类型
// fltobj指向接收DEVICE_OBJECT结构体的指针
status = IoCreateDevice (driver, 0, NULL, oldobj->DeviceType, 0, FALSE, fltobj);
if (status != STATUS_SUCCESS)
{
return status;
}

if (oldobj -> Flags & DO_BUFFERED_IO)
{
(*fltobj)->Flags |= DO_BUFFERED_IO;
}
if (oldobj->Flags & DO_DIRECT_IO)
{
(*fltobj)->Flags |= DO_DIRECT_IO;
}
if (oldobj->Flags & FILE_DEVICE_SECURE_OPEN)
{
(*fltobj)->Characteristics |= FILE_DEVICE_SECURE_OPEN;
}
(*fltobj)->Flags |= DO_POWER_PAGABLE;
// 将调用方的设备对象附加到设备对象链中的最高层,并返回之前在设备对象链中最高的设备对象。
// fltobj需要附着的源设备对象, oldobj附着到的目标设备对象
// 把fltobj放到oldobj所在的链的顶端
topdev = IoAttachDeviceToDeviceStack (*fltobj, oldobj);
if (NULL == topdev)
{
// 从系统中删除一个设备对象fltobj
// VOID IoDeleteDevice(
// _In_ PDEVICE_OBJECT DeviceObject
// );
// DeviceObject 要删除的设备对象指针
IoDeleteDevice (*fltobj);
*fltobj = NULL;
status = STATUS_UNSUCCESSFUL;
return status;
}
*next = topdev;

(*fltobj)->Flags = (*fltobj)->Flags & ~DO_DEVICE_INITIALIZING;
return STATUS_SUCCESS;
}

PDEVICE_OBJECT cppOpenCom(ULONG id, NTSTATUS *status)
{
UNICODE_STRING name_str;
static WCHAR name[32] = {0};
PFILE_OBJECT fileobj = NULL;
PDEVICE_OBJECT devobj = NULL;
memset (name, 0, sizeof(WCHAR)*32);
RtlStringCchPrintfW(name, 32, L"\\Device\\Serial%d", id);
RtlInitUnicodeString (&name_str, name);
// 获取命名对象
// IoGetDeviceObjectPointer返回一个指向命名对象设备堆栈顶部的对象指针和
// 相应的文件对象指针
// The IoGetDeviceObjectPointer routine returns a pointer to the top object
// in the named device object's stack and a pointer to the corresponding file object,
// if the requested access to the objects can be granted.
*status = IoGetDeviceObjectPointer(&name_str, FILE_ALL_ACCESS, &fileobj, &devobj);
if (*status == STATUS_SUCCESS)
{
// 解除引用。
// ObDereferenceObject检查给定对象的引用计
// The ObDereferenceObject routine decrements the given object's reference count
// and performs retention checks.
ObDereferenceObject(fileobj);
}
return devobj;
}




void cppAttachAllCom(PDRIVER_OBJECT driver)
{
ULONG i;
PDEVICE_OBJECT com_ob;
NTSTATUS status;
for (i = 0; i < CPP_MAX_COM_ID; ++i)
{
com_ob = cppOpenCom (i, &status);
if (NULL == com_ob)
{
continue;
}
ccpAttachDevice(driver, com_ob, &s_fltobj[i], &s_nextobj[i]);
}
}

NTSTATUS ccpDispatch(PDEVICE_OBJECT device, PIRP irp)
{
PIO_STACK_LOCATION irpsp = IoGetCurrentIrpStackLocation (irp);
NTSTATUS status;
ULONG i, j;
for (i = 0; i < CPP_MAX_COM_ID; ++i)
{
if (device == s_fltobj[i])
{
if (irpsp->MajorFunction == IRP_MJ_POWER)
{
// The PoStartNextPowerIrp routine signals the power manager that
// the driver is ready to handle the next power IRP.
// (Windows Server 2003, Windows XP, and Windows 2000 only.)
PoStartNextPowerIrp (irp);
// The IoSkipCurrentIrpStackLocation macro modifies the system's
// IO_STACK_LOCATION array pointer, so that when the current
// driver calls the next-lower driver, that driver receives
// the same IO_STACK_LOCATION structure that
// the current driver received.
IoSkipCurrentIrpStackLocation (irp);
// The PoCallDriver routine passes a power IRP to the next-lower
// driver in the device stack.
// (Windows Server 2003, Windows XP, and Windows 2000 only.)
return PoCallDriver (s_nextobj[i], irp);
}
if (irpsp->MajorFunction == IRP_MJ_WRITE)
{
ULONG len = (irpsp->Parameters.Write.Length);
PUCHAR buf = NULL;
if (irp->MdlAddress != NULL)
{
// The MmGetSystemAddressForMdlSafe macro returns a
// nonpaged system-space virtual address for the buffer that
// the specified MDL describes.
buf = (PUCHAR)MmGetSystemAddressForMdlSafe(
irp->MdlAddress, NormalPagePriority);
}
else
{
buf = (PUCHAR)irp->UserBuffer;
}
if (NULL == buf)
{
buf = (PUCHAR)irp->AssociatedIrp.SystemBuffer;
}

for (j = 0; j < len; ++j)
{
DbgPrint("comcap: Send Data: %2x\r\n", buf[j]);
}
}

IoSkipCurrentIrpStackLocation (irp);
// The IoCallDriver routine sends an IRP to the driver associated with
// a specified device object.
// 发送irp给s_nextobj[i]
return IoCallDriver (s_nextobj[i], irp);
}
}
irp->IoStatus.Information = 0;
irp->IoStatus.Status = STATUS_INVALID_PARAMETER;
// The IoCompleteRequest routine indicates that the caller has completed all processing
// for a given I/O request and is returning the given IRP to the I/O manager.
// 调用者已完成所有处理对于一个给定的I / O请求和返回给定的irp到I / O管理器。
IoCompleteRequest(irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}


void ccpUnload(PDRIVER_OBJECT drv)
{
ULONG i;
LARGE_INTEGER interval;
for (i = 0; i < CPP_MAX_COM_ID; ++i)
{
if (NULL != s_nextobj[i])
{
// The IoDetachDevice routine releases an attachment between the caller's
// device object and a lower driver's device object.
// 从设备链上删除 s_nextobj[i]
// s_nextobj[i] 下层堆栈上的设备对象
IoDetachDevice (s_nextobj[i]);
}
}
interval.QuadPart = 5*1000*DELAY_ONE_MILLISECOND;
// The KeDelayExecutionThread routine puts the current thread into an alertable or
// nonalertable wait state for a specified interval.
// 延时
KeDelayExecutionThread (KernelMode, FALSE, &interval);
for (i = 0; i < CPP_MAX_COM_ID; ++i)
{
if (NULL != s_fltobj[i])
{
IoDeleteDevice (s_fltobj[i]);
}
}
}

NTSTATUS DriverEntry(PDRIVER_OBJECT driver, PUNICODE_STRING reg_path)
{
size_t i;
#if DBG
_asm int 3;
#endif
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; ++i)
{
driver->MajorFunction[i] = ccpDispatch;
}

driver->DriverUnload = ccpUnload ;
cppAttachAllCom (driver);
return STATUS_SUCCESS;
}

20150710132330888