Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704/*++
Copyright (c) Microsoft Corporation
Module Name:
HandleApi.cpp
Abstract:
This module implements the driver frameworks handle functions.
Author:
Environment:
Both kernel and user mode
Revision History:
--*/
#include "fxobjectpch.hpp"
extern "C" {
#if defined(EVENT_TRACING)#include "HandleAPI.tmh"#endif
}
size_tFxGetContextSize( __in_opt PWDF_OBJECT_ATTRIBUTES Attributes )/*++
Routine Description: Get a context size from an object's attributes settings.
Arguments: Attributes - attributes which will describe the size requirements for the associated context.
Return Value: Size requirements for the associated context.
--*/{ size_t contextSize = 0;
if (Attributes != NULL) { if (Attributes->ContextTypeInfo != NULL) { if (Attributes->ContextSizeOverride != 0) { contextSize = Attributes->ContextSizeOverride; } else { contextSize = Attributes->ContextTypeInfo->ContextSize; } } }
return contextSize;}
_Must_inspect_result_NTSTATUSFxCalculateObjectTotalSize2( __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in USHORT RawObjectSize, __in USHORT ExtraSize, __in size_t ContextSize, __out size_t* Total )/*++
Routine Description: Calculates the size of an allocation for an FxObject that will contain the object, its initial context and any addtional headers.
Arguments: FxDriverGlobals - driver's globals RawObjectSize - the size of the FxObject derived object ExtraSize - additional size required by the derived object ContextSize - Size requirements for the associated context (see FxGetContextSize() above). Total - pointer which will receive the final size requirement
Return Value: NT_SUCCESS on success, !NT_SUCCESS on failure
--*/{ NTSTATUS status;
*Total = 0;
status = RtlSizeTAdd( WDF_ALIGN_SIZE_UP(COMPUTE_OBJECT_SIZE(RawObjectSize, ExtraSize), MEMORY_ALLOCATION_ALIGNMENT), FX_CONTEXT_HEADER_SIZE, Total );
if (NT_SUCCESS(status)) { if (ContextSize != 0) { size_t alignUp;
alignUp = ALIGN_UP(ContextSize, PVOID);
// // overflow after aligning up to a pointer boundary; // if (alignUp < ContextSize) { return STATUS_INTEGER_OVERFLOW; }
status = RtlSizeTAdd(*Total, alignUp, Total); } }
if (NT_SUCCESS(status) && FxDriverGlobals->IsObjectDebugOn()) { // // Attempt to add in the debug extension // status = RtlSizeTAdd(*Total, FxObjectDebugExtensionSize, Total); }
if (!NT_SUCCESS(status)) { DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGOBJECT, "Size overflow, object size 0x%x, extra object size 0x%x, " "context size 0x%I64x, %!STATUS!", RawObjectSize, ExtraSize, ContextSize, status); }
return status;}
_Must_inspect_result_NTSTATUSFxCalculateObjectTotalSize( __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in USHORT RawObjectSize, __in USHORT ExtraSize, __in_opt PWDF_OBJECT_ATTRIBUTES Attributes, __out size_t* Total ){ return FxCalculateObjectTotalSize2(FxDriverGlobals, RawObjectSize, ExtraSize, FxGetContextSize(Attributes), Total);}
PVOIDFxObjectHandleAlloc( __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in POOL_TYPE PoolType, __in size_t Size, __in ULONG Tag, __in_opt PWDF_OBJECT_ATTRIBUTES Attributes, __in USHORT ExtraSize, __in FxObjectType ObjectType )/*++
Routine Description: Allocates an FxObject derived object, it's associated context, and any framework required headers and footers.
Arguments: FxDriverGlobals - caller's globals PoolType - type of pool to be used in allocating the object's memory Size - size of the object (as passed to operator new() by the compiler) Tag - tag to use when allocating the object's memory Attributes - attributes which describe the context to be associated with the object ExtraSize - any addtional storage required by the object itself ObjectType - the type (internal or external) of object being allocated. An internal object is a worker object which will never have an associated type or be Commit()'ed into an external object handle that the client driver will see.
Return Value: A valid pointer on success, NULL otherwise
--*/{ PVOID blob; size_t totalSize; NTSTATUS status;
if (Tag == 0) { Tag = FxDriverGlobals->Tag; ASSERT(Tag != 0); }
if (ObjectType == FxObjectTypeInternal) { // // An internal object might need the debug extension size added to it, // but that's it. No extra size, no FxContextHeader. // if (FxDriverGlobals->IsObjectDebugOn()) { status = RtlSizeTAdd(Size, FxObjectDebugExtensionSize, &totalSize); } else { totalSize = Size; status = STATUS_SUCCESS; } } else { status = FxCalculateObjectTotalSize(FxDriverGlobals, (USHORT) Size, ExtraSize, Attributes, &totalSize); }
if (!NT_SUCCESS(status)) { return NULL; }
blob = FxPoolAllocateWithTag(FxDriverGlobals, PoolType, totalSize, Tag);
if (blob != NULL) { blob = FxObjectAndHandleHeaderInit( FxDriverGlobals, blob, COMPUTE_OBJECT_SIZE((USHORT) Size, ExtraSize), Attributes, ObjectType ); }
return blob;}
VOIDFxContextHeaderInit( __in FxContextHeader* Header, __in FxObject* Object, __in_opt PWDF_OBJECT_ATTRIBUTES Attributes )/*++
Routine Description: Initializes a context header which describes a typed context.
Arguments: Header - the header to initialize Object - the object on which the context is being associated with Attributes - description of the typed context
--*/{ RtlZeroMemory(Header, FX_CONTEXT_HEADER_SIZE);
Header->Object = Object;
if (Attributes != NULL) { if (Attributes->ContextTypeInfo != NULL) { size_t contextSize;
if (Attributes->ContextSizeOverride != 0) { contextSize = Attributes->ContextSizeOverride;
} else { contextSize = Attributes->ContextTypeInfo->ContextSize; }
// // Zero initialize the entire context // RtlZeroMemory(&Header->Context[0], ALIGN_UP(contextSize, PVOID)); }
Header->ContextTypeInfo = Attributes->ContextTypeInfo; }}
PVOIDFxObjectAndHandleHeaderInit( __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PVOID AllocationStart, __in USHORT ObjectSize, __in_opt PWDF_OBJECT_ATTRIBUTES Attributes, __in FxObjectType ObjectType )/*++
Routine Description: Initialize the object and its associated context.
Arguments: FxDriverGlobals - caller's globals AllocationStart - start of the memory block allocated to represent the object. This will not be the same as the pointer which represents the address of the object itself in memory ObjectSize - size of the object Attributes - description of its context ObjectType - type (internal or external) of object being initialized
Return Value: The address of the object withing AllocationStart
--*/
{ FxObject* pObject;
if (FxDriverGlobals->IsObjectDebugOn()) { FxObjectDebugExtension* pExtension;
pExtension = (FxObjectDebugExtension*) AllocationStart;
RtlZeroMemory(pExtension, FxObjectDebugExtensionSize); pExtension->Signature = FxObjectDebugExtensionSignature;
pObject = (FxObject*) &pExtension->AllocationStart[0]; } else { pObject = (FxObject*) AllocationStart; }
if (ObjectType == FxObjectTypeExternal) { FxContextHeaderInit( (FxContextHeader*) WDF_PTR_ADD_OFFSET(pObject, ObjectSize), pObject, Attributes ); }
return pObject;}
VOIDFxObjectHandleGetPtrQI( __in FxObject* Object, __out PVOID* PPObject, __in WDFOBJECT Handle, __in WDFTYPE Type, __in WDFOBJECT_OFFSET Offset )/*++
Routine Description: Worker function for FxObjectHandleGetPtrXxx which will call FxObject::QueryInterface when the Type does not match the object's built in Type.
Arguments: Object - object to query PPObject - pointer which will recieve the queried for object Handle - handle which the caller passed to the framework Type - required object type Offset - offset of the handle within the object. Nearly all handles will have a zero object.
--*/{ FxQueryInterfaceParams params = { PPObject, Type, Offset }; NTSTATUS status;
*PPObject = NULL;
status = Object->QueryInterface(¶ms);
if (!NT_SUCCESS(status)) { DoTraceLevelMessage( Object->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE, "Object Type Mismatch, Handle 0x%p, Type 0x%x, " "Obj 0x%p, SB 0x%x", Handle, Type, Object, Object->GetType());
FxVerifierBugCheck(Object->GetDriverGlobals(), WDF_INVALID_HANDLE, (ULONG_PTR) Handle, Type);
/* NOTREACHED */ return; }}
_Must_inspect_result_NTSTATUSFxObjectAllocateContext( __in FxObject* Object, __in PWDF_OBJECT_ATTRIBUTES Attributes, __in BOOLEAN AllowCallbacksOnly, __deref_opt_out PVOID* Context )/*++
Routine Description: Allocates an additional context on the object if it is in the correct state.
Arguments: Object - object on which to add a context Attributes - attributes which describe the type and size of the new context AllowEmptyContext -TRUE to allow logic to allocate the context's header only. Context - optional pointer which will recieve the new context
Return Value: STATUS_SUCCESS upon success, STATUS_OBJECT_NAME_EXISTS if the context type is already attached to the handle, and !NT_SUCCESS on failure
--*/{ PFX_DRIVER_GLOBALS fxDriverGlobals; NTSTATUS status; FxContextHeader * header; size_t size; BOOLEAN relRef; ULONG flags;
fxDriverGlobals = Object->GetDriverGlobals(); header = NULL; relRef = FALSE;
// // Init validation flags. // flags = FX_VALIDATE_OPTION_ATTRIBUTES_REQUIRED; if (fxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,11)) { flags |= FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED; }
// // Basic validations. // status = FxValidateObjectAttributes(fxDriverGlobals, Attributes, flags); if (!NT_SUCCESS(status)) { goto Done; }
// // Check for context type! // if (Attributes->ContextTypeInfo == NULL && AllowCallbacksOnly == FALSE) { status = STATUS_OBJECT_NAME_INVALID; DoTraceLevelMessage( fxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGHANDLE, "Attributes %p ContextTypeInfo is NULL, %!STATUS!", Attributes, status); goto Done; }
Object->ADDREF(&status); relRef = TRUE;
// // By passing 0's for raw object size and extra size, we can compute the // size of only the header and its contents. // status = FxCalculateObjectTotalSize(fxDriverGlobals, 0, 0, Attributes, &size); if (!NT_SUCCESS(status)) { goto Done; }
header = (FxContextHeader*) FxPoolAllocate(fxDriverGlobals, NonPagedPool, size);
if (header == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto Done; }
FxContextHeaderInit(header, Object, Attributes);
status = Object->AddContext(header, Context, Attributes);
// // STATUS_OBJECT_NAME_EXISTS will not fail NT_SUCCESS, so check // explicitly for STATUS_SUCCESS. // if (status != STATUS_SUCCESS) { FxPoolFree(header); }
Done:
if (relRef) { Object->RELEASE(&status); }
return status;}
// extern "C" all APIsextern "C" {
_Must_inspect_result___drv_maxIRQL(DISPATCH_LEVEL)WDFAPINTSTATUSNTAPIWDFEXPORT(WdfObjectAllocateContext)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFOBJECT Handle, __in PWDF_OBJECT_ATTRIBUTES Attributes, __deref_opt_out PVOID* Context )/*++
Routine Description: Allocates an additional context on the handle if the object is in the correct state
Arguments: Handle - handle on which to add a context Attributes - attributes which describe the type and size of the new context Context - optional pointer which will recieve the new context
Return Value: STATUS_SUCCESS upon success, STATUS_OBJECT_NAME_EXISTS if the context type is already attached to the handle, and !NT_SUCCESS on failure
--*/{ DDI_ENTRY_IMPERSONATION_OK();
NTSTATUS status; FxObject* object; WDFOBJECT_OFFSET offset;
FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), Handle);
// // No need to call FxObjectHandleGetPtr( , , FX_TYPE_OBJECT) because // we assume that the object handle will point back to an FxObject. (The // call to FxObjectHandleGetPtr will just make needless virtual call into // FxObject anyways). // offset = 0; object = FxObject::_GetObjectFromHandle(Handle, &offset);
if (offset != 0) {
status = STATUS_OBJECT_PATH_INVALID; DoTraceLevelMessage( object->GetDriverGlobals(), TRACE_LEVEL_WARNING, TRACINGHANDLE, "WDFHANDLE %p cannot have contexts added to it, %!STATUS!", Handle, status); goto Done; }
// // Internal helper function does the rest of the work. // status = FxObjectAllocateContext(object, Attributes, FALSE, Context);
Done: return status;}
__drv_maxIRQL(DISPATCH_LEVEL+1)WDFAPIPVOIDFASTCALLWDFEXPORT(WdfObjectGetTypedContextWorker)( __in PWDF_DRIVER_GLOBALS DriverGlobals, __in WDFOBJECT Handle, __in PCWDF_OBJECT_CONTEXT_TYPE_INFO TypeInfo )/*++
Routine Description: Retrieves the requested type from a handle
Arguments: Handle - the handle to retrieve the context from TypeInfo - global constant pointer which describes the type. Since the pointer value is unique in all of kernel space, we will perform a pointer compare instead of a deep structure compare
Return Value: A valid context pointere or NULL. NULL is not a failure, querying for a type not associated with the handle is a legitimate operation.
--*/{ DDI_ENTRY_IMPERSONATION_OK();
FxContextHeader* pHeader; FxObject* pObject; PFX_DRIVER_GLOBALS pFxDriverGlobals; WDFOBJECT_OFFSET offset;
FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), Handle);
// // Do not call FxObjectHandleGetPtr( , , FX_TYPE_OBJECT) because this is a // hot spot / workhorse function that should be as efficient as possible. // // A call to FxObjectHandleGetPtr would : // 1) invoke a virtual call to QueryInterface // // 2) ASSERT that the ref count of the object is > zero. Since this is one // of the few functions that can be called in EvtObjectDestroy where the // ref count is zero, that is not a good side affect. // offset = 0; pObject = FxObject::_GetObjectFromHandle(Handle, &offset);
// // Use the object's globals, not the caller's // pFxDriverGlobals = pObject->GetDriverGlobals();
FxPointerNotNull(pFxDriverGlobals, TypeInfo);
pHeader = pObject->GetContextHeader();
for ( ; pHeader != NULL; pHeader = pHeader->NextHeader) { if (pHeader->ContextTypeInfo == TypeInfo) { return &pHeader->Context[0]; } }
PCHAR pGivenName;
if (TypeInfo->ContextName != NULL) { pGivenName = TypeInfo->ContextName; } else { pGivenName = "<no typename given>"; }
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGHANDLE, "Attempting to get context type %s from WDFOBJECT 0x%p", pGivenName, Handle);
return NULL;}
__drv_maxIRQL(DISPATCH_LEVEL+1)WDFAPIWDFOBJECTFASTCALLWDFEXPORT(WdfObjectContextGetObject)( __in PWDF_DRIVER_GLOBALS, __in PVOID ContextPointer )/*++
Routine Description: Reverse of WdfObjectGetTypedContextWorker. Function will return the handle associated with the provided context pointer.
Arguments: ContextPointer - context pointer from which to retrieve the owning handle
Return Value: A valid WDF handle
--*/{ DDI_ENTRY_IMPERSONATION_OK();
FxContextHeader* pHeader; FxObject* pObject;
// // The context could be one of the chained contexts on the object and not // the first one, so it is easiest to go back to the object and build the // handle value from the FxObject*. // #pragma prefast(push);
#pragma prefast(disable:__WARNING_BUFFER_UNDERFLOW, "No way to express that passed in ptr is at an offset");
pHeader = CONTAINING_RECORD(ContextPointer, FxContextHeader, Context); pObject = pHeader->Object;
#pragma prefast(pop);
return (WDFOBJECT) pObject->GetObjectHandle();}
} // extern "C"