ReactOS 0.4.16-dev-136-g52192f1
fxrequestbufferkm.cpp
Go to the documentation of this file.
1/*++
2
3Copyright (c) Microsoft. All rights reserved.
4
5Module Name:
6
7 FxRequestBufferKm.cpp
8
9Abstract:
10
11 This module implements a memory union object
12
13Author:
14
15
16
17Environment:
18
19 Kernel mode only
20
21Revision History:
22
23--*/
24
25#include "fxsupportpch.hpp"
26
27extern "C" {
28// #include "FxRequestBufferKm.tmh"
29}
30
34 __in PFX_DRIVER_GLOBALS FxDriverGlobals,
36 __inout PMDL* MdlToFree,
37 __inout PBOOLEAN UnlockWhenFreed,
39 __in BOOLEAN ReuseMdl,
41 )
42/*++
43
44Routine Description:
45
46 This function attempts to reuse the passed-in MDL (if any) or allocates
47 a new MDL if reuse flag isn't passed-in or if the existing MDL isn't
48 big enough.
49
50Arguments:
51
52Return Value:
53 FxDriverGlobals - Driver globals
54
55 Mdl - on return it contains the MDL allocated/reused
56
57 MdlToFree - pointer to any MDL
58 * to be reused, if the size is <= current size, or
59 * freed and set to newly allocated MDL
60
61 UnlockWhenFreed - whether to unlock pages when freeing MDL
62 (if FALSE, MDL may represent just MDL buffer but the pages
63 might have already been unlocked)
64
65 Operation - Operation to pass to MmLockPages
66
67 ReuseMdl - whether to reuse *MdlToFree
68 Please note that this can be FALSE even when MDL is supplied
69
70 SizeOfMdl - on input contains size of *MdlToFree,
71 on return contains size of *Mdl
72
73Remarks:
74
75 *MdlToFree is modified only when this function frees the passed in MDL
76 Otherwise it leaves it untouched. Caller is responsible for storing
77 properly initialized value and/or freeing what's stored in the value.
78
79 --*/
80{
81 PVOID pBuf;
84 BOOLEAN oldUnlockValue;
85
86 pBuf = NULL;
87
88 oldUnlockValue = *UnlockWhenFreed;
89
90 //
91 // Format functions that use this helper call
92 // FxRequestBase::ValidateTarget which calls ContextReleaseAndRestore
93 // which unlocks any locked pages.
94 //
95 // Hence pages must already be unlocked now. Let's assert that.
96 //
97 // This condition needs to be true since we unconditionally set
98 // *UnlockWhenFreed to FALSE just below.
99 //
100 ASSERT (oldUnlockValue == FALSE);
101
102 *UnlockWhenFreed = FALSE;
103
104 //
105 // Even if ReuseMdl is not true, SizeOfMdl may be supplied to store
106 // the size of allocated MDL to be used later
107 //
108 ASSERT(ReuseMdl ? (SizeOfMdl != NULL && *MdlToFree != NULL) : TRUE);
109
110 switch (DataType) {
112 *Mdl = NULL;
113 //
114 // We should not set *MdlToFree to NULL as *MdlToFree might have a valid
115 // MDL which we should not overwrite with NULL without freeing it
116 //
117 return STATUS_SUCCESS;
118
120 if (u.Memory.Offsets != NULL) {
121 pBuf = WDF_PTR_ADD_OFFSET(u.Memory.Memory->GetBuffer(),
122 u.Memory.Offsets->BufferOffset);
123 }
124 else {
125 pBuf = u.Memory.Memory->GetBuffer();
126 }
127 // || ||
128 // \/ \/ fall through
129
131 if (pBuf == NULL) {
132 pBuf = u.Buffer.Buffer;
133 }
134
136 status = GetOrAllocateMdlWorker(FxDriverGlobals,
137 Mdl,
138 &ReuseMdl,
139 length,
140 pBuf,
141 SizeOfMdl,
142 oldUnlockValue,
143 MdlToFree
144 );
145 if (!NT_SUCCESS(status)) {
147 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
148 "Couldn't allocate memory for MDL of length 0x%x %!STATUS!", length, status);
149 return status;
150 }
151
152 //
153 // If we are reusing the MDL we need to initialize it with current
154 // buffer.
155 //
156 if (ReuseMdl == TRUE) {
158 }
159
161
162 if (!NT_SUCCESS(status)) {
164 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
165 "Couldn't lock pages for MDL 0x%p %!STATUS!", *Mdl, status);
166
167 //
168 // Free MDL only if it was not reused.
169 //
170 if (ReuseMdl == FALSE) {
171 FxMdlFree(FxDriverGlobals, *Mdl);
172 }
173
174 *Mdl = NULL;
175 return status;
176 }
177
178 *UnlockWhenFreed = TRUE;
179 *MdlToFree = *Mdl;
180
181 return STATUS_SUCCESS;
182
184 *Mdl = u.Mdl.Mdl;
185 //
186 // We should not set *MdlToFree to NULL as *MdlToFree might have a valid
187 // MDL which we should not overwrite with NULL without freeing it
188 //
189 return STATUS_SUCCESS;
190
192 if (u.RefMdl.Offsets == NULL ||
193 (u.RefMdl.Offsets->BufferOffset == 0 && u.RefMdl.Offsets->BufferLength == 0)) {
194 *Mdl = u.RefMdl.Mdl;
195 //
196 // We should not set *MdlToFree to NULL as *MdlToFree might have a valid
197 // MDL which we should not overwrite with NULL without freeing it
198 //
199 }
200 else {
201 //
202 // Do not use MmGetSystemAddressForMdlSafe because StartVa could be
203 // in UM while MappedVa (obviously) is in KM. Since
204 // IoBuildPartial Mdl basically uses
205 // pBuf - MmGetMdlVirtualAddress(SrcMdl) to compute offset, if one
206 // VA is in UM (e.g. MmGetMdlVirtualAddress(SrcMdl)), you get the
207 // (drastically) wrong offset.
208 //
209 pBuf = Mx::MxGetMdlVirtualAddress(u.RefMdl.Mdl);
210 ASSERT(pBuf != NULL);
211
212 pBuf = WDF_PTR_ADD_OFFSET(pBuf, u.RefMdl.Offsets->BufferOffset);
213
214 //
215 // GetBufferLength will compute the correct length with the given offsets
216 //
218 status = GetOrAllocateMdlWorker(FxDriverGlobals,
219 Mdl,
220 &ReuseMdl,
221 length,
222 pBuf,
223 SizeOfMdl,
224 oldUnlockValue,
225 MdlToFree
226 );
227 if (!NT_SUCCESS(status)) {
229 FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
230 "Couldn't allocate memory for MDL of length 0x%x %!STATUS!", length, status);
231 return status;
232 }
233
235 u.RefMdl.Mdl,
236 *Mdl,
237 pBuf,
238 length
239 );
240
241 *MdlToFree = *Mdl;
242 }
243
244 return STATUS_SUCCESS;
245
246 default:
247 *Mdl = NULL;
248 //
249 // We should not set *MdlToFree to NULL as *MdlToFree might have a valid
250 // MDL which we should not overwrite with NULL without freeing it
251 //
253 }
254}
255
256VOID
259 __in PWDFMEMORY_OFFSET Offsets
260 )
261{
262 PMDL pMdl;
263
264 pMdl = Memory->GetMdl();
265 if (pMdl != NULL) {
267 u.RefMdl.Memory = Memory;
268 u.RefMdl.Offsets = Offsets;
269 u.RefMdl.Mdl = pMdl;
270 }
271 else {
273 u.Memory.Memory = Memory;
274 u.Memory.Offsets = Offsets;
275 }
276}
277
static ULONG SizeOfMdl(VOID)
Definition: NtReadFile.c:36
unsigned char BOOLEAN
LONG NTSTATUS
Definition: precomp.h:26
static __inline VOID MxBuildPartialMdl(_In_ PMDL SourceMdl, _Inout_ PMDL TargetMdl, _In_ PVOID VirtualAddress, _In_ ULONG Length)
Definition: mxgeneralkm.h:663
static __inline PVOID MxGetMdlVirtualAddress(_In_ PMDL Mdl)
Definition: mxgeneralkm.h:654
static __inline VOID MxInitializeMdl(_In_ PMDL MemoryDescriptorList, _In_ PVOID BaseVa, _In_ SIZE_T Length)
Definition: mxgeneralkm.h:643
#define __inout_opt
Definition: dbghelp.h:53
#define __in
Definition: dbghelp.h:35
#define __inout
Definition: dbghelp.h:50
#define __deref_out_opt
Definition: dbghelp.h:29
#define TRACINGAPIERROR
Definition: dbgtrace.h:60
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
FP_OP Operation
Definition: fpcontrol.c:150
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP, "Enter, WDFDEVICE %p", Device)
VOID __inline FxMdlFree(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PMDL Mdl)
Definition: fxmdl.h:60
NTSTATUS FxProbeAndLockWithAccess(__in PMDL Mdl, __in KPROCESSOR_MODE AccessMode, __in LOCK_OPERATION Operation)
Definition: probeandlock.c:74
@ FxRequestBufferUnspecified
@ FxRequestBufferMemory
@ FxRequestBufferBuffer
@ FxRequestBufferReferencedMdl
@ FxRequestBufferMdl
GLuint GLsizei GLsizei * length
Definition: glext.h:6040
#define ASSERT(a)
Definition: mode.c:44
#define _Must_inspect_result_
Definition: ms_sal.h:558
#define KernelMode
Definition: asm.h:34
#define STATUS_SUCCESS
Definition: shellext.h:65
DataType
Definition: simd.h:252
#define TRACE_LEVEL_ERROR
Definition: storswtr.h:27
union FxRequestBuffer::@4810 u
ULONG GetBufferLength(VOID)
VOID SetMemory(__in IFxMemory *Memory, __in PWDFMEMORY_OFFSET Offsets)
NTSTATUS GetOrAllocateMdlWorker(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __deref_out PMDL *Mdl, __in BOOLEAN *ReuseMdl, __in LONG Length, __in PVOID Buffer, __inout size_t *SizeOfMdl, __in BOOLEAN UnlockWhenFreed, __deref_out_opt PMDL *MdlToFree)
PWDFMEMORY_OFFSET Offsets
_Must_inspect_result_ NTSTATUS GetOrAllocateMdl(__in PFX_DRIVER_GLOBALS FxDriverGlobals, __deref_out_opt PMDL *Mdl, __inout PMDL *MdlToFree, __inout PBOOLEAN UnlockWhenFreed, __in LOCK_OPERATION Operation, __in BOOLEAN ReuseMdl=FALSE, __inout_opt size_t *SizeOfMdl=NULL)
Definition: ps.c:97
unsigned char * PBOOLEAN
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define WDF_PTR_ADD_OFFSET(_ptr, _offset)
Definition: wdfcore.h:144
_In_ WDFDEVICE _In_ PVOID _In_opt_ PMDL Mdl
_Must_inspect_result_ _In_opt_ PWDF_OBJECT_ATTRIBUTES _In_ _Strict_type_match_ POOL_TYPE _In_opt_ ULONG _In_ _Out_ WDFMEMORY * Memory
Definition: wdfmemory.h:169
enum _LOCK_OPERATION LOCK_OPERATION