1 /*++
2
3 Copyright (c) Microsoft Corporation
4
5 Module Name:
6
7 FxRequestOutputBuffer.cpp
8
9 Abstract:
10
11 This module implements class representing the output buffer in an FxRequest
12
13 Author:
14
15
16
17 Environment:
18
19 Both kernel and user mode
20
21 Revision History:
22
23
24
25
26 --*/
27
28 #include "coreprivshared.hpp"
29
30 // Tracing support
31 extern "C" {
32 // #include "FxRequestOutputBuffer.tmh"
33 }
34
35 PVOID
GetBuffer(VOID)36 FxRequestOutputBuffer::GetBuffer(
37 VOID
38 )
39 /*++
40
41 Routine Description:
42 Returns the output buffer that has been cached away by the call to SetBuffer()
43
44 Arguments:
45 None
46
47 Return Value:
48 Valid memory or NULL on error
49
50 --*/
51 {
52 FxIrp* irp = GetRequest()->GetFxIrp();
53
54 ASSERT(irp->GetMajorFunction() == IRP_MJ_DEVICE_CONTROL ||
55 irp->GetMajorFunction() == IRP_MJ_INTERNAL_DEVICE_CONTROL);
56
57 switch (irp->GetParameterIoctlCodeBufferMethod()) {
58 case METHOD_BUFFERED:
59 //
60 // For buffered ioctls, input and output buffer pointers are same.
61 //
62 return m_Buffer;
63
64 case METHOD_IN_DIRECT:
65 case METHOD_OUT_DIRECT:
66 //
67 // FxRequest::GetDeviceControlOutputMemoryObject has already called
68 // MmGetSystemAddressForMdlSafe and returned success, so we know that
69 // we can safely call MmGetSystemAddressForMdlSafe again to get a
70 // valid VA pointer.
71 //
72 return Mx::MxGetSystemAddressForMdlSafe(m_Mdl, NormalPagePriority);
73
74 case METHOD_NEITHER:
75 return m_Buffer;
76
77 default:
78 ASSERT(FALSE);
79 return NULL;
80 }
81 }
82
83 size_t
GetBufferSize(VOID)84 FxRequestOutputBuffer::GetBufferSize(
85 VOID
86 )
87 /*++
88
89 Routine Description:
90 Returns the size of the buffer returned by GetBuffer()
91
92 Arguments:
93 None
94
95 Return Value:
96 Buffer length or 0 on error
97
98 --*/
99 {
100 FxIrp* irp = GetRequest()->GetFxIrp();
101
102 ASSERT(irp->GetMajorFunction() == IRP_MJ_DEVICE_CONTROL ||
103 irp->GetMajorFunction() == IRP_MJ_INTERNAL_DEVICE_CONTROL);
104
105 return irp->GetParameterIoctlOutputBufferLength();
106 }
107
108 _Must_inspect_result_
109 PMDL
GetMdl(VOID)110 FxRequestOutputBuffer::GetMdl(
111 VOID
112 )
113 /*++
114
115 Routine Description:
116 Returns the PMDL from the irp if one exists, otherwise NULL
117
118 Arguments:
119 None
120
121 Return Value:
122 a valid PMDL or NULL (not an error condition)
123
124 --*/
125 {
126 FxIrp* irp = GetRequest()->GetFxIrp();
127
128 ASSERT(irp->GetMajorFunction() == IRP_MJ_DEVICE_CONTROL ||
129 irp->GetMajorFunction() == IRP_MJ_INTERNAL_DEVICE_CONTROL);
130
131 switch (irp->GetParameterIoctlCodeBufferMethod()) {
132 case METHOD_IN_DIRECT:
133 case METHOD_OUT_DIRECT:
134 return m_Mdl;
135
136 default:
137 return NULL;
138 }
139 }
140
141 WDFMEMORY
GetHandle(VOID)142 FxRequestOutputBuffer::GetHandle(
143 VOID
144 )
145 /*++
146
147 Routine Description:
148 Returns the handle that will represent this object to the driver writer.
149
150 Arguments:
151 None
152
153 Return Value:
154 Valid WDF handle
155
156 --*/
157 {
158 return GetRequest()->GetMemoryHandle(
159 FIELD_OFFSET(FxRequest, m_OutputBufferOffset));
160 }
161
162 USHORT
GetFlags(VOID)163 FxRequestOutputBuffer::GetFlags(
164 VOID
165 )
166 /*++
167
168 Routine Description:
169 Returns the flags associated with this buffer. This currently only includes
170 whether the buffer is read only or not
171
172 Arguments:
173 None
174
175 Return Value:
176 flags from IFxMemoryFlags
177
178 --*/
179 {
180 FxIrp* irp = GetRequest()->GetFxIrp();
181
182 ASSERT(irp->GetMajorFunction() == IRP_MJ_DEVICE_CONTROL ||
183 irp->GetMajorFunction() == IRP_MJ_INTERNAL_DEVICE_CONTROL);
184
185 switch (irp->GetParameterIoctlCodeBufferMethod()) {
186 case METHOD_IN_DIRECT:
187 return IFxMemoryFlagReadOnly;
188
189 case METHOD_BUFFERED:
190 case METHOD_OUT_DIRECT:
191 case METHOD_NEITHER: // since it is neither, we can't tell, so leave it as 0
192 default:
193 return 0;
194 }
195 }
196
197 PFX_DRIVER_GLOBALS
GetDriverGlobals(VOID)198 FxRequestOutputBuffer::GetDriverGlobals(
199 VOID
200 )
201 /*++
202
203 Routine Description:
204 Returns the driver globals
205
206 Arguments:
207 none
208
209 Return Value:
210 Driver globals pointer
211
212 --*/
213 {
214 return GetRequest()->GetDriverGlobals();
215 }
216
217 ULONG
AddRef(__in PVOID Tag,__in LONG Line,__in_opt PSTR File)218 FxRequestOutputBuffer::AddRef(
219 __in PVOID Tag,
220 __in LONG Line,
221 __in_opt PSTR File
222 )
223 /*++
224
225 Routine Description:
226 Adds an irp reference to the owning FxRequest. This object does not maintain
227 its own reference count. A request cannot be completed with outstanding
228 irp references.
229
230 Arguments:
231 Tag - the tag to use to track the reference
232
233 Line - The line number of the caller
234
235 File - the file name of the caller
236
237 Return Value:
238 current reference count
239
240 --*/
241 {
242 UNREFERENCED_PARAMETER(Tag);
243 UNREFERENCED_PARAMETER(Line);
244 UNREFERENCED_PARAMETER(File);
245
246 GetRequest()->AddIrpReference();
247
248 return 2;
249 }
250
251 ULONG
Release(__in PVOID Tag,__in LONG Line,__in_opt PSTR File)252 FxRequestOutputBuffer::Release(
253 __in PVOID Tag,
254 __in LONG Line,
255 __in_opt PSTR File
256 )
257 /*++
258
259 Routine Description:
260 Removes an irp reference to the owning FxRequest. This object does not maintain
261 its own reference count. A request cannot be completed with outstanding
262 irp references.
263
264 Arguments:
265 Tag - the tag to use to track the release
266
267 Line - The line number of the caller
268
269 File - the file name of the caller
270
271 Return Value:
272 current reference count
273
274 --*/
275 {
276 UNREFERENCED_PARAMETER(Tag);
277 UNREFERENCED_PARAMETER(Line);
278 UNREFERENCED_PARAMETER(File);
279
280 GetRequest()->ReleaseIrpReference();
281
282 return 1;
283 }
284
285 FxRequest*
GetRequest(VOID)286 FxRequestOutputBuffer::GetRequest(
287 VOID
288 )
289 /*++
290
291 Routine Description:
292 Return the owning FxRequest based on this object's address
293
294 Arguments:
295 None
296
297 Return Value:
298 owning FxRequest
299
300 --*/
301 {
302 return CONTAINING_RECORD(this, FxRequest, m_OutputBuffer);
303 }
304
305 VOID
Delete(VOID)306 FxRequestOutputBuffer::Delete(
307 VOID
308 )
309 /*++
310
311 Routine Description:
312 Attempt to delete this interface. Since this is an embedded object, it
313 cannot be deleted. Since this function is only called internally, the
314 internal caller knows if the IFxMemory is deletable because the internal
315 caller allocated the IFxMemory to begin with.
316
317 Arguments:
318 None
319
320 Return Value:
321 None
322
323 --*/
324 {
325 // this function should never be called
326 ASSERT(FALSE);
327 }
328