1 /*++
2
3 Copyright (c) Microsoft Corporation
4
5 Module Name:
6
7 FxMemoryBufferApi.cpp
8
9 Abstract:
10
11 This modules implements the C API's for the FxMemoryBuffer.
12
13 Author:
14
15
16 Environment:
17
18 kernel mode only
19
20 Revision History:
21
22 --*/
23
24 #include "coreprivshared.hpp"
25 #include "fxmemorybuffer.hpp"
26
27 extern "C" {
28 // #include "FxMemoryBufferAPI.tmh"
29 }
30
31 extern "C" {
32
33 _Must_inspect_result_
34 __drv_when(PoolType == 1 || PoolType == 257, __drv_maxIRQL(APC_LEVEL))
35 __drv_when(PoolType == 0 || PoolType == 256, __drv_maxIRQL(DISPATCH_LEVEL))
36 WDFAPI
37 NTSTATUS
38 STDCALL
WDFEXPORT(WdfMemoryCreate)39 WDFEXPORT(WdfMemoryCreate)(
40 __in
41 PWDF_DRIVER_GLOBALS DriverGlobals,
42 __in_opt
43 PWDF_OBJECT_ATTRIBUTES Attributes,
44 __in
45 __drv_strictTypeMatch(__drv_typeExpr)
46 POOL_TYPE PoolType,
47 __in_opt
48 ULONG PoolTag,
49 __in
50 __drv_when(BufferSize == 0, __drv_reportError(BufferSize cannot be zero))
51 size_t BufferSize,
52 __out
53 WDFMEMORY* Memory,
54 __out_opt
55 PVOID* Buffer
56 )
57 /*++
58
59 Routine Description:
60 Creates a WDFMEMORY handle based on the caller's specifications
61
62 Arguments:
63 Attributes - Attributes associated with this object
64
65 PoolType - The type of pool created
66
67 PoolTag - Tag to use when allocating the memory. If 0, then the frameworks
68 tag is used
69
70 BufferSize - The size of the buffer represented by the returned handle
71
72 Memory - The returned handle to the caller
73
74 Buffer - (opt) Pointer to the associated memory buffer.
75
76 Return Value:
77 STATUS_INVALID_PARAMETER - any required parameters are not present
78
79 STATUS_INSUFFICIENT_RESOURCES - could not allocated the object that backs
80 the handle
81
82 STATUS_SUCCESS - success
83
84 --*/
85 {
86 DDI_ENTRY();
87
88 PFX_DRIVER_GLOBALS pFxDriverGlobals;
89 FxMemoryObject* pBuffer;
90 WDFMEMORY hMemory;
91 NTSTATUS status;
92
93 pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
94
95 //
96 // Get the parent's globals if it is present
97 //
98 if (NT_SUCCESS(FxValidateObjectAttributesForParentHandle(pFxDriverGlobals,
99 Attributes))) {
100 FxObject* pParent;
101
102 FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
103 Attributes->ParentObject,
104 FX_TYPE_OBJECT,
105 (PVOID*)&pParent,
106 &pFxDriverGlobals);
107 }
108
109 FxPointerNotNull(pFxDriverGlobals, Memory);
110
111 if (FxIsPagedPoolType(PoolType)) {
112 status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
113 if (!NT_SUCCESS(status)) {
114 return status;
115 }
116 }
117
118 if (BufferSize == 0) {
119 status = STATUS_INVALID_PARAMETER;
120 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
121 "BufferSize == 0 not allowed, %!STATUS!", status);
122 return status;
123 }
124
125 *Memory = NULL;
126
127 status = FxValidateObjectAttributes(pFxDriverGlobals, Attributes);
128 if (!NT_SUCCESS(status)) {
129 return status;
130 }
131
132 if (PoolTag == 0) {
133 PoolTag = pFxDriverGlobals->Tag;
134 }
135
136 FxVerifierCheckNxPoolType(pFxDriverGlobals, PoolType, PoolTag);
137
138 status = FxMemoryObject::_Create(
139 pFxDriverGlobals,
140 Attributes,
141 PoolType,
142 PoolTag,
143 BufferSize,
144 &pBuffer);
145
146 if (!NT_SUCCESS(status)) {
147 return status;
148 }
149
150 status = pBuffer->Commit(Attributes, (WDFOBJECT*)&hMemory);
151
152 if (NT_SUCCESS(status)) {
153 *Memory = hMemory;
154 if (Buffer != NULL) {
155 *Buffer = pBuffer->GetBuffer();
156 }
157 }
158 else {
159 pBuffer->DeleteFromFailedCreate();
160 }
161
162 return status;
163 }
164
__drv_maxIRQL(DISPATCH_LEVEL)165 __drv_maxIRQL(DISPATCH_LEVEL)
166 PVOID
167 WDFAPI
168 STDCALL
169 WDFEXPORT(WdfMemoryGetBuffer)(
170 __in
171 PWDF_DRIVER_GLOBALS DriverGlobals,
172 __in
173 WDFMEMORY Memory,
174 __out_opt
175 size_t* BufferSize
176 )
177 /*++
178
179 Routine Description:
180 Retrieves the raw pointers associated with WDFMEMORY handle
181
182 Arguments:
183 Memory - handle to the WDFMEMORY
184
185 BufferSize - the size / length of the buffer
186
187 Return Value:
188 raw buffer
189
190 --*/
191 {
192 DDI_ENTRY();
193
194 IFxMemory* pMemory;
195
196 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
197 Memory,
198 IFX_TYPE_MEMORY,
199 (PVOID*)&pMemory);
200
201 if (BufferSize != NULL) {
202 *BufferSize = pMemory->GetBufferSize();
203 }
204
205 return pMemory->GetBuffer();
206 }
207
208 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)209 __drv_maxIRQL(DISPATCH_LEVEL)
210 NTSTATUS
211 WDFAPI
212 STDCALL
213 WDFEXPORT(WdfMemoryCopyToBuffer)(
214 __in
215 PWDF_DRIVER_GLOBALS DriverGlobals,
216 __in
217 WDFMEMORY SourceMemory,
218 __in
219 size_t SourceOffset,
220 __out_bcount( NumBytesToCopyTo)
221 PVOID Buffer,
222 __in
223 __drv_when(NumBytesToCopyTo == 0, __drv_reportError(NumBytesToCopyTo cannot be zero))
224 size_t NumBytesToCopyTo
225 )
226 /*++
227
228 Routine Description:
229 Copies memory from a WDFMEMORY handle to a raw pointer
230
231 Arguments:
232 SourceMemory - Memory handle whose contents we are copying from.
233
234 SourceOffset - Offset into SourceMemory from which the copy starts.
235
236 Buffer - Memory whose contents we are copying into
237
238 NumBytesToCopyTo - Number of bytes to copy into buffer.
239
240 Return Value:
241
242 STATUS_BUFFER_TOO_SMALL - SourceMemory is smaller than the requested number
243 of bytes to be copied.
244
245 NTSTATUS
246
247 --*/
248 {
249 DDI_ENTRY();
250
251 PFX_DRIVER_GLOBALS pFxDriverGlobals;
252 IFxMemory* pSource;
253 WDFMEMORY_OFFSET srcOffsets;
254 WDFMEMORY_OFFSET dstOffsets;
255 NTSTATUS status;
256
257 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
258 SourceMemory,
259 IFX_TYPE_MEMORY,
260 (PVOID*) &pSource);
261
262 pFxDriverGlobals = pSource->GetDriverGlobals();
263
264 FxPointerNotNull(pFxDriverGlobals, Buffer);
265
266 if (NumBytesToCopyTo == 0) {
267 status =STATUS_INVALID_PARAMETER;
268 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
269 "Zero bytes to copy not allowed, %!STATUS!", status);
270 return status;
271 }
272
273 RtlZeroMemory(&srcOffsets, sizeof(srcOffsets));
274 srcOffsets.BufferLength = NumBytesToCopyTo;
275 srcOffsets.BufferOffset = SourceOffset;
276
277 RtlZeroMemory(&dstOffsets, sizeof(dstOffsets));
278 dstOffsets.BufferLength = NumBytesToCopyTo;
279 dstOffsets.BufferOffset = 0;
280
281 return pSource->CopyToPtr(&srcOffsets,
282 Buffer,
283 NumBytesToCopyTo,
284 &dstOffsets);
285 }
286
287 _Must_inspect_result_
__drv_maxIRQL(DISPATCH_LEVEL)288 __drv_maxIRQL(DISPATCH_LEVEL)
289 NTSTATUS
290 WDFAPI
291 STDCALL
292 WDFEXPORT(WdfMemoryCopyFromBuffer)(
293 __in
294 PWDF_DRIVER_GLOBALS DriverGlobals,
295 __in
296 WDFMEMORY DestinationMemory,
297 __in
298 size_t DestinationOffset,
299 __in
300 PVOID Buffer,
301 __in
302 __drv_when(NumBytesToCopyFrom == 0, __drv_reportError(NumBytesToCopyFrom cannot be zero))
303 size_t NumBytesToCopyFrom
304 )
305 /*++
306
307 Routine Description:
308 Copies memory from a raw pointer into a WDFMEMORY handle
309
310 Arguments:
311 DestinationMemory - Memory handle whose contents we are copying into
312
313 DestinationOffset - Offset into DestinationMemory from which the copy
314 starts.
315
316 Buffer - Buffer whose context we are copying from
317
318 NumBytesToCopyFrom - Number of bytes to copy from
319
320 Return Value:
321
322 STATUS_INVALID_BUFFER_SIZE - DestinationMemory is not large enough to contain
323 the number of bytes requested to be copied
324
325 NTSATUS
326
327 --*/
328
329 {
330 DDI_ENTRY();
331
332 PFX_DRIVER_GLOBALS pFxDriverGlobals;
333 WDFMEMORY_OFFSET srcOffsets;
334 WDFMEMORY_OFFSET dstOffsets;
335 IFxMemory* pDest;
336 NTSTATUS status;
337
338 FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
339 DestinationMemory,
340 IFX_TYPE_MEMORY,
341 (PVOID*) &pDest);
342
343 pFxDriverGlobals = pDest->GetDriverGlobals();
344
345 FxPointerNotNull(pFxDriverGlobals, Buffer);
346
347 if (NumBytesToCopyFrom == 0) {
348 status = STATUS_INVALID_PARAMETER;
349 DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
350 "Zero bytes to copy not allowed, %!STATUS!", status);
351 return status;
352 }
353
354 RtlZeroMemory(&srcOffsets, sizeof(srcOffsets));
355 srcOffsets.BufferLength = NumBytesToCopyFrom;
356 srcOffsets.BufferOffset = 0;
357
358 RtlZeroMemory(&dstOffsets, sizeof(dstOffsets));
359 dstOffsets.BufferLength = NumBytesToCopyFrom;
360 dstOffsets.BufferOffset = DestinationOffset;
361
362 return pDest->CopyFromPtr(&dstOffsets,
363 Buffer,
364 NumBytesToCopyFrom,
365 &srcOffsets);
366 }
367
368 } // extern "C"
369