-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathQueue.c
197 lines (146 loc) · 5.46 KB
/
Queue.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
/*++
Module Name:
queue.c
Abstract:
This file contains the queue entry points and callbacks.
Environment:
Kernel-mode Driver Framework
--*/
#include "driver.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text (PAGE, SymResKQueueInitialize)
#endif
NTSTATUS
SymResKQueueInitialize(
_In_ WDFDEVICE Device
)
/*++
Routine Description:
The I/O dispatch callbacks for the frameworks device object
are configured in this function.
A single default I/O Queue is configured for parallel request
processing, and a driver context memory allocation is created
to hold our structure QUEUE_CONTEXT.
Arguments:
Device - Handle to a framework device object.
Return Value:
VOID
--*/
{
WDFQUEUE queue;
NTSTATUS status;
WDF_IO_QUEUE_CONFIG queueConfig;
PAGED_CODE();
//
// Configure a default queue so that requests that are not
// configure-fowarded using WdfDeviceConfigureRequestDispatching to goto
// other queues get dispatched here.
//
WDF_IO_QUEUE_CONFIG_INIT_DEFAULT_QUEUE(
&queueConfig,
WdfIoQueueDispatchParallel
);
queueConfig.EvtIoDeviceControl = SymResKEvtIoDeviceControl;
queueConfig.EvtIoStop = SymResKEvtIoStop;
status = WdfIoQueueCreate(
Device,
&queueConfig,
WDF_NO_OBJECT_ATTRIBUTES,
&queue
);
if(!NT_SUCCESS(status)) {
// TraceEvents(TRACE_LEVEL_ERROR, TRACE_QUEUE, "WdfIoQueueCreate failed %!STATUS!", status);
return status;
}
return status;
}
VOID
SymResKEvtIoDeviceControl(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ size_t OutputBufferLength,
_In_ size_t InputBufferLength,
_In_ ULONG IoControlCode
)
/*++
Routine Description:
This event is invoked when the framework receives IRP_MJ_DEVICE_CONTROL request.
Arguments:
Queue - Handle to the framework queue object that is associated with the
I/O request.
Request - Handle to a framework request object.
OutputBufferLength - Size of the output buffer in bytes
InputBufferLength - Size of the input buffer in bytes
IoControlCode - I/O control code.
Return Value:
VOID
--*/
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL,
"%s Queue 0x%p, Request 0x%p OutputBufferLength %d InputBufferLength %d IoControlCode %d",
__func__, Queue, Request, (int) OutputBufferLength, (int) InputBufferLength, IoControlCode);
WdfRequestComplete(Request, STATUS_SUCCESS);
return;
}
VOID
SymResKEvtIoStop(
_In_ WDFQUEUE Queue,
_In_ WDFREQUEST Request,
_In_ ULONG ActionFlags
)
/*++
Routine Description:
This event is invoked for a power-managed queue before the device leaves the working state (D0).
Arguments:
Queue - Handle to the framework queue object that is associated with the
I/O request.
Request - Handle to a framework request object.
ActionFlags - A bitwise OR of one or more WDF_REQUEST_STOP_ACTION_FLAGS-typed flags
that identify the reason that the callback function is being called
and whether the request is cancelable.
Return Value:
VOID
--*/
{
DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL,
"%s Queue 0x%p, Request 0x%p ActionFlags %d",
__func__, Queue, Request, ActionFlags);
//
// In most cases, the EvtIoStop callback function completes, cancels, or postpones
// further processing of the I/O request.
//
// Typically, the driver uses the following rules:
//
// - If the driver owns the I/O request, it calls WdfRequestUnmarkCancelable
// (if the request is cancelable) and either calls WdfRequestStopAcknowledge
// with a Requeue value of TRUE, or it calls WdfRequestComplete with a
// completion status value of STATUS_SUCCESS or STATUS_CANCELLED.
//
// Before it can call these methods safely, the driver must make sure that
// its implementation of EvtIoStop has exclusive access to the request.
//
// In order to do that, the driver must synchronize access to the request
// to prevent other threads from manipulating the request concurrently.
// The synchronization method you choose will depend on your driver's design.
//
// For example, if the request is held in a shared context, the EvtIoStop callback
// might acquire an internal driver lock, take the request from the shared context,
// and then release the lock. At this point, the EvtIoStop callback owns the request
// and can safely complete or requeue the request.
//
// - If the driver has forwarded the I/O request to an I/O target, it either calls
// WdfRequestCancelSentRequest to attempt to cancel the request, or it postpones
// further processing of the request and calls WdfRequestStopAcknowledge with
// a Requeue value of FALSE.
//
// A driver might choose to take no action in EvtIoStop for requests that are
// guaranteed to complete in a small amount of time.
//
// In this case, the framework waits until the specified request is complete
// before moving the device (or system) to a lower power state or removing the device.
// Potentially, this inaction can prevent a system from entering its hibernation state
// or another low system power state. In extreme cases, it can cause the system
// to crash with bugcheck code 9F.
//
return;
}