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