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
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
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
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
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
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
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
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
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*
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
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