-
Notifications
You must be signed in to change notification settings - Fork 33
/
Copy pathforward_progress.c
297 lines (204 loc) · 7.51 KB
/
forward_progress.c
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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
#include "ramdisk.h"
void EvtForwardProgressRequestDestroy(WDFOBJECT request)
/*++
Routine Description:
This event is called when the request memory is about to be freed.
Reserved requests get deleted only when the queue gets deleted.
Arguments:
Request - Handle to a framework request object.
Return Value:
VOID
--*/
{
PFWD_PROGRESS_REQUEST_CONTEXT context;
context = GetForwardProgressRequestContext(request);
}
void EvtForwardProgressRequestCleanup(WDFOBJECT request)
/*++
Routine Description:
This event is called when the reserved request is about to be deleted.
NOTE: In case of reserved request this callback doesn't get called after the
I/O is done but only when the request is about to be deleted.
Arguments:
Request - Handle to a framework request object.
Return Value:
VOID
--*/
{
FWD_PROGRESS_REQUEST_CONTEXT *context;
context = GetForwardProgressRequestContext(request);
// Cleanup any resources allocated earlier for reserved requests here.
}
NTSTATUS AllocateAdditionalRequestContext(__in WDFREQUEST request)
/*++
Routine Description:
Allocate resources used by request.
Set the EvtCleanupCallback and EvtDestroyCallback
to show the lifetime of a Reserved request.
Arguments:
Request - Handle to a framework request object.
Return Value:
NTSTATUS
--*/
{
WDF_OBJECT_ATTRIBUTES requestContextAttributes;
PFWD_PROGRESS_REQUEST_CONTEXT reqContext;
NTSTATUS status;
WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(&requestContextAttributes,
FWD_PROGRESS_REQUEST_CONTEXT);
requestContextAttributes.EvtCleanupCallback = EvtForwardProgressRequestCleanup;
requestContextAttributes.EvtDestroyCallback = EvtForwardProgressRequestDestroy;
status = WdfObjectAllocateContext(request,
&requestContextAttributes,
&reqContext);
return status;
}
WDF_IO_FORWARD_PROGRESS_ACTION
EvtIoWdmIrpForForwardProgress(
__in WDFQUEUE Queue,
__in PIRP Irp
)
/*++
Routine Description:
A driver's EvtIoWdmIrpForForwardProgress callback function is used for
examining an IRP and tell the framework whether to use a reserved
request object for the IRP or to fail the I/O request by completing
it with an error status value.
Arguments:
Queue - Handle to the framework queue object that is associated with the
I/O request.
Irp -
Return Value:
WDF_IO_FORWARD_PROGRESS_ACTION
WdfIoForwardProgressActionFailRequest is returned it causes
the Framework to fail the IRP.
WdfIoForwardProgressActionUseReservedRequest is returned it causes
the framework to use a reserved request to handle the IRP.
--*/
{
PIO_STACK_LOCATION irpStack;
WDF_IO_FORWARD_PROGRESS_ACTION action;
UNREFERENCED_PARAMETER(Queue);
irpStack = IoGetCurrentIrpStackLocation(Irp);
switch (irpStack->MajorFunction) {
case IRP_MJ_READ:
case IRP_MJ_WRITE:
case IRP_MJ_DEVICE_CONTROL:
case IRP_MJ_INTERNAL_DEVICE_CONTROL:
//
// Use reserved request for reads, writes, IOCTL's
//
action = WdfIoForwardProgressActionUseReservedRequest;
break;
default:
//
// Just for demonstration of the available actions fail the
// other I/O IRP's
//
action = WdfIoForwardProgressActionFailRequest;
break;
}
return action;
}
NTSTATUS
EvtIoAllocateResourcesForReservedRequest(
__in WDFQUEUE Queue,
__in WDFREQUEST Request
)
/*++
Routine Description:
A driver's EvtIoAllocateResourcesForReservedRequest callback function
allocates and stores request-specific resources for request objects that
the framework is reserving for low-memory situations.
NOTE: You can't call WdfRequestGetIoQueue for Reserved requests
Use the Queue handle passed in.
Arguments:
Queue - Handle to the framework queue object that is associated with the
I/O request.
Request - Handle to a framework request object.
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
PFWD_PROGRESS_REQUEST_CONTEXT fwdReqContext;
UNREFERENCED_PARAMETER(Queue);
UNREFERENCED_PARAMETER(fwdReqContext);
status = STATUS_SUCCESS;
ASSERT(WdfRequestIsReserved(Request));
//
// Allocate all resources needed for the request here. If you need to
// pre-allocate memory or any other resource do it in this callback and
// store it in the context.
//
status = AllocateAdditionalRequestContext(Request);
if (NT_SUCCESS(status)) {
PFWD_PROGRESS_REQUEST_CONTEXT fwdReqContext;
fwdReqContext = GetForwardProgressRequestContext(Request);
}
return status;
}
NTSTATUS
EvtIoAllocateResources(
__in WDFQUEUE Queue,
__in WDFREQUEST Request
)
/*++
Routine Description:
This event is called for the driver to allocate request
resources for immediate use (unlike reserved requests which is for use under
low memory).
It is called immediately after the framework has received an IRP and created
a request object for the IRP.
Arguments:
Queue - Handle to the framework queue object that is associated with the
I/O request.
Request - Handle to a framework request object.
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
PFWD_PROGRESS_REQUEST_CONTEXT fwdReqContext;
UNREFERENCED_PARAMETER(Queue);
status = STATUS_SUCCESS;
//
// Allocate all resources needed for the request here and store it in the request
// context.
//
fwdReqContext = GetForwardProgressRequestContext(Request);
return status;
}
NTSTATUS SetForwardProgressOnQueue(__in WDFQUEUE queue)
/*++
Routine Description:
Set forward progress on the top level( handles one of the major I/O IRP)
queue we created.
The default is always a top level queue or if the queue was configured
with WdfDeviceConfigureRequestDispatching.
Arguments:
Queue - Handle to the framework queue object that is associated with the
I/O request.
Return Value:
NTSTATUS
--*/
{
WDF_IO_QUEUE_FORWARD_PROGRESS_POLICY forwardProgressPolicy;
NTSTATUS status;
// The policy is configurable by the user. In the code segment below
// WdfIoForwardProgressReservedPolicyUseExamine
// is demonstrated. If your driver supports paging I/O you should select
// WdfIoForwardProgressReservedPolicyPagingIO.
// MAX_RESERVED_REQUESTS should be adjusted depending on the number of parallel
// requests the driver wants to handle under low memory conditions. It may
// require some hit and trial to get the right number.
WDF_IO_QUEUE_FORWARD_PROGRESS_POLICY_EXAMINE_INIT(&forwardProgressPolicy, MAX_RESERVED_REQUESTS, EvtIoWdmIrpForForwardProgress);
forwardProgressPolicy.EvtIoAllocateResourcesForReservedRequest = EvtIoAllocateResourcesForReservedRequest;
forwardProgressPolicy.EvtIoAllocateRequestResources = EvtIoAllocateResources;
status = WdfIoQueueAssignForwardProgressPolicy(queue, &forwardProgressPolicy);
if (!NT_SUCCESS(status)) {
KdPrint(("Error WdfIoQueueAssignForwardProgressPolicy 0x%x.\n", status));
return status;
}
return status;
}