mirror of
https://github.com/reactos/reactos.git
synced 2025-08-05 18:23:07 +00:00
[WDF] Add Windows Driver Framework files
Takern from Microsoft GitHub repo:
d9c6040fe9
Licensed under MIT
This commit is contained in:
parent
545df81502
commit
8a978a179f
475 changed files with 285099 additions and 0 deletions
130
sdk/lib/drivers/wdf/shared/object/dbgtrace.cpp
Normal file
130
sdk/lib/drivers/wdf/shared/object/dbgtrace.cpp
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
ModuleName:
|
||||
|
||||
DbgTrace.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Temporary file to be used until ETW can be used
|
||||
for UM
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxobjectpch.hpp"
|
||||
|
||||
#if FX_CORE_MODE==FX_CORE_USER_MODE
|
||||
#include "strsafe.h"
|
||||
#endif
|
||||
|
||||
#if !defined(EVENT_TRACING)
|
||||
|
||||
VOID
|
||||
__cdecl
|
||||
DoTraceLevelMessage(
|
||||
__in PVOID FxDriverGlobals,
|
||||
__in ULONG DebugPrintLevel,
|
||||
__in ULONG DebugPrintFlag,
|
||||
__drv_formatString(FormatMessage)
|
||||
__in PCSTR DebugMessage,
|
||||
...
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Print the trace message to debugger.
|
||||
|
||||
Arguments:
|
||||
|
||||
TraceEventsLevel - print level between 0 and 3, with 3 the most verbose
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
{
|
||||
#if DBG
|
||||
UNREFERENCED_PARAMETER(FxDriverGlobals);
|
||||
|
||||
#define TEMP_BUFFER_SIZE 1024
|
||||
va_list list;
|
||||
CHAR debugMessageBuffer[TEMP_BUFFER_SIZE];
|
||||
NTSTATUS status;
|
||||
|
||||
va_start(list, DebugMessage);
|
||||
|
||||
if (DebugMessage) {
|
||||
|
||||
//
|
||||
// Using new safe string functions instead of _vsnprintf.
|
||||
// This function takes care of NULL terminating if the message
|
||||
// is longer than the buffer.
|
||||
//
|
||||
#if FX_CORE_MODE==FX_CORE_KERNEL_MODE
|
||||
status = RtlStringCbVPrintfA( debugMessageBuffer,
|
||||
sizeof(debugMessageBuffer),
|
||||
DebugMessage,
|
||||
list );
|
||||
#else
|
||||
HRESULT hr;
|
||||
hr = StringCbVPrintfA( debugMessageBuffer,
|
||||
sizeof(debugMessageBuffer),
|
||||
DebugMessage,
|
||||
list );
|
||||
|
||||
|
||||
if (HRESULT_FACILITY(hr) == FACILITY_WIN32)
|
||||
{
|
||||
status = WinErrorToNtStatus(HRESULT_CODE(hr));
|
||||
}
|
||||
else
|
||||
{
|
||||
status = SUCCEEDED(hr) ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
#endif
|
||||
if(!NT_SUCCESS(status)) {
|
||||
|
||||
#if FX_CORE_MODE==FX_CORE_KERNEL_MODE
|
||||
DbgPrint ("WDFTrace: RtlStringCbVPrintfA failed 0x%x\n", status);
|
||||
#else
|
||||
OutputDebugString("WDFTrace: Unable to expand: ");
|
||||
OutputDebugString(DebugMessage);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (DebugPrintLevel <= TRACE_LEVEL_ERROR ||
|
||||
(DebugPrintLevel <= DebugLevel &&
|
||||
((DebugPrintFlag & DebugFlag) == DebugPrintFlag))) {
|
||||
#if FX_CORE_MODE==FX_CORE_KERNEL_MODE
|
||||
DbgPrint("WDFTrace: %s", debugMessageBuffer);
|
||||
#else
|
||||
OutputDebugString("WDFTrace: ");
|
||||
OutputDebugString(DebugMessage);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
va_end(list);
|
||||
|
||||
return;
|
||||
#else
|
||||
UNREFERENCED_PARAMETER(FxDriverGlobals);
|
||||
UNREFERENCED_PARAMETER(DebugPrintLevel);
|
||||
UNREFERENCED_PARAMETER(DebugPrintFlag);
|
||||
UNREFERENCED_PARAMETER(DebugMessage);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
1137
sdk/lib/drivers/wdf/shared/object/fxobject.cpp
Normal file
1137
sdk/lib/drivers/wdf/shared/object/fxobject.cpp
Normal file
File diff suppressed because it is too large
Load diff
383
sdk/lib/drivers/wdf/shared/object/fxobjectapi.cpp
Normal file
383
sdk/lib/drivers/wdf/shared/object/fxobjectapi.cpp
Normal file
|
@ -0,0 +1,383 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxObjectApi.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxobjectpch.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "FxObjectAPI.tmh"
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFAPI
|
||||
VOID
|
||||
WDFEXPORT(WdfObjectReferenceActual)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFOBJECT Object,
|
||||
__in_opt
|
||||
PVOID Tag,
|
||||
__in
|
||||
LONG Line,
|
||||
__in
|
||||
PSTR File
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Adds an explicit reference that was taken on an object.
|
||||
|
||||
Arguments:
|
||||
Object - the object to reference
|
||||
Tag - The tag used to track this reference. If not matched on dereference,
|
||||
a breakpoint is hit. Tags are only tracked when enabled via the
|
||||
registry or WDF verifier.
|
||||
Line - the caller's line number making the call
|
||||
File - the caller's file name making the call
|
||||
|
||||
Return Value:
|
||||
None. We do not return the current reference count.
|
||||
|
||||
--*/
|
||||
{
|
||||
DDI_ENTRY();
|
||||
|
||||
FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), Object);
|
||||
|
||||
FxObject::_ReferenceActual(
|
||||
Object,
|
||||
Tag,
|
||||
Line,
|
||||
File
|
||||
);
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFAPI
|
||||
VOID
|
||||
WDFEXPORT(WdfObjectDereferenceActual)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFOBJECT Object,
|
||||
__in_opt
|
||||
PVOID Tag,
|
||||
__in
|
||||
LONG Line,
|
||||
__in
|
||||
PSTR File
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Removes an explicit reference that was taken on an object.
|
||||
|
||||
Arguments:
|
||||
Object - the object to dereference
|
||||
Tag - The tag used when referencing the Object, if not matched, a breakpoint
|
||||
is hit. Tags are only tracked when enabled via the registry or
|
||||
WDF verifier.
|
||||
Line - the caller's line number making the call
|
||||
File - the caller's file name making the call
|
||||
|
||||
Return Value:
|
||||
None. We do not return the current reference count.
|
||||
|
||||
--*/
|
||||
{
|
||||
DDI_ENTRY();
|
||||
|
||||
FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), Object);
|
||||
|
||||
FxObject::_DereferenceActual(
|
||||
Object,
|
||||
Tag,
|
||||
Line,
|
||||
File
|
||||
);
|
||||
}
|
||||
|
||||
FxCallbackLock*
|
||||
FxGetCallbackLock(
|
||||
FxObject* Object
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This returns the proper FxCallbackLock pointer
|
||||
for the object.
|
||||
|
||||
It returns NULL if an FxCallbackLock is not valid
|
||||
for the object.
|
||||
|
||||
Arguments:
|
||||
|
||||
Object - Pointer to object to retrieve the callback lock pointer for
|
||||
|
||||
Returns:
|
||||
|
||||
FxCallbackLock*
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
NTSTATUS status;
|
||||
IFxHasCallbacks* ihcb;
|
||||
FxQueryInterfaceParams params = { (PVOID*) &ihcb, FX_TYPE_IHASCALLBACKS, 0 };
|
||||
|
||||
ihcb = NULL;
|
||||
|
||||
//
|
||||
// Query the object for the IFxHasCallbacks interface. Objects that
|
||||
// have callback locks must support this interface.
|
||||
//
|
||||
status = Object->QueryInterface(¶ms);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ihcb->GetCallbackLockPtr(NULL);
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFAPI
|
||||
VOID
|
||||
WDFEXPORT(WdfObjectAcquireLock)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
_Requires_lock_not_held_(_Curr_)
|
||||
_Acquires_lock_(_Curr_)
|
||||
WDFOBJECT Object
|
||||
)
|
||||
{
|
||||
DDI_ENTRY();
|
||||
|
||||
FxObject* pObject;
|
||||
FxCallbackLock* pLock;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
KIRQL irql;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
Object,
|
||||
FX_TYPE_OBJECT,
|
||||
(PVOID*)&pObject,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
//
|
||||
// If Lock Verifier on, validate whether its correct to
|
||||
// make this call
|
||||
//
|
||||
if (pFxDriverGlobals->FxVerifierLock) {
|
||||
//
|
||||
// Check IRQL Level, etc.
|
||||
//
|
||||
}
|
||||
|
||||
//
|
||||
// Get the CallbackLock for the object
|
||||
//
|
||||
pLock = FxGetCallbackLock(pObject);
|
||||
|
||||
if (pLock == NULL) {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Invalid to call on WDFOBJECT 0x%p", Object);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
FxVerifierBugCheck(pFxDriverGlobals,
|
||||
WDF_INVALID_LOCK_OPERATION,
|
||||
(ULONG_PTR)Object,
|
||||
(ULONG_PTR)NULL
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
pLock->Lock(&irql);
|
||||
pLock->m_PreviousIrql = irql;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFAPI
|
||||
VOID
|
||||
WDFEXPORT(WdfObjectReleaseLock)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
_Requires_lock_held_(_Curr_)
|
||||
_Releases_lock_(_Curr_)
|
||||
WDFOBJECT Object
|
||||
)
|
||||
{
|
||||
DDI_ENTRY();
|
||||
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxObject* pObject;
|
||||
FxCallbackLock* pLock;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
Object,
|
||||
FX_TYPE_OBJECT,
|
||||
(PVOID*)&pObject,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
//
|
||||
// If Lock Verifier on, validate whether its correct to
|
||||
// make this call
|
||||
//
|
||||
if (pFxDriverGlobals->FxVerifierLock) {
|
||||
//
|
||||
// Check IRQL Level, etc.
|
||||
//
|
||||
}
|
||||
|
||||
//
|
||||
// Get the CallbackLock for the object
|
||||
//
|
||||
pLock = FxGetCallbackLock(pObject);
|
||||
if (pLock == NULL) {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Invalid to call on WDFOBJECT 0x%p",Object);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
FxVerifierBugCheck(pFxDriverGlobals,
|
||||
WDF_INVALID_LOCK_OPERATION,
|
||||
(ULONG_PTR)Object,
|
||||
(ULONG_PTR)NULL
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
pLock->Unlock(pLock->m_PreviousIrql);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFAPI
|
||||
VOID
|
||||
WDFEXPORT(WdfObjectDelete)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFOBJECT Object
|
||||
)
|
||||
{
|
||||
DDI_ENTRY();
|
||||
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxObject* pObject;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
Object,
|
||||
FX_TYPE_OBJECT,
|
||||
(PVOID*)&pObject,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
//
|
||||
// The object may not allow the Delete DDI
|
||||
//
|
||||
if (pObject->IsNoDeleteDDI()) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Attempt to Delete an Object Which does not allow WdfDeleteObject "
|
||||
"Handle 0x%p, %!STATUS!",
|
||||
Object, STATUS_CANNOT_DELETE);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
}
|
||||
else {
|
||||
pObject->DeleteObject();
|
||||
}
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFAPI
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfObjectQuery)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFOBJECT Object,
|
||||
__in
|
||||
CONST GUID* Guid,
|
||||
__in
|
||||
ULONG QueryBufferLength,
|
||||
__out_bcount(QueryBufferLength)
|
||||
PVOID QueryBuffer
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Query the object handle for specific information
|
||||
|
||||
This allows dynamic extensions to DDI's.
|
||||
|
||||
Currently, it is used to allow test hooks for verification
|
||||
which are not available in a production release.
|
||||
|
||||
Arguments:
|
||||
|
||||
Object - Handle to object for the query
|
||||
|
||||
Guid - GUID to represent the information/DDI to query for
|
||||
|
||||
QueryBufferLength - Length of QueryBuffer to return data in
|
||||
|
||||
QueryBuffer - Pointer to QueryBuffer
|
||||
|
||||
Returns:
|
||||
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
DDI_ENTRY();
|
||||
|
||||
FxObject* p;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
Object,
|
||||
FX_TYPE_OBJECT,
|
||||
(PVOID*)&p);
|
||||
|
||||
return FxObject::_ObjectQuery(p,
|
||||
Guid,
|
||||
QueryBufferLength,
|
||||
QueryBuffer);
|
||||
}
|
||||
|
||||
} // extern "C" for all functions
|
||||
|
||||
|
30
sdk/lib/drivers/wdf/shared/object/fxobjectpch.hpp
Normal file
30
sdk/lib/drivers/wdf/shared/object/fxobjectpch.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
fxobjectpch.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains header definitions and include files needed by all
|
||||
modules in shared\object
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
Both kernel and user mode
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef __FX_CORE_PCH_H__
|
||||
#define __FX_CORE_PCH_H__
|
||||
|
||||
#include "objectpriv.hpp"
|
||||
#include "fxmin.hpp"
|
||||
#include "FxToObjectItf.hpp"
|
||||
|
||||
#endif // __FX_CORE_PCH_H__
|
1217
sdk/lib/drivers/wdf/shared/object/fxobjectstatemachine.cpp
Normal file
1217
sdk/lib/drivers/wdf/shared/object/fxobjectstatemachine.cpp
Normal file
File diff suppressed because it is too large
Load diff
382
sdk/lib/drivers/wdf/shared/object/fxtagtracker.cpp
Normal file
382
sdk/lib/drivers/wdf/shared/object/fxtagtracker.cpp
Normal file
|
@ -0,0 +1,382 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxTagTracker.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
|
||||
Both kernel and user mode
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxobjectpch.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "fxtagtracker.tmh"
|
||||
#endif
|
||||
|
||||
#if (FX_CORE_MODE == FX_CORE_KERNEL_MODE)
|
||||
//
|
||||
// rtlsupportapi.h causes problems in AMD64 and ARM builds.
|
||||
//
|
||||
extern
|
||||
_Success_(return != 0)
|
||||
USHORT
|
||||
RtlCaptureStackBackTrace(
|
||||
_In_ ULONG FramesToSkip,
|
||||
_In_ ULONG FramesToCapture,
|
||||
_Out_writes_to_(FramesToCapture, return) PVOID * BackTrace,
|
||||
_Out_opt_ PULONG BackTraceHash
|
||||
);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
FxTagTracker::~FxTagTracker()
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Destructor for this object. Will verify that the object is being freed
|
||||
without any outstanding tags.
|
||||
|
||||
Arguments:
|
||||
None
|
||||
|
||||
Return Value:
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
KIRQL irql;
|
||||
FxTagTrackingBlock *current, *next;
|
||||
|
||||
if (m_TrackerType == FxTagTrackerTypeHandle) {
|
||||
FxDriverGlobalsDebugExtension* pExtension;
|
||||
|
||||
CheckForAbandondedTags();
|
||||
|
||||
pExtension = GetDriverGlobals()->DebugExtension;
|
||||
|
||||
//
|
||||
// Remove this tracker from the list of allocated trackers
|
||||
//
|
||||
pExtension->AllocatedTagTrackersLock.Acquire(&irql);
|
||||
RemoveEntryList(&m_TrackerEntry);
|
||||
pExtension->AllocatedTagTrackersLock.Release(irql);
|
||||
} else {
|
||||
ASSERT(m_TrackerType == FxTagTrackerTypePower);
|
||||
}
|
||||
|
||||
//
|
||||
// Delete any outstanding tracking blocks.
|
||||
//
|
||||
m_SpinLock.Acquire(&irql);
|
||||
|
||||
current = m_Next;
|
||||
m_Next = NULL;
|
||||
|
||||
while (current != NULL) {
|
||||
next = current->Next;
|
||||
delete current;
|
||||
current = next;
|
||||
}
|
||||
|
||||
m_SpinLock.Release(irql);
|
||||
}
|
||||
|
||||
VOID
|
||||
FxTagTracker::CopyStackFrames(
|
||||
_Inout_ FxTagTrackingStackFrames** StackFrames,
|
||||
_In_ USHORT NumFrames,
|
||||
_In_reads_(NumFrames) PVOID* Frames
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxTagTrackingStackFrames* stackFrames;
|
||||
|
||||
//
|
||||
// FxTagHistory structs are stored in a circular buffer and reused,
|
||||
// so we also reuse the FxTagTrackingStackFrames that each allocates.
|
||||
//
|
||||
stackFrames = *StackFrames;
|
||||
if (stackFrames == NULL) {
|
||||
pFxDriverGlobals = GetDriverGlobals();
|
||||
stackFrames = new(pFxDriverGlobals) FxTagTrackingStackFrames;
|
||||
if (stackFrames == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
*StackFrames = stackFrames;
|
||||
}
|
||||
|
||||
stackFrames->NumFrames = NumFrames;
|
||||
|
||||
for (int i = 0; i < NumFrames; i++) {
|
||||
stackFrames->Frames[i] = (ULONG64)Frames[i];
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FxTagTracker::UpdateTagHistory(
|
||||
__in PVOID Tag,
|
||||
__in LONG Line,
|
||||
__in_opt PSTR File,
|
||||
__in FxTagRefType RefType,
|
||||
__in ULONG RefCount
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Update tag history and either create or free an existing tag tracking block.
|
||||
|
||||
Arguments:
|
||||
|
||||
Tag - Unique tag associated with the reference
|
||||
|
||||
Line - Line where the reference is referenced/released
|
||||
|
||||
File - Buffer containing the file name
|
||||
|
||||
RefType - Enumerated type ( AddRef or Release )
|
||||
|
||||
RefCount - Approximate current reference count (see FxTagHistory.RefCount comment)
|
||||
|
||||
Return Value:
|
||||
|
||||
VOID
|
||||
|
||||
--*/
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxTagHistory* pTagHistory;
|
||||
FxTagTrackingBlock* pBlock;
|
||||
LONG pos;
|
||||
KIRQL irql;
|
||||
USHORT numFrames = 0;
|
||||
PVOID frames[FRAMES_TO_CAPTURE];
|
||||
|
||||
pFxDriverGlobals = GetDriverGlobals();
|
||||
|
||||
pos = InterlockedIncrement(&m_CurRefHistory) - 1;
|
||||
pos %= TAG_HISTORY_DEPTH;
|
||||
|
||||
//
|
||||
// Prefast reports that m_CurRefHistory can be negative which can lead to
|
||||
// underflow. But we know that m_CurRefHistory would never be negative.
|
||||
// Hence we assert for the condition below and assume that it would be true.
|
||||
//
|
||||
FX_ASSERT_AND_ASSUME_FOR_PREFAST(pos >= 0 && pos < TAG_HISTORY_DEPTH);
|
||||
|
||||
pTagHistory = m_TagHistory + pos;
|
||||
|
||||
pTagHistory->RefType = RefType;
|
||||
pTagHistory->RefCount = RefCount;
|
||||
pTagHistory->Line = Line;
|
||||
pTagHistory->Tag = Tag;
|
||||
pTagHistory->File = File;
|
||||
|
||||
if (m_CaptureStack) {
|
||||
numFrames = RtlCaptureStackBackTrace(FRAMES_TO_SKIP,
|
||||
FRAMES_TO_CAPTURE,
|
||||
frames,
|
||||
NULL);
|
||||
if (numFrames > 0) {
|
||||
CopyStackFrames(&pTagHistory->StackFrames, numFrames, frames);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// We use the perf counter here and the tick count in the tracking block.
|
||||
// Use the tick count here as well until we decide that correlating the
|
||||
// perf counter to system time is not important.
|
||||
//
|
||||
// pTagHistory->Time = KeQueryPerformanceCounter(NULL);
|
||||
Mx::MxQueryTickCount(&pTagHistory->Time);
|
||||
|
||||
if (RefType == TagAddRef) {
|
||||
|
||||
//
|
||||
// Try to allocate some memory for the new block. If unsuccessful,
|
||||
// fallback to a failed count increment.
|
||||
//
|
||||
pBlock = new(pFxDriverGlobals) FxTagTrackingBlock(Tag, Line, File);
|
||||
|
||||
if (pBlock == NULL) {
|
||||
InterlockedIncrement(&m_FailedCount);
|
||||
}
|
||||
else {
|
||||
m_SpinLock.Acquire(&irql);
|
||||
pBlock->Next = m_Next;
|
||||
m_Next = pBlock;
|
||||
m_SpinLock.Release(irql);
|
||||
|
||||
if (m_CaptureStack && numFrames > 0) {
|
||||
CopyStackFrames(&pBlock->StackFrames, numFrames, frames);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
FxTagTrackingBlock **prev;
|
||||
|
||||
//
|
||||
// Walk the list of current blocks and attempt to find the tag being
|
||||
// released. If not found, decrement the failed count. If no failed
|
||||
// tags exists, ASSERT immediately.
|
||||
//
|
||||
|
||||
m_SpinLock.Acquire(&irql);
|
||||
prev = &m_Next;
|
||||
pBlock = *prev;
|
||||
|
||||
while (pBlock != NULL) {
|
||||
if (pBlock->Tag == Tag) {
|
||||
*prev = pBlock->Next;
|
||||
break;
|
||||
}
|
||||
|
||||
prev = &pBlock->Next;
|
||||
pBlock = pBlock->Next;
|
||||
}
|
||||
|
||||
m_SpinLock.Release(irql);
|
||||
|
||||
if (pBlock == NULL) {
|
||||
//
|
||||
// Check to see if we have any credits in our Low Memory Count.
|
||||
// In this fassion we can tell if we have acquired any locks without
|
||||
// the memory for adding tracking blocks.
|
||||
//
|
||||
if (InterlockedDecrement(&m_FailedCount) < 0) {
|
||||
//
|
||||
// We have just released a lock that neither had a corresponding
|
||||
// tracking block, nor a credit in LowMemoryCount.
|
||||
//
|
||||
InterlockedIncrement(&m_FailedCount);
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"releasing %s %p on object %p that was not acquired, !wdftagtracker %p",
|
||||
m_TrackerType == FxTagTrackerTypePower ? "power tag" : "tag",
|
||||
Tag,
|
||||
m_OwningObject,
|
||||
this);
|
||||
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
}
|
||||
}
|
||||
else {
|
||||
delete pBlock;
|
||||
pBlock = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FxTagTracker::CheckForAbandondedTags(
|
||||
VOID
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Iterates over any existing tags, dumping any existing tags to the debugger.
|
||||
Will assert if there any outstanding tags (assumes that the caller wants
|
||||
no current tags).
|
||||
|
||||
Arguments:
|
||||
None
|
||||
|
||||
Return Value:
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxTagTrackingBlock *current, *next;
|
||||
LONG abandoned;
|
||||
KIRQL irql;
|
||||
BOOLEAN committed;
|
||||
|
||||
pFxDriverGlobals = GetDriverGlobals();
|
||||
|
||||
committed = m_OwningObject->IsCommitted();
|
||||
|
||||
//
|
||||
// If the object was not committed, then it was an FxObject derived
|
||||
// class that was *embedded* as a field in another structure or class.
|
||||
// As such, we are allowing one outstanding reference at this time. We will
|
||||
// catch > 1 outstanding references below in the while loop.
|
||||
//
|
||||
if (committed) {
|
||||
if (m_Next != NULL || m_FailedCount != 0) {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Dropped references on a tag tracker, "
|
||||
"show references with: !wdftagtracker %p", this);
|
||||
//
|
||||
// If this ASSERT fails, look in the history .. you'll
|
||||
// likely find that you released more references than you had
|
||||
//
|
||||
ASSERT(m_Next == NULL && m_FailedCount == 0);
|
||||
}
|
||||
}
|
||||
|
||||
m_SpinLock.Acquire(&irql);
|
||||
|
||||
current = m_Next;
|
||||
abandoned = 0;
|
||||
|
||||
while (current != NULL) {
|
||||
next = current->Next;
|
||||
|
||||
if (committed) {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Abandonded ref on object %p tag %p (%s @ %d)",
|
||||
m_OwningObject, current->Tag, current->File, current->Line);
|
||||
abandoned++;
|
||||
}
|
||||
|
||||
if (committed == FALSE) {
|
||||
//
|
||||
// The next time we encounter an abandoned reference, we will complain
|
||||
// about it...we have used up our allowance of one leaked reference
|
||||
// because the object is an embedded object.
|
||||
//
|
||||
// NOTE: we might be eating the real outstanding reference here
|
||||
// and not tracing it and then tracing the initial creation
|
||||
// reference as the leaked reference which will be confusing.
|
||||
// This is b/c there is no way to distinguish what is the
|
||||
// tracking block used to track the creatio of the object.
|
||||
//
|
||||
committed = TRUE;
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGDEVICE,
|
||||
"Possibly Abandonded ref on object %p tag %p (%s @ %d). "
|
||||
"Is benign unless there are other outstanding leaked references.",
|
||||
m_OwningObject, current->Tag, current->File, current->Line);
|
||||
}
|
||||
|
||||
current = next;
|
||||
}
|
||||
|
||||
m_SpinLock.Release(irql);
|
||||
|
||||
ASSERTMSG("Abandoned tags on ref\n", abandoned == 0);
|
||||
}
|
||||
|
||||
|
106
sdk/lib/drivers/wdf/shared/object/fxuserobject.cpp
Normal file
106
sdk/lib/drivers/wdf/shared/object/fxuserobject.cpp
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxUserObject.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the user object that device
|
||||
driver writers can use to take advantage of the
|
||||
driver frameworks infrastructure.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Both kernel and user mode
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxobjectpch.hpp"
|
||||
|
||||
#include "FxUserObject.hpp"
|
||||
|
||||
// Tracing support
|
||||
extern "C" {
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "FxUserObject.tmh"
|
||||
#endif
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxUserObject::_Create(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in_opt PWDF_OBJECT_ATTRIBUTES Attributes,
|
||||
__out FxUserObject** pUserObject
|
||||
)
|
||||
{
|
||||
FxUserObject* pObject = NULL;
|
||||
NTSTATUS status;
|
||||
USHORT wrapperSize = 0;
|
||||
WDFOBJECT handle;
|
||||
|
||||
#ifdef INLINE_WRAPPER_ALLOCATION
|
||||
#if FX_CORE_MODE==FX_CORE_USER_MODE
|
||||
wrapperSize = FxUserObject::GetWrapperSize();
|
||||
#endif
|
||||
#endif
|
||||
|
||||
pObject = new(FxDriverGlobals, Attributes, wrapperSize)
|
||||
FxUserObject(FxDriverGlobals);
|
||||
|
||||
|
||||
if (pObject == NULL) {
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGOBJECT,
|
||||
"Memory allocation failed");
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
status = pObject->Commit(Attributes, &handle);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR,
|
||||
TRACINGOBJECT,
|
||||
"FxObject::Commit failed %!STATUS!", status);
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
*pUserObject = pObject;
|
||||
}
|
||||
else {
|
||||
pObject->DeleteFromFailedCreate();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Public constructors
|
||||
//
|
||||
|
||||
FxUserObject::FxUserObject(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals
|
||||
) :
|
||||
#ifdef INLINE_WRAPPER_ALLOCATION
|
||||
FxNonPagedObject(FX_TYPE_USEROBJECT, sizeof(FxUserObject) + GetWrapperSize(), FxDriverGlobals)
|
||||
#else
|
||||
FxNonPagedObject(FX_TYPE_USEROBJECT, sizeof(FxUserObject), FxDriverGlobals)
|
||||
#endif
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
145
sdk/lib/drivers/wdf/shared/object/fxuserobjectapi.cpp
Normal file
145
sdk/lib/drivers/wdf/shared/object/fxuserobjectapi.cpp
Normal file
|
@ -0,0 +1,145 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxUserObjectApi.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This modules implements the C API's for the FxUserObject.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Both kernel and user mode
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxobjectpch.hpp"
|
||||
|
||||
#include "FxUserObject.hpp"
|
||||
|
||||
// Tracing support
|
||||
extern "C" {
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "FxUserObjectApi.tmh"
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfObjectCreate)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in_opt
|
||||
PWDF_OBJECT_ATTRIBUTES Attributes,
|
||||
__out
|
||||
WDFOBJECT* Object
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This creates a general WDF object for use by the device driver.
|
||||
|
||||
It participates in general framework object contracts in that it:
|
||||
|
||||
- Has a handle and a reference count
|
||||
- Has Cleanup and Destroy callbacks
|
||||
- Supports driver context memory and type
|
||||
- Can have child objects
|
||||
- Can optionally have a parent object and automatically delete with it
|
||||
|
||||
It is intended to allow a WDF device driver to use this object to
|
||||
create its own structures that can participate in frameworks lifetime
|
||||
management.
|
||||
|
||||
The device driver can use the objects context memory and type to
|
||||
represent its own internal data structures, and can further assign
|
||||
device driver specific resources and release them by registering
|
||||
for EvtObjectCleanup, and EvtObjectDestroy callbacks.
|
||||
|
||||
The object may be deleted by using the WdfObjectDelete API.
|
||||
|
||||
Since the object is represented by a frameworks handle, it can be
|
||||
reference counted, and validated.
|
||||
|
||||
Class drivers may use this object to define framework object handles
|
||||
for their types.
|
||||
|
||||
Arguments:
|
||||
|
||||
Attributes - WDF_OBJECT_ATTRIBUTES to define a parent object, context memory,
|
||||
Cleanup and Destroy handlers.
|
||||
|
||||
Return Value:
|
||||
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
DDI_ENTRY();
|
||||
|
||||
NTSTATUS status;
|
||||
WDFOBJECT handle;
|
||||
FxUserObject* pUserObject;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
|
||||
pUserObject = NULL;
|
||||
pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
|
||||
|
||||
//
|
||||
// Get the parent's globals if it is present
|
||||
//
|
||||
if (NT_SUCCESS(FxValidateObjectAttributesForParentHandle(pFxDriverGlobals,
|
||||
Attributes))) {
|
||||
FxObject* pParent;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
|
||||
Attributes->ParentObject,
|
||||
FX_TYPE_OBJECT,
|
||||
(PVOID*)&pParent,
|
||||
&pFxDriverGlobals);
|
||||
}
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, Object);
|
||||
|
||||
status = FxValidateObjectAttributes(pFxDriverGlobals,
|
||||
Attributes,
|
||||
FX_VALIDATE_OPTION_EXECUTION_LEVEL_ALLOWED
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Create the FxObject.
|
||||
//
|
||||
status = FxUserObject::_Create(pFxDriverGlobals, Attributes, &pUserObject);
|
||||
if (NT_SUCCESS(status)) {
|
||||
handle = pUserObject->GetHandle();
|
||||
*Object = handle;
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE,
|
||||
TRACINGUSEROBJECT,
|
||||
"Created UserObject Handle 0x%p",
|
||||
handle);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
} // extern "C" the entire file
|
220
sdk/lib/drivers/wdf/shared/object/fxvalidatefunctions.cpp
Normal file
220
sdk/lib/drivers/wdf/shared/object/fxvalidatefunctions.cpp
Normal file
|
@ -0,0 +1,220 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
FxValidateFunctions.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Functions which validate external WDF data structures
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Both kernel and user mode
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxobjectpch.hpp"
|
||||
|
||||
// We use DoTraceMessage
|
||||
extern "C" {
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "FxValidateFunctions.tmh"
|
||||
#endif
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxValidateObjectAttributes(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PWDF_OBJECT_ATTRIBUTES Attributes,
|
||||
__in ULONG Flags
|
||||
)
|
||||
{
|
||||
if (Attributes == NULL) {
|
||||
if (Flags & FX_VALIDATE_OPTION_ATTRIBUTES_REQUIRED) {
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"WDF_OBJECT_ATTRIBUTES required, %!STATUS!",
|
||||
(ULONG) STATUS_WDF_PARENT_NOT_SPECIFIED);
|
||||
|
||||
return STATUS_WDF_PARENT_NOT_SPECIFIED;
|
||||
}
|
||||
else {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (Attributes->Size != sizeof(WDF_OBJECT_ATTRIBUTES)) {
|
||||
//
|
||||
// Size is wrong, bail out
|
||||
//
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
|
||||
"Attributes %p Size incorrect, expected %d, got %d, %!STATUS!",
|
||||
Attributes, sizeof(WDF_OBJECT_ATTRIBUTES),
|
||||
Attributes->Size, STATUS_INFO_LENGTH_MISMATCH);
|
||||
|
||||
return STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
if (Attributes->ContextTypeInfo != NULL) {
|
||||
#pragma prefast(suppress:__WARNING_REDUNDANTTEST, "different structs of the same size")
|
||||
if (Attributes->ContextTypeInfo->Size !=
|
||||
sizeof(WDF_OBJECT_CONTEXT_TYPE_INFO) &&
|
||||
Attributes->ContextTypeInfo->Size !=
|
||||
sizeof(WDF_OBJECT_CONTEXT_TYPE_INFO_V1_0)) {
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
|
||||
"Attributes %p ContextTypeInfo %p Size %d incorrect, expected %d, %!STATUS!",
|
||||
Attributes, Attributes->ContextTypeInfo,
|
||||
Attributes->ContextTypeInfo->Size,
|
||||
sizeof(WDF_OBJECT_CONTEXT_TYPE_INFO), STATUS_INFO_LENGTH_MISMATCH);
|
||||
|
||||
return STATUS_INFO_LENGTH_MISMATCH;
|
||||
}
|
||||
|
||||
//
|
||||
// A ContextName != NULL and a ContextSize of 0 is allowed
|
||||
//
|
||||
if (Attributes->ContextTypeInfo->ContextSize > 0 &&
|
||||
Attributes->ContextTypeInfo->ContextName == NULL) {
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
|
||||
"Attributes %p ContextTypeInfo %p ContextSize %I64d is not zero, "
|
||||
"but ContextName is NULL, %!STATUS!",
|
||||
Attributes, Attributes->ContextTypeInfo,
|
||||
Attributes->ContextTypeInfo->ContextSize,
|
||||
STATUS_WDF_OBJECT_ATTRIBUTES_INVALID);
|
||||
|
||||
return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
if (Attributes->ContextSizeOverride > 0) {
|
||||
if (Attributes->ContextTypeInfo == NULL) {
|
||||
//
|
||||
// Can't specify additional size without a type
|
||||
//
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
|
||||
"Attributes %p ContextSizeOverride of %I64d specified, but no type "
|
||||
"information, %!STATUS!",
|
||||
Attributes, Attributes->ContextSizeOverride,
|
||||
STATUS_WDF_OBJECT_ATTRIBUTES_INVALID);
|
||||
|
||||
return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID;
|
||||
}
|
||||
else if (Attributes->ContextSizeOverride <
|
||||
Attributes->ContextTypeInfo->ContextSize) {
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
|
||||
"Attributes %p ContextSizeOverride %I64d < "
|
||||
"ContextTypeInfo->ContextSize %I64d, %!STATUS!",
|
||||
Attributes, Attributes->ContextSizeOverride,
|
||||
Attributes->ContextTypeInfo->ContextSize,
|
||||
STATUS_WDF_OBJECT_ATTRIBUTES_INVALID);
|
||||
|
||||
return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
if (Flags & FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED) {
|
||||
if (Attributes->ParentObject != NULL) {
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
|
||||
"Attributes %p does not allow a parent object to be set, set to "
|
||||
"%p, %!STATUS!", Attributes, Attributes->ParentObject,
|
||||
STATUS_WDF_PARENT_ASSIGNMENT_NOT_ALLOWED);
|
||||
|
||||
return STATUS_WDF_PARENT_ASSIGNMENT_NOT_ALLOWED;
|
||||
}
|
||||
}
|
||||
else if ((Flags & FX_VALIDATE_OPTION_PARENT_REQUIRED_FLAG) &&
|
||||
Attributes->ParentObject == NULL) {
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"ParentObject required in WDF_OBJECT_ATTRIBUTES %p, %!STATUS!",
|
||||
Attributes, STATUS_WDF_PARENT_NOT_SPECIFIED);
|
||||
|
||||
return STATUS_WDF_PARENT_NOT_SPECIFIED;
|
||||
}
|
||||
|
||||
// Enum range checks
|
||||
if ((Attributes->ExecutionLevel == WdfExecutionLevelInvalid) ||
|
||||
(Attributes->ExecutionLevel > WdfExecutionLevelDispatch)) {
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
|
||||
"Attributes %p execution level set to %d, out of range, %!STATUS!",
|
||||
Attributes, Attributes->ExecutionLevel,
|
||||
STATUS_WDF_OBJECT_ATTRIBUTES_INVALID);
|
||||
return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID;
|
||||
}
|
||||
|
||||
if ((Attributes->SynchronizationScope == WdfSynchronizationScopeInvalid) ||
|
||||
(Attributes->SynchronizationScope > WdfSynchronizationScopeNone)) {
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
|
||||
"Attributes %p synchronization scope set to %d, out of range, %!STATUS!",
|
||||
Attributes, Attributes->SynchronizationScope,
|
||||
STATUS_WDF_OBJECT_ATTRIBUTES_INVALID);
|
||||
return STATUS_WDF_OBJECT_ATTRIBUTES_INVALID;
|
||||
}
|
||||
|
||||
if ((Flags & FX_VALIDATE_OPTION_SYNCHRONIZATION_SCOPE_ALLOWED) == 0) {
|
||||
|
||||
//
|
||||
// If synchronization is not allowed for this object,
|
||||
// check the requested level to ensure none was specified.
|
||||
//
|
||||
if ((Attributes->SynchronizationScope != WdfSynchronizationScopeInheritFromParent) &&
|
||||
(Attributes->SynchronizationScope != WdfSynchronizationScopeNone)) {
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
|
||||
"Attributes %p does not allow synchronization scope too be set, "
|
||||
"but was set to %!WDF_SYNCHRONIZATION_SCOPE!, %!STATUS!",
|
||||
Attributes, Attributes->SynchronizationScope,
|
||||
STATUS_WDF_SYNCHRONIZATION_SCOPE_INVALID);
|
||||
|
||||
return STATUS_WDF_SYNCHRONIZATION_SCOPE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
if ((Flags & FX_VALIDATE_OPTION_EXECUTION_LEVEL_ALLOWED) == 0) {
|
||||
|
||||
//
|
||||
// If execution level restrictions are not allowed for this object,
|
||||
// check the requested level to ensure none was specified.
|
||||
//
|
||||
if (Attributes->ExecutionLevel != WdfExecutionLevelInheritFromParent) {
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGAPIERROR,
|
||||
"Attributes %p does not allow execution level to be set, but was"
|
||||
" set to %!WDF_EXECUTION_LEVEL!, %!STATUS!",
|
||||
Attributes, Attributes->ExecutionLevel,
|
||||
STATUS_WDF_EXECUTION_LEVEL_INVALID);
|
||||
|
||||
return STATUS_WDF_EXECUTION_LEVEL_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
107
sdk/lib/drivers/wdf/shared/object/fxverifierbugcheck.cpp
Normal file
107
sdk/lib/drivers/wdf/shared/object/fxverifierbugcheck.cpp
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxVerifierBugcheck.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This file contains definitions of verifier bugcheck functions
|
||||
These definitions are split from tracing.cpp in kmdf\src\core
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Both kernel and user mode
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxobjectpch.hpp"
|
||||
|
||||
// We use DoTraceMessage
|
||||
extern "C" {
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "FxVerifierBugcheck.tmh"
|
||||
#endif
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
|
||||
VOID
|
||||
__declspec(noreturn)
|
||||
FxVerifierBugCheckWorker(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in WDF_BUGCHECK_CODES WdfBugCheckCode,
|
||||
__in_opt ULONG_PTR BugCheckParameter2,
|
||||
__in_opt ULONG_PTR BugCheckParameter3
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Wrapper for system BugCheck.
|
||||
|
||||
Note this functions is marked "__declspec(noreturn)"
|
||||
|
||||
Arguments:
|
||||
|
||||
Returns:
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// Indicate to the BugCheck callback filter which IFR to dump.
|
||||
//
|
||||
FxDriverGlobals->FxForceLogsInMiniDump = TRUE;
|
||||
|
||||
Mx::MxBugCheckEx(WDF_VIOLATION,
|
||||
WdfBugCheckCode,
|
||||
BugCheckParameter2,
|
||||
BugCheckParameter3,
|
||||
(ULONG_PTR) FxDriverGlobals );
|
||||
}
|
||||
|
||||
VOID
|
||||
__declspec(noreturn)
|
||||
FxVerifierNullBugCheck(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PVOID ReturnAddress
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Calls KeBugCheckEx indicating a WDF DDI was passed a NULL parameter.
|
||||
|
||||
Note this functions is marked "__declspec(noreturn)"
|
||||
|
||||
Arguments:
|
||||
|
||||
Returns:
|
||||
|
||||
--*/
|
||||
{
|
||||
|
||||
DoTraceLevelMessage( FxDriverGlobals, TRACE_LEVEL_FATAL, TRACINGERROR,
|
||||
"NULL Required Parameter Passed to a DDI\n"
|
||||
"FxDriverGlobals 0x%p",
|
||||
FxDriverGlobals
|
||||
);
|
||||
|
||||
FxVerifierBugCheck(FxDriverGlobals,
|
||||
WDF_REQUIRED_PARAMETER_IS_NULL, // Bugcheck code.
|
||||
0, // Parameter 2
|
||||
(ULONG_PTR)ReturnAddress // Parameter 3
|
||||
);
|
||||
}
|
1050
sdk/lib/drivers/wdf/shared/object/fxverifierlock.cpp
Normal file
1050
sdk/lib/drivers/wdf/shared/object/fxverifierlock.cpp
Normal file
File diff suppressed because it is too large
Load diff
1740
sdk/lib/drivers/wdf/shared/object/globals.cpp
Normal file
1740
sdk/lib/drivers/wdf/shared/object/globals.cpp
Normal file
File diff suppressed because it is too large
Load diff
702
sdk/lib/drivers/wdf/shared/object/handleapi.cpp
Normal file
702
sdk/lib/drivers/wdf/shared/object/handleapi.cpp
Normal file
|
@ -0,0 +1,702 @@
|
|||
/*++
|
||||
|
||||
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_t
|
||||
FxGetContextSize(
|
||||
__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_
|
||||
NTSTATUS
|
||||
FxCalculateObjectTotalSize2(
|
||||
__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_
|
||||
NTSTATUS
|
||||
FxCalculateObjectTotalSize(
|
||||
__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);
|
||||
}
|
||||
|
||||
PVOID
|
||||
FxObjectHandleAlloc(
|
||||
__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;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxContextHeaderInit(
|
||||
__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;
|
||||
}
|
||||
}
|
||||
|
||||
PVOID
|
||||
FxObjectAndHandleHeaderInit(
|
||||
__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;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxObjectHandleGetPtrQI(
|
||||
__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_
|
||||
NTSTATUS
|
||||
FxObjectAllocateContext(
|
||||
__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 APIs
|
||||
extern "C" {
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFAPI
|
||||
NTSTATUS
|
||||
WDFEXPORT(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)
|
||||
WDFAPI
|
||||
PVOID
|
||||
FASTCALL
|
||||
WDFEXPORT(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)
|
||||
WDFAPI
|
||||
WDFOBJECT
|
||||
FASTCALL
|
||||
WDFEXPORT(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"
|
120
sdk/lib/drivers/wdf/shared/object/km/fxobjectkm.cpp
Normal file
120
sdk/lib/drivers/wdf/shared/object/km/fxobjectkm.cpp
Normal file
|
@ -0,0 +1,120 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxObjectKm.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Kernel mode implementations of FxObject APIs
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxobjectpch.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "FxObjectKm.tmh"
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxObject::_ObjectQuery(
|
||||
_In_ FxObject* Object,
|
||||
_In_ CONST GUID* Guid,
|
||||
_In_ ULONG QueryBufferLength,
|
||||
_Out_writes_bytes_(QueryBufferLength)
|
||||
PVOID QueryBuffer
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Query the object handle for specific information
|
||||
|
||||
This allows dynamic extensions to DDI's.
|
||||
|
||||
Currently, it is used to allow test hooks for verification
|
||||
which are not available in a production release.
|
||||
|
||||
Arguments:
|
||||
|
||||
Object - Object to query
|
||||
|
||||
Guid - GUID to represent the information/DDI to query for
|
||||
|
||||
QueryBufferLength - Length of QueryBuffer to return data in
|
||||
|
||||
QueryBuffer - Pointer to QueryBuffer
|
||||
|
||||
Returns:
|
||||
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
// PFX_DRIVER_GLOBALS pFxDriverGlobals = Object->GetDriverGlobals();
|
||||
|
||||
//
|
||||
// Design Note: This interface does not look strongly typed
|
||||
// but it is. The GUID defines a specific strongly typed
|
||||
// contract for QueryBuffer and QueryBufferLength.
|
||||
//
|
||||
|
||||
#if DBG
|
||||
|
||||
//
|
||||
// These operations are only available on checked builds for deep unit
|
||||
// testing, code coverage analysis, and model verification.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
|
||||
// Add code based on the GUID
|
||||
|
||||
// IsEqualGUID(guid1, guid2), DEFINE_GUID, INITGUID, inc\wnet\guiddef.h
|
||||
UNREFERENCED_PARAMETER(Object);
|
||||
UNREFERENCED_PARAMETER(Guid);
|
||||
UNREFERENCED_PARAMETER(QueryBufferLength);
|
||||
UNREFERENCED_PARAMETER(QueryBuffer);
|
||||
#else
|
||||
UNREFERENCED_PARAMETER(Object);
|
||||
UNREFERENCED_PARAMETER(Guid);
|
||||
UNREFERENCED_PARAMETER(QueryBufferLength);
|
||||
UNREFERENCED_PARAMETER(QueryBuffer);
|
||||
#endif
|
||||
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
} // extern "C"
|
254
sdk/lib/drivers/wdf/shared/object/km/globalskm.cpp
Normal file
254
sdk/lib/drivers/wdf/shared/object/km/globalskm.cpp
Normal file
|
@ -0,0 +1,254 @@
|
|||
//
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
//
|
||||
#include "fxobjectpch.hpp"
|
||||
|
||||
// Tracing support
|
||||
extern "C" {
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "GlobalsKm.tmh"
|
||||
#endif
|
||||
|
||||
#include <wdfcxbase.h>
|
||||
#include <fxldr.h>
|
||||
|
||||
|
||||
}
|
||||
extern "C" {
|
||||
|
||||
VOID
|
||||
FxFreeAllocatedMdlsDebugInfo(
|
||||
__in FxDriverGlobalsDebugExtension* DebugExtension
|
||||
)
|
||||
{
|
||||
FxAllocatedMdls* pNext, *pCur;
|
||||
|
||||
pNext = DebugExtension->AllocatedMdls.Next;
|
||||
|
||||
//
|
||||
// MDL leaks were already checked for in FxPoolDestroy, just free all
|
||||
// the tables here.
|
||||
//
|
||||
while (pNext != NULL) {
|
||||
pCur = pNext;
|
||||
pNext = pCur->Next;
|
||||
|
||||
ExFreePool(pCur);
|
||||
}
|
||||
}
|
||||
|
||||
KDEFERRED_ROUTINE FxFlushDpc;
|
||||
|
||||
__drv_functionClass(KDEFERRED_ROUTINE)
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
__drv_minIRQL(DISPATCH_LEVEL)
|
||||
__drv_requiresIRQL(DISPATCH_LEVEL)
|
||||
__drv_sameIRQL
|
||||
VOID
|
||||
FxFlushDpc (
|
||||
__in struct _KDPC *Dpc,
|
||||
__in_opt PVOID DeferredContext,
|
||||
__in_opt PVOID SystemArgument1,
|
||||
__in_opt PVOID SystemArgument2
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This DPC is called on a processor to assist in flushing previous DPC's
|
||||
|
||||
Arguments:
|
||||
|
||||
Dpc - Supplies a pointer to DPC object.
|
||||
|
||||
DeferredContext - Supplies the deferred context (event object address).
|
||||
|
||||
SystemArgument1 - Supplies the first system context parameter (not used).
|
||||
|
||||
SystemArgument2 - Supplies the second system context parameter (not used).
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
|
||||
UNREFERENCED_PARAMETER(Dpc);
|
||||
UNREFERENCED_PARAMETER(SystemArgument1);
|
||||
UNREFERENCED_PARAMETER(SystemArgument2);
|
||||
|
||||
//
|
||||
// Signal that this routine has been called.
|
||||
//
|
||||
((FxCREvent*)DeferredContext)->Set();
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
BOOLEAN
|
||||
FX_DRIVER_GLOBALS::IsVersionGreaterThanOrEqualTo(
|
||||
__in ULONG Major,
|
||||
__in ULONG Minor
|
||||
)
|
||||
{
|
||||
if ((WdfBindInfo->Version.Major > Major) ||
|
||||
(WdfBindInfo->Version.Major == Major &&
|
||||
WdfBindInfo->Version.Minor >= Minor)) {
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
#define WDF_MAJOR_VERSION_VALUE L"WdfMajorVersion"
|
||||
#define WDF_MINOR_VERSION_VALUE L"WdfMinorVersion"
|
||||
|
||||
_Must_inspect_result_
|
||||
BOOLEAN
|
||||
FX_DRIVER_GLOBALS::IsCorrectVersionRegistered(
|
||||
_In_ PCUNICODE_STRING ServiceKeyName
|
||||
)
|
||||
{
|
||||
FxAutoRegKey hDriver, hWdf;
|
||||
DECLARE_CONST_UNICODE_STRING(parametersPath, L"Parameters\\Wdf");
|
||||
DECLARE_CONST_UNICODE_STRING(wdfMajorValue, WDF_MAJOR_VERSION_VALUE);
|
||||
DECLARE_CONST_UNICODE_STRING(wdfMinorValue, WDF_MINOR_VERSION_VALUE);
|
||||
ULONG registeredMajor = 0, registeredMinor = 0;
|
||||
NTSTATUS status;
|
||||
|
||||
status = FxRegKey::_OpenKey(NULL,
|
||||
ServiceKeyName,
|
||||
&hDriver.m_Key,
|
||||
KEY_READ
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = FxRegKey::_OpenKey(hDriver.m_Key,
|
||||
¶metersPath,
|
||||
&hWdf.m_Key,
|
||||
KEY_READ
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = FxRegKey::_QueryULong(hWdf.m_Key,
|
||||
&wdfMajorValue,
|
||||
®isteredMajor);
|
||||
|
||||
if (!NT_SUCCESS(status) || registeredMajor != WdfBindInfo->Version.Major) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
status = FxRegKey::_QueryULong(hWdf.m_Key,
|
||||
&wdfMinorValue,
|
||||
®isteredMinor);
|
||||
|
||||
if (!NT_SUCCESS(status) || registeredMinor != WdfBindInfo->Version.Minor){
|
||||
return FALSE;
|
||||
}
|
||||
else {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FX_DRIVER_GLOBALS::RegisterClientVersion(
|
||||
_In_ PCUNICODE_STRING ServiceKeyName
|
||||
)
|
||||
{
|
||||
FxAutoRegKey hDriver, hParameters, hWdf;
|
||||
DECLARE_CONST_UNICODE_STRING(parametersPart, L"Parameters");
|
||||
DECLARE_CONST_UNICODE_STRING(wdfPart, L"Wdf");
|
||||
//
|
||||
// Not defined with the macro because ZwSetValue doesn't use PCUNICODE_STRING
|
||||
//
|
||||
UNICODE_STRING wdfMajorValue;
|
||||
UNICODE_STRING wdfMinorValue;
|
||||
NTSTATUS status;
|
||||
|
||||
RtlInitUnicodeString(&wdfMajorValue, WDF_MAJOR_VERSION_VALUE);
|
||||
RtlInitUnicodeString(&wdfMinorValue, WDF_MINOR_VERSION_VALUE);
|
||||
|
||||
status = FxRegKey::_OpenKey(NULL,
|
||||
ServiceKeyName,
|
||||
&hDriver.m_Key,
|
||||
KEY_WRITE | KEY_READ
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER,
|
||||
"Unable to open driver's service key, status %!STATUS!", status);
|
||||
return;
|
||||
}
|
||||
//
|
||||
// Key creation, unlike user mode, must happen one level at a time, since
|
||||
// create will also open take both steps instead of trying open first
|
||||
//
|
||||
status = FxRegKey::_Create(hDriver.m_Key,
|
||||
¶metersPart,
|
||||
&hParameters.m_Key,
|
||||
KEY_WRITE | KEY_READ
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER,
|
||||
"Unable to write Parameters key, status %!STATUS!", status);
|
||||
return;
|
||||
}
|
||||
|
||||
status = FxRegKey::_Create(hParameters.m_Key,
|
||||
&wdfPart,
|
||||
&hWdf.m_Key,
|
||||
KEY_WRITE | KEY_READ
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER,
|
||||
"Unable to write Parameters key, status %!STATUS!", status);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Using ZwSetValueKey here to avoid having to change the implementation
|
||||
// in FxRegKey of SetValue to a static / thiscall pair
|
||||
//
|
||||
status = ZwSetValueKey(hWdf.m_Key,
|
||||
&wdfMajorValue,
|
||||
0,
|
||||
REG_DWORD,
|
||||
&WdfBindInfo->Version.Major,
|
||||
sizeof(WdfBindInfo->Version.Major)
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER,
|
||||
"Failed to record driver major version value, status %!STATUS!", status);
|
||||
}
|
||||
|
||||
status = ZwSetValueKey(hWdf.m_Key,
|
||||
&wdfMinorValue,
|
||||
0,
|
||||
REG_DWORD,
|
||||
&WdfBindInfo->Version.Minor,
|
||||
sizeof(WdfBindInfo->Version.Minor)
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(this, TRACE_LEVEL_VERBOSE, TRACINGDRIVER,
|
||||
"Failed to record driver version value, status %!STATUS!", status);
|
||||
}
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
||||
_Must_inspect_result_
|
||||
BOOLEAN
|
||||
FX_DRIVER_GLOBALS::IsDebuggerAttached(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return (FALSE == KdRefreshDebuggerNotPresent());
|
||||
}
|
272
sdk/lib/drivers/wdf/shared/object/km/wdfpoolkm.cpp
Normal file
272
sdk/lib/drivers/wdf/shared/object/km/wdfpoolkm.cpp
Normal file
|
@ -0,0 +1,272 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
wdfpoolkm.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the driver frameworks pool routines
|
||||
functionality only applicable in kernel mode
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxobjectpch.hpp"
|
||||
|
||||
// We use DoTraceMessage
|
||||
extern "C" {
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "wdfpoolkm.tmh"
|
||||
#endif
|
||||
}
|
||||
|
||||
// undo the previous masking
|
||||
#undef IoAllocateMdl
|
||||
#undef IoFreeMdl
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
NTKERNELAPI
|
||||
PMDL
|
||||
IoAllocateMdl(
|
||||
__in_opt __drv_aliasesMem PVOID VirtualAddress,
|
||||
__in ULONG Length,
|
||||
__in BOOLEAN SecondaryBuffer,
|
||||
__in BOOLEAN ChargeQuota,
|
||||
__inout_opt PIRP Irp
|
||||
);
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
NTKERNELAPI
|
||||
VOID
|
||||
IoFreeMdl(
|
||||
PMDL Mdl
|
||||
);
|
||||
|
||||
//
|
||||
// Windows Driver Framework Pool Tracking
|
||||
//
|
||||
// This module implements a generic pool tracking mechanism
|
||||
// if pool verifier mode is enabled.
|
||||
//
|
||||
// There can be multiple pools, each represented by a FX_POOL header.
|
||||
//
|
||||
// When the framework is supplied as a DLL, there is a global
|
||||
// pool that represents allocations for the framework DLL itself. These
|
||||
// allocations are pool allocations and object allocations.
|
||||
//
|
||||
// The driver's pool allocations are not currently tracked. If the driver needs
|
||||
// to use pool outside of the framework objects, it calls the WDM
|
||||
// ExAllocatePoolWithTag and ExFreePool(WithTag) APIs.
|
||||
//
|
||||
|
||||
|
||||
|
||||
PMDL
|
||||
FxMdlAllocateDebug(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in FxObject* Owner,
|
||||
__in PVOID VirtualAddress,
|
||||
__in ULONG Length,
|
||||
__in BOOLEAN SecondaryBuffer,
|
||||
__in BOOLEAN ChargeQuota,
|
||||
__in PVOID CallersAddress
|
||||
)
|
||||
{
|
||||
FxDriverGlobalsDebugExtension* pExtension;
|
||||
FxAllocatedMdls* pAllocated, **ppNext;
|
||||
ULONG i;
|
||||
PMDL pMdl;
|
||||
KIRQL irql;
|
||||
|
||||
pExtension = FxDriverGlobals->DebugExtension;
|
||||
if (pExtension == NULL) {
|
||||
return IoAllocateMdl(VirtualAddress,
|
||||
Length,
|
||||
SecondaryBuffer,
|
||||
ChargeQuota,
|
||||
NULL);
|
||||
}
|
||||
|
||||
pAllocated = &pExtension->AllocatedMdls;
|
||||
ppNext = NULL;
|
||||
pMdl = NULL;
|
||||
|
||||
KeAcquireSpinLock(&pExtension->AllocatedMdlsLock, &irql);
|
||||
|
||||
while (pAllocated != NULL && pAllocated->Count == NUM_MDLS_IN_INFO) {
|
||||
ppNext = &pAllocated->Next;
|
||||
pAllocated = pAllocated->Next;
|
||||
}
|
||||
|
||||
if (pAllocated == NULL) {
|
||||
//
|
||||
// No more entries, allocate a new table
|
||||
//
|
||||
pAllocated = (FxAllocatedMdls*) ExAllocatePoolWithTag(
|
||||
NonPagedPool, sizeof(FxAllocatedMdls), FxDriverGlobals->Tag);
|
||||
|
||||
if (pAllocated != NULL) {
|
||||
//
|
||||
// Zero out the new buffer and link it in to the list
|
||||
//
|
||||
RtlZeroMemory(pAllocated, sizeof(*pAllocated));
|
||||
*ppNext = pAllocated;
|
||||
}
|
||||
else {
|
||||
//
|
||||
// Could not allocate a new table, return error
|
||||
//
|
||||
KeReleaseSpinLock(&pExtension->AllocatedMdlsLock, irql);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < NUM_MDLS_IN_INFO; i++) {
|
||||
if (pAllocated->Info[i].Mdl != NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pMdl = IoAllocateMdl(VirtualAddress,
|
||||
Length,
|
||||
SecondaryBuffer,
|
||||
ChargeQuota,
|
||||
NULL);
|
||||
|
||||
if (pMdl != NULL) {
|
||||
pAllocated->Info[i].Mdl = pMdl;
|
||||
pAllocated->Info[i].Owner = Owner;
|
||||
pAllocated->Info[i].Caller = CallersAddress;
|
||||
pAllocated->Count++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&pExtension->AllocatedMdlsLock, irql);
|
||||
|
||||
return pMdl;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxMdlFreeDebug(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PMDL Mdl
|
||||
)
|
||||
{
|
||||
FxDriverGlobalsDebugExtension* pExtension;
|
||||
FxAllocatedMdls* pAllocated, **ppNext;
|
||||
ULONG i;
|
||||
KIRQL irql;
|
||||
BOOLEAN found;
|
||||
|
||||
pExtension = FxDriverGlobals->DebugExtension;
|
||||
if (pExtension == NULL) {
|
||||
IoFreeMdl(Mdl);
|
||||
return;
|
||||
}
|
||||
|
||||
found = FALSE;
|
||||
|
||||
pAllocated = &pExtension->AllocatedMdls;
|
||||
ppNext = NULL;
|
||||
|
||||
KeAcquireSpinLock(&pExtension->AllocatedMdlsLock, &irql);
|
||||
|
||||
while (pAllocated != NULL) {
|
||||
for (i = 0; i < NUM_MDLS_IN_INFO; i++) {
|
||||
if (pAllocated->Info[i].Mdl != Mdl) {
|
||||
continue;
|
||||
}
|
||||
|
||||
RtlZeroMemory(&pAllocated->Info[i],
|
||||
sizeof(pAllocated->Info[i]));
|
||||
|
||||
pAllocated->Count--;
|
||||
|
||||
if (pAllocated->Count == 0 &&
|
||||
pAllocated != &pExtension->AllocatedMdls) {
|
||||
//
|
||||
// Remove the current table from the chain
|
||||
//
|
||||
*ppNext = pAllocated->Next;
|
||||
|
||||
//
|
||||
// And free it
|
||||
//
|
||||
ExFreePool(pAllocated);
|
||||
}
|
||||
|
||||
IoFreeMdl(Mdl);
|
||||
found = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
|
||||
ppNext = &pAllocated->Next;
|
||||
pAllocated = pAllocated->Next;
|
||||
}
|
||||
|
||||
KeReleaseSpinLock(&pExtension->AllocatedMdlsLock, irql);
|
||||
|
||||
if (found == FALSE) {
|
||||
|
||||
|
||||
|
||||
FxVerifierDbgBreakPoint(FxDriverGlobals);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FxMdlDump(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals
|
||||
)
|
||||
{
|
||||
FxAllocatedMdls *pCur;
|
||||
BOOLEAN leak;
|
||||
|
||||
if (FxDriverGlobals->DebugExtension == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
leak = FALSE;
|
||||
|
||||
for (pCur = &FxDriverGlobals->DebugExtension->AllocatedMdls;
|
||||
pCur != NULL;
|
||||
pCur = pCur->Next) {
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < NUM_MDLS_IN_INFO; i++) {
|
||||
if (pCur->Info[i].Mdl != NULL) {
|
||||
leak = TRUE;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"PMDL 0x%p leaked, FxObject owner %p, Callers Address %p",
|
||||
pCur->Info[i].Mdl, pCur->Info[i].Owner,
|
||||
pCur->Info[i].Caller);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (leak) {
|
||||
FxVerifierDbgBreakPoint(FxDriverGlobals);
|
||||
}
|
||||
}
|
||||
|
37
sdk/lib/drivers/wdf/shared/object/objectpriv.hpp
Normal file
37
sdk/lib/drivers/wdf/shared/object/objectpriv.hpp
Normal file
|
@ -0,0 +1,37 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
objectpriv.hpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Private header file for shared\object directory
|
||||
It is then included in objectpch.hpp
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Both kernel and user mode
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
extern "C" {
|
||||
#include "mx.h"
|
||||
}
|
||||
|
||||
//
|
||||
// Root WDF key, for both UMDF and KMDF settings.
|
||||
//
|
||||
#define WDF_REGISTRY_BASE_PATH L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Wdf"
|
||||
|
||||
#define WDF_GLOBAL_VALUE_IFRDISABLED L"WdfGlobalLogsDisabled" // REG_DWORD
|
||||
|
70
sdk/lib/drivers/wdf/shared/object/um/fxobjectinfoum.cpp
Normal file
70
sdk/lib/drivers/wdf/shared/object/um/fxobjectinfoum.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
//
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
//
|
||||
#include "FxMin.hpp"
|
||||
#include "fxobjectpch.hpp"
|
||||
|
||||
#include "FxUserObject.hpp"
|
||||
#include "pnppriv.hpp"
|
||||
|
||||
//
|
||||
// More object types should be added to this table as more objects
|
||||
// are merged and incorporated in UMDF
|
||||
//
|
||||
|
||||
extern "C" {
|
||||
|
||||
//
|
||||
// Assumes sorted (by type) order!
|
||||
//
|
||||
FX_OBJECT_INFO FxObjectsInfo[] = {
|
||||
FX_INTERNAL_OBJECT_INFO_ENTRY(FxObject, FX_TYPE_OBJECT),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxDriver, FX_TYPE_DRIVER, WDFDRIVER),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxDevice, FX_TYPE_DEVICE, WDFDEVICE),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxIoQueue, FX_TYPE_QUEUE, WDFQUEUE),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxWmiProvider, FX_TYPE_WMI_PROVIDER, WDFWMIPROVIDER),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxRegKey, FX_TYPE_REG_KEY, WDFKEY),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxString, FX_TYPE_STRING, WDFSTRING),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxRequest, FX_TYPE_REQUEST, WDFREQUEST),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxLookasideList, FX_TYPE_LOOKASIDE, WDFLOOKASIDE),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxMemoryObject, IFX_TYPE_MEMORY, WDFMEMORY),
|
||||
FX_INTERNAL_OBJECT_INFO_ENTRY(FxIrpQueue, FX_TYPE_IRPQUEUE),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxUserObject, FX_TYPE_USEROBJECT, WDFOBJECT),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxCollection, FX_TYPE_COLLECTION, WDFCOLLECTION),
|
||||
FX_INTERNAL_OBJECT_INFO_ENTRY(FxVerifierLock, FX_TYPE_VERIFIERLOCK),
|
||||
FX_INTERNAL_OBJECT_INFO_ENTRY(FxSystemThread, FX_TYPE_SYSTEMTHREAD),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxMpDevice, FX_TYPE_MP_DEVICE, WDFDEVICE),
|
||||
FX_INTERNAL_OBJECT_INFO_ENTRY(FxResourceIo, FX_TYPE_RESOURCE_IO),
|
||||
FX_INTERNAL_OBJECT_INFO_ENTRY(FxResourceCm, FX_TYPE_RESOURCE_CM),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxFileObject, FX_TYPE_FILEOBJECT, WDFFILEOBJECT),
|
||||
FX_INTERNAL_OBJECT_INFO_ENTRY(FxRelatedDevice, FX_TYPE_RELATED_DEVICE),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxMemoryBufferPreallocated, FX_TYPE_MEMORY_PREALLOCATED, WDFMEMORY),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxWaitLock, FX_TYPE_WAIT_LOCK, WDFWAITLOCK),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxSpinLock, FX_TYPE_SPIN_LOCK, WDFSPINLOCK),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxWorkItem, FX_TYPE_WORKITEM, WDFWORKITEM),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxInterrupt, FX_TYPE_INTERRUPT, WDFINTERRUPT),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxTimer, FX_TYPE_TIMER, WDFTIMER),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxChildList, FX_TYPE_CHILD_LIST, WDFCHILDLIST),
|
||||
FX_INTERNAL_OBJECT_INFO_ENTRY(FxSystemWorkItem, FX_TYPE_SYSTEMWORKITEM),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxRequestMemory, FX_TYPE_REQUEST_MEMORY, WDFMEMORY),
|
||||
FX_INTERNAL_OBJECT_INFO_ENTRY(FxDisposeList, FX_TYPE_DISPOSELIST),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxIoResList, FX_TYPE_IO_RES_LIST, WDFIORESLIST),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxCmResList, FX_TYPE_CM_RES_LIST, WDFCMRESLIST),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxIoResReqList, FX_TYPE_IO_RES_REQ_LIST, WDFIORESREQLIST),
|
||||
|
||||
FX_INTERNAL_OBJECT_INFO_ENTRY(FxPkgIo, FX_TYPE_PACKAGE_IO),
|
||||
FX_INTERNAL_OBJECT_INFO_ENTRY(FxPkgFdo, FX_TYPE_PACKAGE_FDO),
|
||||
FX_INTERNAL_OBJECT_INFO_ENTRY(FxPkgPdo, FX_TYPE_PACKAGE_PDO),
|
||||
FX_INTERNAL_OBJECT_INFO_ENTRY(FxPkgGeneral, FX_TYPE_PACKAGE_GENERAL),
|
||||
FX_INTERNAL_OBJECT_INFO_ENTRY(FxDefaultIrpHandler, FX_TYPE_DEFAULT_IRP_HANDLER),
|
||||
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxIoTarget, FX_TYPE_IO_TARGET, WDFIOTARGET),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxUsbDevice, FX_TYPE_IO_TARGET_USB_DEVICE, WDFUSBDEVICE),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxUsbPipe, FX_TYPE_IO_TARGET_USB_PIPE, WDFUSBPIPE),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxUsbInterface, FX_TYPE_USB_INTERFACE, WDFUSBINTERFACE),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxIoTargetSelf, FX_TYPE_IO_TARGET_SELF, WDFIOTARGET),
|
||||
};
|
||||
|
||||
ULONG FxObjectsInfoCount = sizeof(FxObjectsInfo)/sizeof(FX_OBJECT_INFO);
|
||||
|
||||
} //extern "C"
|
194
sdk/lib/drivers/wdf/shared/object/um/fxobjectum.cpp
Normal file
194
sdk/lib/drivers/wdf/shared/object/um/fxobjectum.cpp
Normal file
|
@ -0,0 +1,194 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxObjectUm.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
User mode implementations of FxObject APIs
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
user mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxobjectpch.hpp"
|
||||
|
||||
extern "C" {
|
||||
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "FxObjectUm.tmh"
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
|
||||
#define INITGUID
|
||||
#include <guiddef.h>
|
||||
|
||||
#include <WdfFileObject_private.h>
|
||||
|
||||
//
|
||||
// Function declarations for the WdfObjectQuery DDIs
|
||||
//
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
WDFAPI
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfFileObjectIncrementProcessKeepAliveCount)(
|
||||
_In_
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
_In_
|
||||
WDFFILEOBJECT FileObject
|
||||
);
|
||||
|
||||
_IRQL_requires_max_(PASSIVE_LEVEL)
|
||||
WDFAPI
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfFileObjectDecrementProcessKeepAliveCount)(
|
||||
_In_
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
_In_
|
||||
WDFFILEOBJECT FileObject
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
extern "C" {
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxObject::_ObjectQuery(
|
||||
_In_ FxObject* Object,
|
||||
_In_ CONST GUID* Guid,
|
||||
_In_ ULONG QueryBufferLength,
|
||||
_Out_writes_bytes_(QueryBufferLength)
|
||||
PVOID QueryBuffer
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Query the object handle for specific information
|
||||
|
||||
This allows dynamic extensions to DDI's.
|
||||
|
||||
Currently, it is used to allow test hooks for verification
|
||||
which are not available in a production release.
|
||||
|
||||
Arguments:
|
||||
|
||||
Object - Object to query
|
||||
|
||||
Guid - GUID to represent the information/DDI to query for
|
||||
|
||||
QueryBufferLength - Length of QueryBuffer to return data in
|
||||
|
||||
QueryBuffer - Pointer to QueryBuffer
|
||||
|
||||
Returns:
|
||||
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals = Object->GetDriverGlobals();
|
||||
|
||||
//
|
||||
// Design Note: This interface does not look strongly typed
|
||||
// but it is. The GUID defines a specific strongly typed
|
||||
// contract for QueryBuffer and QueryBufferLength.
|
||||
//
|
||||
|
||||
#if DBG
|
||||
|
||||
//
|
||||
// These operations are only available on checked builds for deep unit
|
||||
// testing, code coverage analysis, and model verification.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
|
||||
// Add code based on the GUID
|
||||
|
||||
// IsEqualGUID(guid1, guid2), DEFINE_GUID, INITGUID, inc\wnet\guiddef.h
|
||||
#endif
|
||||
|
||||
if (IsEqualGUID(*Guid, GUID_WDFP_FILEOBJECT_INTERFACE)) {
|
||||
|
||||
//
|
||||
// Check the query buffer size before performing the cast
|
||||
//
|
||||
const ULONG RequiredBufferLength = sizeof(WDFP_FILEOBJECT_INTERFACE);
|
||||
|
||||
if (QueryBufferLength < RequiredBufferLength) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Insufficient query buffer size for file object query "
|
||||
"Required size %d, %!STATUS!",
|
||||
RequiredBufferLength,
|
||||
STATUS_BUFFER_TOO_SMALL);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
if (nullptr == QueryBuffer) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"NULL query buffer for file object query, %!STATUS!",
|
||||
STATUS_BUFFER_TOO_SMALL);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
PWDFP_FILEOBJECT_INTERFACE FileObjectInterface =
|
||||
reinterpret_cast<PWDFP_FILEOBJECT_INTERFACE>(QueryBuffer);
|
||||
|
||||
//
|
||||
// Check the struct version (require an exact match for a private DDI)
|
||||
//
|
||||
if (FileObjectInterface->Size != RequiredBufferLength) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Wrong struct version provided for file object query, "
|
||||
"%!STATUS!",
|
||||
STATUS_INVALID_PARAMETER);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
FileObjectInterface->WdfpFileObjectIncrementProcessKeepAliveCount =
|
||||
WDFEXPORT(WdfFileObjectIncrementProcessKeepAliveCount);
|
||||
FileObjectInterface->WdfpFileObjectDecrementProcessKeepAliveCount =
|
||||
WDFEXPORT(WdfFileObjectDecrementProcessKeepAliveCount);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return STATUS_NOT_FOUND;
|
||||
}
|
||||
|
||||
} // extern "C"
|
67
sdk/lib/drivers/wdf/shared/object/um/globalsum.cpp
Normal file
67
sdk/lib/drivers/wdf/shared/object/um/globalsum.cpp
Normal file
|
@ -0,0 +1,67 @@
|
|||
//
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
//
|
||||
#include "fxobjectpch.hpp"
|
||||
#include "fxldrum.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
VOID
|
||||
FxFreeAllocatedMdlsDebugInfo(
|
||||
__in FxDriverGlobalsDebugExtension* DebugExtension
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(DebugExtension);
|
||||
|
||||
//DO_NOTHING()
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
BOOLEAN
|
||||
FX_DRIVER_GLOBALS::IsCorrectVersionRegistered(
|
||||
_In_ PCUNICODE_STRING /*ServiceKeyName*/
|
||||
)
|
||||
{
|
||||
return TRUE; // Then it won't even call the next method
|
||||
}
|
||||
|
||||
VOID
|
||||
FX_DRIVER_GLOBALS::RegisterClientVersion(
|
||||
_In_ PCUNICODE_STRING ServiceKeyName
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(ServiceKeyName);
|
||||
|
||||
ASSERTMSG("Not implemented for UMDF\n", FALSE);
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
BOOLEAN
|
||||
FX_DRIVER_GLOBALS::IsVersionGreaterThanOrEqualTo(
|
||||
__in ULONG Major,
|
||||
__in ULONG Minor
|
||||
)
|
||||
{
|
||||
if ((WdfBindInfo->Version.Major > Major) ||
|
||||
(WdfBindInfo->Version.Major == Major &&
|
||||
WdfBindInfo->Version.Minor >= Minor)) {
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
BOOLEAN
|
||||
FX_DRIVER_GLOBALS::IsDebuggerAttached(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// COnvert the returned BOOL into BOOLEAN
|
||||
//
|
||||
return (IsDebuggerPresent() != FALSE);
|
||||
}
|
710
sdk/lib/drivers/wdf/shared/object/wdfpool.cpp
Normal file
710
sdk/lib/drivers/wdf/shared/object/wdfpool.cpp
Normal file
|
@ -0,0 +1,710 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
wdfpool.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the driver frameworks pool routines.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Both kernel and user mode
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxobjectpch.hpp"
|
||||
|
||||
// We use DoTraceMessage
|
||||
extern "C" {
|
||||
|
||||
#if defined(EVENT_TRACING)
|
||||
#include "wdfpool.tmh"
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxIsPagedPoolType(
|
||||
__in POOL_TYPE Type
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Return whether paged pool is specified by POOL_TYPE
|
||||
|
||||
Arguments:
|
||||
|
||||
Type - POOL_TYPE
|
||||
|
||||
Returns:
|
||||
TRUE - Paged Pool,FALSE - Non-Paged Pool
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// Cleaner than doing (Type & 0x01)
|
||||
//
|
||||
switch( Type & (~POOL_COLD_ALLOCATION) ) {
|
||||
case PagedPool:
|
||||
case PagedPoolCacheAligned:
|
||||
return TRUE;
|
||||
|
||||
default:
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PVOID
|
||||
FxPoolAllocator(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PFX_POOL Pool,
|
||||
__in POOL_TYPE Type,
|
||||
__in SIZE_T Size,
|
||||
__in ULONG Tag,
|
||||
__in PVOID Caller
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Allocates system pool tracked in a FX_POOL tracking object.
|
||||
|
||||
Arguments:
|
||||
|
||||
Pool - FX_POOL object for tracking allocations
|
||||
|
||||
Type - POOL_TYPE from ntddk.h
|
||||
|
||||
Size - Size in bytes of the allocation
|
||||
|
||||
Tag - Caller specified additional tag value for debugging/tracing
|
||||
|
||||
Caller - Caller's address
|
||||
|
||||
Returns:
|
||||
|
||||
NULL - Could not allocate pool
|
||||
!NULL - Pointer to pool of minimum Size bytes
|
||||
|
||||
Remarks:
|
||||
|
||||
In kernel mode this routine conditionally adds header on top iff the
|
||||
allocation size is < PAGE_SIZE. If the allocation size is >= PAGE_SIZE
|
||||
the caller would expect a page aligned pointer, hence no header is added.
|
||||
In addition, ExAllocatePool* functions guarantee that a buffer < PAGE_SIZE
|
||||
doesn't straddle page boundary. This allows FxPoolFree to determine whether
|
||||
a header is added to buffer or not based on whether the pointer passed in
|
||||
is page aligned or not. (In addition, when pool tracking is ON, this
|
||||
routine adds pool tracking header based on whether additional space for this
|
||||
header will push the buffer size beyond PAGE_SIZE, which is an optimization.)
|
||||
|
||||
Such guarantees are not available with user mode allocator, hence in case
|
||||
of user mode we always add the header. (In user mode a buffer < PAGE_SIZE
|
||||
can straddle page boundary and the pointer returned may happen to be page
|
||||
aligned, causing FxPoolFree to free the wrong pointer.)
|
||||
|
||||
--*/
|
||||
{
|
||||
PVOID ptr;
|
||||
PCHAR pTrueBase;
|
||||
PFX_POOL_TRACKER pTracker;
|
||||
PFX_POOL_HEADER pHeader;
|
||||
NTSTATUS status;
|
||||
SIZE_T allocationSize;
|
||||
|
||||
|
||||
ptr = NULL;
|
||||
|
||||
//
|
||||
// Allocations of a zero request size are invalid.
|
||||
//
|
||||
// Besides, with a zero request size, special pool could place us
|
||||
// at the end of a page, and adding our header would give us a page
|
||||
// aligned address, which is ambiguous with large allocations.
|
||||
//
|
||||
if (Size == 0) {
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPOOL,
|
||||
"Invalid Allocation Size of 0 requested");
|
||||
FxVerifierDbgBreakPoint(FxDriverGlobals);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (FxDriverGlobals->IsPoolTrackingOn()) {
|
||||
|
||||
if (FxDriverGlobals->FxVerifierOn &&
|
||||
(FxDriverGlobals->WdfVerifierAllocateFailCount != 0xFFFFFFFF)) {
|
||||
|
||||
//
|
||||
// If the registry key VerifierAllocateFailCount is set, all allocations
|
||||
// after the specified count are failed.
|
||||
//
|
||||
// This is a brutal test, but also ensures the framework can cleanup
|
||||
// under low memory conditions as well.
|
||||
//
|
||||
if (FxDriverGlobals->WdfVerifierAllocateFailCount == 0) {
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPOOL,
|
||||
"Allocation Fail Count exceeded");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Decrement the count
|
||||
InterlockedDecrement(&FxDriverGlobals->WdfVerifierAllocateFailCount);
|
||||
}
|
||||
|
||||
//
|
||||
// (Kernel mode only) PAGE_SIZE or greater allocations can not have our
|
||||
// header since this would break the system allocators contract
|
||||
// that PAGE_SIZE or greater allocations start on a whole page boundary
|
||||
//
|
||||
|
||||
//
|
||||
// For allocations less than a page size that will not fit with our
|
||||
// header, we round up to a non-tracked whole page allocation so
|
||||
// we don't burn two pages for this boundary condition.
|
||||
//
|
||||
|
||||
// This if is the same as
|
||||
// Size + sizeof(FX_POOL_TRACKER) + FX_POOL_HEADER_SIZE >= PAGE_SIZE
|
||||
// BUT with no integer overflow
|
||||
if (Mx::IsKM() &&
|
||||
(Size >= PAGE_SIZE - sizeof(FX_POOL_TRACKER) - FX_POOL_HEADER_SIZE)
|
||||
) {
|
||||
|
||||
//
|
||||
// Ensure that we ask for at least a page to ensure the
|
||||
// allocation starts on a whole page.
|
||||
//
|
||||
if (Size < PAGE_SIZE) {
|
||||
Size = PAGE_SIZE;
|
||||
}
|
||||
|
||||
ptr = MxMemory::MxAllocatePoolWithTag(Type, Size, Tag);
|
||||
|
||||
//
|
||||
// The current system allocator returns paged aligned memory
|
||||
// in this case, which we rely on to detect whether our header
|
||||
// is present or not in FxPoolFree
|
||||
//
|
||||
ASSERT(((ULONG_PTR)ptr & (PAGE_SIZE-1)) == 0);
|
||||
}
|
||||
else {
|
||||
|
||||
status = RtlSIZETAdd(Size,
|
||||
sizeof(FX_POOL_TRACKER) + FX_POOL_HEADER_SIZE,
|
||||
&allocationSize);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPOOL,
|
||||
"overflow: allocation tracker (%d) + header (%d) + pool "
|
||||
"request (%I64d)", sizeof(FX_POOL_TRACKER),
|
||||
FX_POOL_HEADER_SIZE, Size);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pTrueBase = (PCHAR) MxMemory::MxAllocatePoolWithTag(
|
||||
Type,
|
||||
allocationSize,
|
||||
Tag
|
||||
);
|
||||
|
||||
if (pTrueBase == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pTracker = (PFX_POOL_TRACKER) pTrueBase;
|
||||
pHeader = WDF_PTR_ADD_OFFSET_TYPE(pTrueBase,
|
||||
sizeof(FX_POOL_TRACKER),
|
||||
PFX_POOL_HEADER);
|
||||
pHeader->Base = pTrueBase;
|
||||
pHeader->FxDriverGlobals = FxDriverGlobals;
|
||||
|
||||
//
|
||||
// Adjust the pointer to what we return to the driver
|
||||
//
|
||||
ptr = &pHeader->AllocationStart[0];
|
||||
|
||||
//
|
||||
// Ensure the pointer we are returning is aligned on the proper
|
||||
// boundary.
|
||||
//
|
||||
ASSERT( ((ULONG_PTR) ptr & (MEMORY_ALLOCATION_ALIGNMENT-1)) == 0);
|
||||
|
||||
//
|
||||
// Ensure the pointer is still not page aligned after
|
||||
// our adjustment. Otherwise the pool free code will
|
||||
// get confused and call ExFreePool on the wrong ptr.
|
||||
//
|
||||
if (Mx::IsKM()) {
|
||||
ASSERT(((ULONG_PTR)ptr & (PAGE_SIZE-1)) != 0 );
|
||||
}
|
||||
|
||||
//
|
||||
// We must separate paged and non-paged pool since
|
||||
// the lock held differs as to whether we can accept
|
||||
// page faults and block in the allocator.
|
||||
//
|
||||
if (FxIsPagedPoolType(Type)) {
|
||||
//
|
||||
// Format and insert the Tracker in the PagedHeader list.
|
||||
//
|
||||
FxPoolInsertPagedAllocateTracker(Pool,
|
||||
pTracker,
|
||||
Size,
|
||||
Tag,
|
||||
Caller);
|
||||
}
|
||||
else {
|
||||
//
|
||||
// Format and insert the Tracker in the NonPagedHeader list.
|
||||
//
|
||||
FxPoolInsertNonPagedAllocateTracker(Pool,
|
||||
pTracker,
|
||||
Size,
|
||||
Tag,
|
||||
Caller);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// No pool tracking...
|
||||
//
|
||||
|
||||
if ((Size < PAGE_SIZE) || Mx::IsUM())
|
||||
{
|
||||
//
|
||||
// (Kernel mode only) See if adding our header promotes us past a
|
||||
// page boundary
|
||||
//
|
||||
status = RtlSIZETAdd(Size,
|
||||
FX_POOL_HEADER_SIZE,
|
||||
&allocationSize);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPOOL,
|
||||
"overflow: header + pool request (%I64d)", Size);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
//
|
||||
// Is the raw request for alloc >= PAGE_SIZE ? Then just use it.
|
||||
//
|
||||
allocationSize = Size;
|
||||
}
|
||||
|
||||
//
|
||||
// Is cooked size for alloc >= PAGE_SIZE ? Then just do it.
|
||||
//
|
||||
if (allocationSize >= PAGE_SIZE && Mx::IsKM())
|
||||
{
|
||||
//
|
||||
// Important to use allocationSize so that we get a page aligned
|
||||
// allocation so that we know to just free the memory pointer as is
|
||||
// when it is freed.
|
||||
//
|
||||
ptr = MxMemory::MxAllocatePoolWithTag(Type, allocationSize, Tag);
|
||||
ASSERT(((ULONG_PTR)ptr & (PAGE_SIZE-1)) == 0);
|
||||
}
|
||||
else {
|
||||
pTrueBase = (PCHAR) MxMemory::MxAllocatePoolWithTag(Type,
|
||||
allocationSize,
|
||||
Tag);
|
||||
|
||||
if (pTrueBase != NULL) {
|
||||
|
||||
pHeader = (PFX_POOL_HEADER) pTrueBase;
|
||||
pHeader->Base = pTrueBase;
|
||||
pHeader->FxDriverGlobals = FxDriverGlobals;
|
||||
|
||||
ptr = &pHeader->AllocationStart[0];
|
||||
|
||||
if (Mx::IsKM()) {
|
||||
//
|
||||
// Ensure the pointer is still not page aligned after
|
||||
// our adjustment. Otherwise the pool free code will
|
||||
// get confused and call ExFreePool on the wrong ptr.
|
||||
//
|
||||
ASSERT( ((ULONG_PTR)ptr & (PAGE_SIZE-1)) != 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxPoolFree(
|
||||
__in_xcount(ptr is at an offset from AllocationStart) PVOID ptr
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Release tracked pool
|
||||
|
||||
Arguments:
|
||||
|
||||
Pool - FX_POOL object allocation is tracked in
|
||||
|
||||
ptr - Pointer to pool to release
|
||||
|
||||
Returns:
|
||||
|
||||
Remarks:
|
||||
In kernel mode the pointer passed in may or may not have a header before
|
||||
it depending upon whether the pointer is page aligned or not.
|
||||
|
||||
In user mode the pointer passed in always has a header before it. See
|
||||
remarks for FxPoolAllocator.
|
||||
|
||||
--*/
|
||||
{
|
||||
PFX_POOL_HEADER pHeader;
|
||||
PVOID pTrueBase;
|
||||
PFX_POOL_TRACKER pTracker;
|
||||
|
||||
//
|
||||
// Null pointers are always bad
|
||||
//
|
||||
if( ptr == NULL ) {
|
||||
ASSERTMSG("NULL pointer freed\n", FALSE);
|
||||
Mx::MxBugCheckEx(WDF_VIOLATION,
|
||||
WDF_REQUIRED_PARAMETER_IS_NULL,
|
||||
(ULONG_PTR)NULL,
|
||||
(ULONG_PTR)_ReturnAddress(),
|
||||
(ULONG_PTR)NULL
|
||||
);
|
||||
}
|
||||
|
||||
//
|
||||
// (Kernel mode only) If ptr is aligned on page boundry (indicates
|
||||
// it was > PAGE_SIZE allocation)
|
||||
// then there will be no common header...just free the memory without
|
||||
// further processing.
|
||||
//
|
||||
if( Mx::IsKM() && ( ((ULONG_PTR)ptr & (PAGE_SIZE-1)) == 0 ) ) {
|
||||
MxMemory::MxFreePool(ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Ensure the pointer we are returning is aligned on the proper
|
||||
// boundary.
|
||||
//
|
||||
ASSERT( ((ULONG_PTR) ptr & (MEMORY_ALLOCATION_ALIGNMENT-1)) == 0);
|
||||
|
||||
//
|
||||
// Dereference the Common header which all <PAGE_SIZE allcations will have.
|
||||
//
|
||||
pHeader = CONTAINING_RECORD(ptr, FX_POOL_HEADER, AllocationStart);
|
||||
pTrueBase = pHeader->Base;
|
||||
|
||||
//
|
||||
// If PoolTracker is on then Base must point to it's header.
|
||||
// This is currently the only option for this area...may change later.
|
||||
//
|
||||
if (pHeader->FxDriverGlobals->IsPoolTrackingOn()) {
|
||||
|
||||
pTracker = (PFX_POOL_TRACKER) pTrueBase;
|
||||
|
||||
if (FxIsPagedPoolType(pTracker->PoolType)) {
|
||||
//
|
||||
// Decommission this Paged Allocation tracker
|
||||
//
|
||||
FxPoolRemovePagedAllocateTracker(pTracker);
|
||||
}
|
||||
else {
|
||||
//
|
||||
// Decommission this NonPaged Allocation tracker
|
||||
//
|
||||
FxPoolRemoveNonPagedAllocateTracker(pTracker);
|
||||
}
|
||||
|
||||
//
|
||||
// Scrub the pool to zeros to catch destructed objects
|
||||
// by NULL'ing the v-table ptr
|
||||
//
|
||||
RtlZeroMemory(pTracker, pTracker->Size + sizeof(FX_POOL_TRACKER));
|
||||
}
|
||||
|
||||
MxMemory::MxFreePool(pTrueBase);
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxPoolDump(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PFX_POOL Pool
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Dump the FX_POOL tracking object
|
||||
|
||||
Arguments:
|
||||
|
||||
Pool - FX_POOL object for tracking allocations
|
||||
|
||||
Returns:
|
||||
|
||||
STATUS_SUCCESS
|
||||
|
||||
--*/
|
||||
{
|
||||
PFX_POOL_TRACKER pTracker;
|
||||
PLIST_ENTRY ple;
|
||||
KIRQL oldIrql;
|
||||
BOOLEAN leak;
|
||||
|
||||
//
|
||||
// Dump usage information
|
||||
//
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"FxPoolDump: "
|
||||
"NonPagedBytes %I64d, PagedBytes %I64d, "
|
||||
"NonPagedAllocations %d, PagedAllocations %d,"
|
||||
"PeakNonPagedBytes %I64d, PeakPagedBytes %I64d,"
|
||||
"FxPoolDump: PeakNonPagedAllocations %d, PeakPagedAllocations %d",
|
||||
Pool->NonPagedBytes, Pool->PagedBytes,
|
||||
Pool->NonPagedAllocations, Pool->PagedAllocations,
|
||||
Pool->PeakNonPagedBytes, Pool->PeakPagedBytes,
|
||||
Pool->PeakNonPagedAllocations, Pool->PeakPagedAllocations
|
||||
);
|
||||
|
||||
leak = FALSE;
|
||||
|
||||
//
|
||||
// Check paged pool for leaks
|
||||
//
|
||||
Pool->PagedLock.Acquire();
|
||||
|
||||
for (ple = Pool->PagedHead.Flink; ple != &Pool->PagedHead; ple = ple->Flink) {
|
||||
pTracker = CONTAINING_RECORD(ple, FX_POOL_TRACKER, Link);
|
||||
|
||||
// Leaker
|
||||
leak = TRUE;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"FX_POOL 0x%p leaked paged memory alloc 0x%p (tracking block %p)",
|
||||
Pool, pTracker + 1, pTracker);
|
||||
}
|
||||
|
||||
Pool->PagedLock.Release();
|
||||
|
||||
//
|
||||
// Check non-paged pool for leaks
|
||||
//
|
||||
|
||||
Pool->NonPagedLock.Acquire(&oldIrql);
|
||||
|
||||
for (ple = Pool->NonPagedHead.Flink;
|
||||
ple != &Pool->NonPagedHead;
|
||||
ple = ple->Flink) {
|
||||
pTracker = CONTAINING_RECORD(ple, FX_POOL_TRACKER, Link );
|
||||
|
||||
// Leaker
|
||||
leak = TRUE;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"FX_POOL 0x%p leaked non-paged memory alloc 0x%p (tracking block %p)",
|
||||
Pool, pTracker+1, pTracker);
|
||||
}
|
||||
|
||||
Pool->NonPagedLock.Release(oldIrql);
|
||||
|
||||
if (leak) {
|
||||
FxVerifierDbgBreakPoint(FxDriverGlobals);
|
||||
return STATUS_MORE_ENTRIES;
|
||||
}
|
||||
else {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxPoolInitialize(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PFX_POOL Pool
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Initialize the FX_POOL tracking object
|
||||
|
||||
Arguments:
|
||||
Pool - FX_POOL object for tracking allocations
|
||||
|
||||
Returns:
|
||||
STATUS_SUCCESS
|
||||
|
||||
--*/
|
||||
{
|
||||
NTSTATUS status = STATUS_SUCCESS;
|
||||
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPOOL,
|
||||
"Initializing Pool 0x%p, Tracking %d",
|
||||
Pool, FxDriverGlobals->IsPoolTrackingOn());
|
||||
|
||||
Pool->NonPagedLock.Initialize();
|
||||
|
||||
InitializeListHead( &Pool->NonPagedHead );
|
||||
|
||||
status = Pool->PagedLock.Initialize();
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPOOL,
|
||||
"Initializing paged lock failed for Pool 0x%p, "
|
||||
"status %!STATUS!",
|
||||
Pool, status);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
InitializeListHead( &Pool->PagedHead );
|
||||
|
||||
// Pool usage information
|
||||
Pool->NonPagedBytes = 0;
|
||||
Pool->PagedBytes = 0;
|
||||
|
||||
Pool->NonPagedAllocations = 0;
|
||||
Pool->PagedAllocations = 0;
|
||||
|
||||
Pool->PeakNonPagedBytes = 0;
|
||||
Pool->PeakPagedBytes = 0;
|
||||
|
||||
Pool->PeakNonPagedAllocations = 0;
|
||||
Pool->PeakPagedAllocations = 0;
|
||||
|
||||
exit:
|
||||
if (!NT_SUCCESS(status)) {
|
||||
//
|
||||
// We disable pool tracking if we could not initialize the locks needed
|
||||
//
|
||||
// If we don't do this we would need another flag to make FxPoolDestroy
|
||||
// not access the locks
|
||||
//
|
||||
FxDriverGlobals->FxPoolTrackingOn = FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// FxPoolDestroy will always be called even if we fail FxPoolInitialize
|
||||
//
|
||||
// FxPoolDestroy will uninitialize locks both in success and failure
|
||||
// cases
|
||||
//
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxPoolDestroy(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PFX_POOL Pool
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Destroy the FX_POOL tracking object
|
||||
|
||||
Arguments:
|
||||
Pool - FX_POOL object for tracking allocations
|
||||
|
||||
Returns:
|
||||
STATUS_SUCCESS
|
||||
|
||||
--*/
|
||||
{
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPOOL,
|
||||
"Destroying Pool 0x%p", Pool);
|
||||
|
||||
if (FxDriverGlobals->IsPoolTrackingOn()) {
|
||||
FxPoolDump(FxDriverGlobals, Pool);
|
||||
|
||||
#if FX_CORE_MODE==FX_CORE_KERNEL_MODE
|
||||
FxMdlDump(FxDriverGlobals);
|
||||
#endif
|
||||
//
|
||||
// We don't automatically free memory items since we don't
|
||||
// know what they contain, and who is still referencing them.
|
||||
//
|
||||
}
|
||||
|
||||
Pool->PagedLock.Uninitialize();
|
||||
Pool->NonPagedLock.Uninitialize();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxPoolPackageInitialize(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Initialize the pool support package at startup time.
|
||||
|
||||
This must be called before the first allocation.
|
||||
|
||||
Arguments:
|
||||
FxDriverGlobals - DriverGlobals
|
||||
|
||||
Returns:
|
||||
STATUS_SUCCESS
|
||||
|
||||
--*/
|
||||
{
|
||||
return FxPoolInitialize(FxDriverGlobals, &FxDriverGlobals->FxPoolFrameworks);
|
||||
}
|
||||
|
||||
VOID
|
||||
FxPoolPackageDestroy(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Destroy the pool support package at unload time
|
||||
|
||||
This must be after the last free
|
||||
|
||||
Arguments:
|
||||
FxDriverGlobals - Driver's globals
|
||||
|
||||
Returns:
|
||||
STATUS_SUCCESS
|
||||
|
||||
--*/
|
||||
{
|
||||
FxPoolDestroy(FxDriverGlobals, &FxDriverGlobals->FxPoolFrameworks);
|
||||
return;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue