1 /*++
2 
3 Copyright (c) Microsoft Corporation
4 
5 Module Name:
6 
7     fxhandle.h
8 
9 Abstract:
10 
11     Private interfaces for Driver Frameworks handle functions.
12 
13 Author:
14 
15 
16 
17 
18 Environment:
19 
20     Both kernel and user mode
21 
22 Revision History:
23 
24 
25 --*/
26 
27 #ifndef _WDFPHANDLE_H_
28 #define _WDFPHANDLE_H_
29 
30 /**
31 
32  Framework Object Memory Layout (x86 32 bit)
33 
34  Note: The handle is XOR'ed with (-1) to scramble it
35 
36                         ---------------------- handle + sizeof(ContextSize)
37                         |                    |
38                         | Drivers Context    |
39                         | Memory             |
40                         |                    |
41 WDFOBJECT handle ->     ---------------------- this + sizeof(C++_OBJECT) + _extrasize + sizeof(FxContextHeader)
42                         |                    |
43                         | FxContextHeader    |
44                         |                    |
45                         ---------------------- this + sizeof(C++_OBJECT) + _extrasize (m_ObjectSize)
46                         |                    |
47                         |  C++ Object        |
48                         |  "extra" memory    |
49                         |                    |
50                         |--------------------| this + sizeof(C++_OBJECT)
51                         |                    |
52                         |  C++ Object        |
53                         |                    |
54                         |                    |
55 Base Pool Allocation -> ---------------------- this
56 C++ this pointer
57 
58 **/
59 
60 struct FxContextHeader;
61 
62 struct FxContextHeader {
63     //
64     // Backpointer to the object that this is a context for
65     //
66     FxObject* Object;
67 
68     //
69     // Next context in the chain
70     //
71     FxContextHeader* NextHeader;
72 
73     //
74     // Function to call when object is deleted
75     //
76     PFN_WDF_OBJECT_CONTEXT_CLEANUP EvtCleanupCallback;
77 
78     //
79     // Function to call when the object's memory is destroyed
80     // when the last reference count goes to zero
81     //
82     PFN_WDF_OBJECT_CONTEXT_DESTROY EvtDestroyCallback;
83 
84     //
85     // Type associated with this context
86     //
87     PCWDF_OBJECT_CONTEXT_TYPE_INFO ContextTypeInfo;
88 
89     //
90     // Start of client's context
91     //
92     DECLSPEC_ALIGN(MEMORY_ALLOCATION_ALIGNMENT) ULONG_PTR Context[1];
93 };
94 
95 //
96 // We want all the way up to the aligned field, but not the field itself
97 //
98 #define FX_CONTEXT_HEADER_SIZE FIELD_OFFSET(FxContextHeader, Context)
99 
100 #define COMPUTE_RAW_OBJECT_SIZE(_rawObjectSize) \
101     ((USHORT) WDF_ALIGN_SIZE_UP(_rawObjectSize, MEMORY_ALLOCATION_ALIGNMENT))
102 
103 //
104 // Computes the size required for a fixed size object plus any extra buffer space
105 // it requires.  The extra buffer space is aligned on a process natural boundary.
106 //
107 #define COMPUTE_OBJECT_SIZE(_rawObjectSize, _extraSize) \
108    (COMPUTE_RAW_OBJECT_SIZE(_rawObjectSize) + (USHORT) WDF_ALIGN_SIZE_UP(_extraSize, MEMORY_ALLOCATION_ALIGNMENT))
109 
110 //
111 // Gets size of the context associated with the specified attributes structure.
112 //
113 size_t
114 FxGetContextSize(
115     __in_opt    PWDF_OBJECT_ATTRIBUTES Attributes
116     );
117 
118 //
119 // Computes the total size of an object taking into account its fixed size,
120 // any additional size after the fixed, and an object header, so the memory looks
121 // like:
122 //
123 // Object
124 // additional optional memory
125 // WDF_HANDLE_HEADER
126 //
127 _Must_inspect_result_
128 NTSTATUS
129 FxCalculateObjectTotalSize2(
130     __in        PFX_DRIVER_GLOBALS FxDriverGlobals,
131     __in        USHORT RawObjectSize,
132     __in        USHORT ExtraSize,
133     __in        size_t ContextSize,
134     __out       size_t* Total
135     );
136 
137 _Must_inspect_result_
138 NTSTATUS
139 FxCalculateObjectTotalSize(
140     __in        PFX_DRIVER_GLOBALS FxDriverGlobals,
141     __in        USHORT RawObjectSize,
142     __in        USHORT ExtraSize,
143     __in_opt    PWDF_OBJECT_ATTRIBUTES Attributes,
144     __out       size_t* Total
145     );
146 
147 PVOID
148 FxObjectHandleAlloc(
149     __in        PFX_DRIVER_GLOBALS FxDriverGlobals,
150     __in        POOL_TYPE PoolType,
151     __in        size_t Size,
152     __in        ULONG Tag,
153     __in_opt    PWDF_OBJECT_ATTRIBUTES Attributes,
154     __in        USHORT ExtraSize,
155     __in        FxObjectType ObjectType
156     );
157 
158 VOID
159 FxContextHeaderInit(
160     __in        FxContextHeader* Header,
161     __in        FxObject* Object,
162     __in_opt    PWDF_OBJECT_ATTRIBUTES Attributes
163     );
164 
165 PVOID
166 FxObjectAndHandleHeaderInit(
167     __in        PFX_DRIVER_GLOBALS FxDriverGlobals,
168     __in        PVOID AllocationStart,
169     __in        USHORT ObjectSize,
170     __in_opt    PWDF_OBJECT_ATTRIBUTES Attributes,
171     __in        FxObjectType ObjectType
172     );
173 
174 VOID
175 __inline
FxObjectHandleCreate(__in FxObject * Object,__out PWDFOBJECT Handle)176 FxObjectHandleCreate(
177     __in  FxObject* Object,
178     __out PWDFOBJECT Handle
179     )
180 {
181 #if FX_SUPER_DBG
182     if (Object->GetDriverGlobals()->FxVerifierHandle) {
183 
184 
185 
186 
187 
188 
189         ASSERT(Object->GetObjectSize() > 0);
190         ASSERT(Object == Object->GetContextHeader()->Object);
191     }
192 #endif
193 
194     ASSERT((((ULONG_PTR) Object) & FxHandleFlagMask) == 0x0);
195     *Handle = Object->GetObjectHandle();
196 }
197 
198 /*++
199 
200 Routine Description:
201 
202     Retrieves the object pointer from the handle if valid.
203 
204     This does not change an objects reference count.
205 
206 Arguments:
207 
208     handle - The object handle created by WdfObjectCreateHandle
209 
210     type - Type of the object from FxTypes.h
211 
212     ppObj - Pointer to location to store the returned object.
213 
214 Returns:
215 
216     NTSTATUS
217 
218 --*/
219 
220 VOID
221 FxObjectHandleGetPtrQI(
222     __in FxObject* Object,
223     __out PVOID* PPObject,
224     __in WDFOBJECT Handle,
225     __in WDFTYPE Type,
226     __in WDFOBJECT_OFFSET Offset
227     );
228 
229 _Must_inspect_result_
230 NTSTATUS
231 FxObjectAllocateContext(
232     __in        FxObject*               Object,
233     __in        PWDF_OBJECT_ATTRIBUTES  Attributes,
234     __in        BOOLEAN                 AllowCallbacksOnly,
235     __deref_opt_out PVOID*              Context
236     );
237 
238 __inline
239 BOOLEAN
FxObjectCheckType(__in FxObject * Object,__in WDFTYPE Type)240 FxObjectCheckType(
241     __in FxObject* Object,
242     __in WDFTYPE  Type
243     )
244 /*++
245 
246 Routine Description:
247     Checks if the FxObject is of a the Type.
248 
249 Arguments:
250     FxObject - the object being checked
251     Type - The type value to be checked
252 
253 Returns:
254     TRUE if the Object is of the type 'Type'
255     FALSE otherwise
256   --*/
257 {
258     NTSTATUS status;
259     PVOID tmpObject;
260     FxQueryInterfaceParams params = {&tmpObject, Type, 0};
261 
262     //
263     // Do a quick non virtual call for the type and only do the slow QI if
264     // the first types do not match
265     //
266 
267     if (Object->GetType() == Type) {
268         return TRUE;
269     }
270 
271     status = Object->QueryInterface(&params);
272 
273     if (!NT_SUCCESS(status)) {
274         return FALSE;
275     }
276 
277     return TRUE;
278 
279 }
280 
281 __inline
282 VOID
FxObjectHandleGetPtr(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in WDFOBJECT Handle,__in WDFTYPE Type,__out PVOID * PPObject)283 FxObjectHandleGetPtr(
284     __in PFX_DRIVER_GLOBALS FxDriverGlobals,
285     __in WDFOBJECT Handle,
286     __in WDFTYPE Type,
287     __out PVOID* PPObject
288     )
289 /*++
290 
291 Routine Description:
292     Converts an externally facing WDF handle into its internal object.
293 
294 Arguments:
295     FxDriverGlobals - caller's globals
296     Handle - handle to convert into an object
297     Type - required type of the underlying object
298     PPObject - pointer to receive the underlying object
299 
300   --*/
301 {
302     WDFOBJECT_OFFSET offset;
303     FxObject* pObject;
304 
305     if (Handle == NULL) {
306 
307 
308 
309 
310 
311         FxVerifierBugCheck(FxDriverGlobals,
312                            WDF_INVALID_HANDLE,
313                            (ULONG_PTR) Handle,
314                            Type);
315 
316         /* NOTREACHED */
317         return;
318     }
319 
320     offset = 0;
321     pObject = FxObject::_GetObjectFromHandle(Handle, &offset);
322 
323     //
324     // The only DDI you can call on an object which has a ref count of zero is
325     // WdfObjectGetTypedContextWorker().
326     //
327     ASSERT(pObject->GetRefCnt() > 0);
328 
329     //
330     // Do a quick non virtual call for the type and only do the slow QI if
331     // the first types do not match
332     //
333     if (pObject->GetType() == Type) {
334         *PPObject = pObject;
335         ASSERT(offset == 0x0);
336         return;
337     }
338     else {
339         FxObjectHandleGetPtrQI(pObject, PPObject, Handle, Type, offset);
340     }
341 }
342 
343 __inline
344 VOID
FxObjectHandleGetPtrOffset(__in PFX_DRIVER_GLOBALS FxDriverGlobals,__in WDFOBJECT Handle,__in WDFTYPE Type,__out PVOID * PPObject,__out PWDFOBJECT_OFFSET Offset)345 FxObjectHandleGetPtrOffset(
346     __in PFX_DRIVER_GLOBALS FxDriverGlobals,
347     __in WDFOBJECT Handle,
348     __in WDFTYPE Type,
349     __out PVOID* PPObject,
350     __out PWDFOBJECT_OFFSET Offset
351     )
352 /*++
353 
354 Routine Description:
355     This function  probably should be removed and the optional Offset paramter
356     moved into the signature for  FxObjectHandleGetPtr(). The distinction
357     between these 2 functions was important when both of them were *not*
358     FORCEINLINE functions (since there was an additional parameter to push onto
359     the stack).  Now that they are both __inlined, there is no longer a
360     parameter to push, eliminating this optimization.
361 
362 Arguments:
363     FxDriverGlobals - caller's globals
364     Handle - handle to convert into an object
365     Type - required type of the underlying object
366     PPObject - pointer to receive the underlying object
367     Offset - offset into the object which the handle resided.  Nearly all objects
368         will have a zero offset
369 
370   --*/
371 {
372     FxObject* pObject;
373 
374     if (Handle == NULL) {
375 
376 
377 
378 
379 
380         FxVerifierBugCheck(FxDriverGlobals,
381                            WDF_INVALID_HANDLE,
382                            (ULONG_PTR) Handle,
383                            Type);
384 
385         /* NOTREACHED */
386         return;
387     }
388 
389     *Offset = 0;
390     pObject = FxObject::_GetObjectFromHandle(Handle, Offset);
391 
392     //
393     // The only DDI you can call on an object which has a ref count of zero is
394     // WdfObjectGetTypedContextWorker().
395     //
396     ASSERT(pObject->GetRefCnt() > 0);
397 
398     //
399     // Do a quick non virtual call for the type and only do the slow QI if
400     // the first types do not match
401     //
402     if (pObject->GetType() == Type) {
403         *PPObject = pObject;
404         ASSERT(*Offset == 0x0);
405         return;
406     }
407     else {
408         FxObjectHandleGetPtrQI(pObject, PPObject, Handle, Type, *Offset);
409     }
410 }
411 
412 VOID
413 __inline
FxObjectHandleGetPtrAndGlobals(__in PFX_DRIVER_GLOBALS CallersGlobals,__in WDFOBJECT Handle,__in WDFTYPE Type,__out PVOID * PPObject,__out PFX_DRIVER_GLOBALS * ObjectGlobals)414 FxObjectHandleGetPtrAndGlobals(
415     __in  PFX_DRIVER_GLOBALS CallersGlobals,
416     __in  WDFOBJECT Handle,
417     __in  WDFTYPE   Type,
418     __out PVOID*    PPObject,
419     __out PFX_DRIVER_GLOBALS* ObjectGlobals
420     )
421 /*++
422 
423 Routine Description:
424     Converts an externally facing WDF handle into its internal object.
425 
426 Arguments:
427     FxDriverGlobals - caller's globals
428     Handle - handle to convert into an object
429     Type - required type of the underlying object
430     PPObject - pointer to receive the underlying object
431     ObjectGlobals - pointer to receive the underlying object's globals.
432 
433   --*/
434 {
435     //
436     // All FX_TYPEs except for IFX_TYPE_MEMORY derive from FxObject, so our cast
437     // below will work with all types but IFX_TYPE_MEMORY (in which case the caller
438     // should call FxObjectHandleGetPtr and then get the globals on their own
439     // from the IFxMemory interface).
440     //
441     ASSERT(Type != IFX_TYPE_MEMORY);
442 
443     FxObjectHandleGetPtr(CallersGlobals,
444                          Handle,
445                          Type,
446                          PPObject);
447 
448     *ObjectGlobals = ((FxObject*) (*PPObject))->GetDriverGlobals();
449 }
450 
451 VOID
452 __inline
FxObjectHandleGetGlobals(__in PFX_DRIVER_GLOBALS CallersGlobals,__in WDFOBJECT Handle,__out PFX_DRIVER_GLOBALS * ObjectGlobals)453 FxObjectHandleGetGlobals(
454     __in  PFX_DRIVER_GLOBALS CallersGlobals,
455     __in  WDFOBJECT Handle,
456     __out PFX_DRIVER_GLOBALS* ObjectGlobals
457     )
458 /*++
459 
460 Routine Description:
461     Converts an externally facing WDF handle into its internal object and
462     returns its globals.
463 
464 Arguments:
465     FxDriverGlobals - caller's globals
466     Handle - handle to convert into an object
467     ObjectGlobals - pointer to receive the underlying object's globals.
468 
469   --*/
470 {
471     PVOID pObject;
472 
473     FxObjectHandleGetPtrAndGlobals(CallersGlobals,
474                                    Handle,
475                                    FX_TYPE_OBJECT,
476                                    &pObject,
477                                    ObjectGlobals);
478 
479     UNREFERENCED_PARAMETER(pObject);
480 }
481 
482 #endif // _WDFPHANDLE_H_
483