mirror of
https://github.com/reactos/reactos.git
synced 2025-08-06 13:13:00 +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
208
sdk/lib/drivers/wdf/kmdf/inc/private/fx.hpp
Normal file
208
sdk/lib/drivers/wdf/kmdf/inc/private/fx.hpp
Normal file
|
@ -0,0 +1,208 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
Fx.hpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This is the main driver framework include file.
|
||||
|
||||
Author:
|
||||
WDF team
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _FX_H
|
||||
#define _FX_H
|
||||
|
||||
extern "C" {
|
||||
#include "mx.h"
|
||||
}
|
||||
|
||||
#include "FxMacros.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "wdf.h"
|
||||
#include "wdmsec.h"
|
||||
#include "wdmguid.h"
|
||||
|
||||
#include "wdfdevicepri.h"
|
||||
#include "wdfiotargetpri.h"
|
||||
#include "wdfcx.h"
|
||||
#include "wdfldr.h"
|
||||
|
||||
#include <FxDynamicsWrapper.h>
|
||||
|
||||
#include "wdf10.h"
|
||||
#include "wdf11.h"
|
||||
#include "wdf15.h"
|
||||
#include "wdf17.h"
|
||||
#include "wdf19.h"
|
||||
#include "wdf111.h"
|
||||
#include "wdf113.h"
|
||||
#include "wdf115.h"
|
||||
}
|
||||
|
||||
#define KMDF_ONLY_CODE_PATH_ASSERT()
|
||||
|
||||
// Integer overflow functions
|
||||
#include "ntintsafe.h"
|
||||
|
||||
#include "FxForward.hpp"
|
||||
|
||||
//KMDF defines for shared type names
|
||||
#include "FxTypeDefsKm.hpp"
|
||||
|
||||
#include "fxwmicompat.h"
|
||||
#include "fxtrace.h"
|
||||
#include "fxtypes.h"
|
||||
#include "fxrequestcontexttypes.h"
|
||||
#include "fxpool.h"
|
||||
#include "FxGlobalsKM.h"
|
||||
#include "FxPoolInlines.hpp"
|
||||
#include "fxverifier.h"
|
||||
#include "fxverifierkm.h"
|
||||
#include "FxMdl.h"
|
||||
#include "FxProbeAndLock.h"
|
||||
|
||||
#include "FxPerfTraceKm.hpp"
|
||||
#include "DriverFrameworks-KernelMode-KmEvents.h"
|
||||
|
||||
#include <NtStrSafe.h>
|
||||
|
||||
#include "FxStump.hpp"
|
||||
|
||||
#include "FxRequestBuffer.hpp"
|
||||
|
||||
#include "FxTagTracker.hpp"
|
||||
|
||||
// internal locks
|
||||
#include "FxVerifierLock.hpp"
|
||||
#include "FxLock.hpp"
|
||||
|
||||
// base objects
|
||||
#include "fxobject.hpp"
|
||||
#include "FxPagedObject.hpp"
|
||||
#include "FxNonPagedObject.hpp"
|
||||
|
||||
#include "fxhandle.h"
|
||||
|
||||
// external locks
|
||||
#include "FxWaitLock.hpp"
|
||||
#include "FxSpinLock.hpp"
|
||||
|
||||
// utitilty classes and functions
|
||||
#include "FxTransactionedList.hpp"
|
||||
#include "FxRelatedDeviceList.hpp"
|
||||
#include "FxDisposeList.hpp"
|
||||
#include "FxCollection.hpp"
|
||||
#include "StringUtil.hpp"
|
||||
|
||||
// abstract classes
|
||||
#include "IFxHasCallbacks.hpp"
|
||||
|
||||
// callback delegation and locking
|
||||
#include "FxSystemThread.hpp"
|
||||
#include "FxSystemWorkItem.hpp"
|
||||
#include "FxCallbackLock.hpp"
|
||||
#include "FxCallbackSpinLock.hpp"
|
||||
#include "FxCallbackMutexLock.hpp"
|
||||
#include "FxCallback.hpp"
|
||||
#include "FxSystemThread.hpp"
|
||||
|
||||
#include "IFxMemory.hpp"
|
||||
#include "FxLookasideList.hpp"
|
||||
#include "FxNPagedLookasideList.hpp"
|
||||
#include "FxPagedLookasideList.hpp"
|
||||
#include "FxMemoryObject.hpp"
|
||||
#include "FxMemoryBuffer.hpp"
|
||||
#include "FxMemoryBufferFromPool.hpp"
|
||||
#include "FxMemoryBufferPreallocated.hpp"
|
||||
#include "FxMemoryBufferFromLookaside.hpp"
|
||||
#include "FxRequestMemory.hpp"
|
||||
#include "FxRegKey.hpp"
|
||||
#include "FxAutoRegistry.hpp"
|
||||
#include "FxAutoString.hpp"
|
||||
#include "FxString.hpp"
|
||||
|
||||
#include "FxValidateFunctions.hpp"
|
||||
#include "FxRequestValidateFunctions.hpp"
|
||||
|
||||
#include "FxResource.hpp"
|
||||
#include "FxRelatedDevice.hpp"
|
||||
#include "FxDeviceInterface.hpp"
|
||||
#include "FxQueryInterface.hpp"
|
||||
#include "FxDeviceText.hpp"
|
||||
|
||||
#include "FxIrp.hpp"
|
||||
#include "FxDriver.hpp"
|
||||
|
||||
// generic package interface
|
||||
#include "FxPackage.hpp"
|
||||
#include "FxPkgGeneral.hpp"
|
||||
#include "FxDefaultIrpHandler.hpp"
|
||||
#include "FxPkgPnp.hpp"
|
||||
#include "FxWatchDog.hpp"
|
||||
|
||||
// Device support
|
||||
#include "FxChildList.hpp"
|
||||
#include "FxCxDeviceInfo.hpp"
|
||||
#include "FxDevice.hpp"
|
||||
|
||||
#include "FxPkgIo.hpp"
|
||||
|
||||
#include "FxDeviceToMxInterface.hpp"
|
||||
|
||||
#include "FxIrpQueue.hpp"
|
||||
#include "FxRequestContext.hpp"
|
||||
#include "FxRequestCallbacks.hpp"
|
||||
#include "FxRequestBase.hpp"
|
||||
#include "FxRequest.hpp"
|
||||
#include "FxSyncRequest.hpp"
|
||||
|
||||
// specialized irp handlers (ie packages)
|
||||
#include "FxPkgFdo.hpp"
|
||||
#include "FxPkgPdo.hpp"
|
||||
#include "FxWmiIrpHandler.hpp"
|
||||
#include "FxWmiProvider.hpp"
|
||||
#include "FxWmiInstance.hpp"
|
||||
|
||||
// queus for read, write, (internal) IOCTL
|
||||
#include "FxIoQueue.hpp"
|
||||
#include "FxFileObject.hpp"
|
||||
#include "FxIrpPreprocessInfo.hpp"
|
||||
#include "FxIrpDynamicDispatchInfo.hpp"
|
||||
|
||||
#include "FxDpc.hpp"
|
||||
#include "FxWorkItem.hpp"
|
||||
#include "FxTimer.hpp"
|
||||
#include "FxInterruptKm.hpp"
|
||||
|
||||
// IO targets (device lower edge interface)
|
||||
#include "FxIoTarget.hpp"
|
||||
#include "FxIoTargetRemote.hpp"
|
||||
#include "FxIoTargetSelf.hpp"
|
||||
|
||||
#include "FxUsbDevice.hpp"
|
||||
#include "FxUsbInterface.hpp"
|
||||
#include "FxUsbPipe.hpp"
|
||||
|
||||
// DMA support
|
||||
#include "FxDmaEnabler.hpp"
|
||||
#include "FxDmaTransaction.hpp"
|
||||
#include "FxCommonBuffer.hpp"
|
||||
|
||||
// Triage info.
|
||||
#include "wdftriage.h"
|
||||
|
||||
#include "FxTelemetry.hpp"
|
||||
#endif // _FX_H
|
91
sdk/lib/drivers/wdf/kmdf/inc/private/fxbugcheck.h
Normal file
91
sdk/lib/drivers/wdf/kmdf/inc/private/fxbugcheck.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxBugcheck.h
|
||||
|
||||
Abstract:
|
||||
This module contains private macros/defines for crashdumps.
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef __FXBUGCHECK_H__
|
||||
#define __FXBUGCHECK_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//
|
||||
// Macro for doing pointer arithmetic.
|
||||
//
|
||||
#define Add2Ptr(P,I) ((PVOID)((PUCHAR)(P) + (I)))
|
||||
|
||||
//
|
||||
// This macro takes a length & rounds it up to a multiple of the alignment
|
||||
// Alignment is given as a power of 2
|
||||
//
|
||||
#define EXP_ALIGN_UP_PTR_ON_BOUNDARY(_length, _alignment) \
|
||||
(PVOID) ((((ULONG_PTR) (_length)) + ((_alignment)-1)) & \
|
||||
~(ULONG_PTR)((_alignment) - 1))
|
||||
|
||||
//
|
||||
// Checks if 1st argument is aligned on given power of 2 boundary specified
|
||||
// by 2nd argument
|
||||
//
|
||||
#define EXP_IS_PTR_ALIGNED_ON_BOUNDARY(_pointer, _alignment) \
|
||||
((((ULONG_PTR) (_pointer)) & ((_alignment) - 1)) == 0)
|
||||
|
||||
|
||||
//
|
||||
// This macro takes a size and rounds it down to a multiple of the alignemnt.
|
||||
// Alignment doesn't need to be a power of 2.
|
||||
//
|
||||
#define EXP_ALIGN_DOWN_ON_BOUNDARY(_size, _alignment) \
|
||||
((_size) - ((_size) % _alignment))
|
||||
|
||||
//
|
||||
// Define the max data size the bugcheck callback can write. Per callback the
|
||||
// total size is around 16K on 32bit OS (32K on 64bit OS).
|
||||
//
|
||||
#ifdef _WIN64
|
||||
#define FX_MAX_DUMP_SIZE (32*1024)
|
||||
#else
|
||||
#define FX_MAX_DUMP_SIZE (16*1024)
|
||||
#endif
|
||||
|
||||
//
|
||||
// Maximum number of CPUs supported by the driver tracker.
|
||||
//
|
||||
#define FX_DRIVER_TRACKER_MAX_CPUS 256 // Max Win7 processors.
|
||||
|
||||
//
|
||||
// The initial/increment size of the array to hold driver info.
|
||||
//
|
||||
#define FX_DUMP_DRIVER_INFO_INCREMENT 10 // # entries.
|
||||
|
||||
//
|
||||
// The max size of the array to hold the driver info. This is the max data
|
||||
// we can write into the minidump.
|
||||
//
|
||||
#define FX_MAX_DUMP_DRIVER_INFO_COUNT \
|
||||
(FX_MAX_DUMP_SIZE/sizeof(FX_DUMP_DRIVER_INFO_ENTRY))
|
||||
|
||||
//
|
||||
// During run-time we store info about the loaded drivers in an array
|
||||
// of FX_DUMP_DRIVER_INFO_ENTRY struct entries, on a crash we write the
|
||||
// entire array in the minidump for postmortem analysis.
|
||||
//
|
||||
typedef struct _FX_DUMP_DRIVER_INFO_ENTRY {
|
||||
PFX_DRIVER_GLOBALS FxDriverGlobals;
|
||||
WDF_VERSION Version;
|
||||
CHAR DriverName[WDF_DRIVER_GLOBALS_NAME_LEN];
|
||||
} FX_DUMP_DRIVER_INFO_ENTRY, *PFX_DUMP_DRIVER_INFO_ENTRY;
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
||||
#endif // __FXBUGCHECK_H__
|
161
sdk/lib/drivers/wdf/kmdf/inc/private/fxcommonbuffer.hpp
Normal file
161
sdk/lib/drivers/wdf/kmdf/inc/private/fxcommonbuffer.hpp
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxCommonBuffer.hpp
|
||||
|
||||
Abstract:
|
||||
|
||||
WDF CommonBuffer Object support
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only.
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _FXCOMMONBUFFER_H_
|
||||
#define _FXCOMMONBUFFER_H_
|
||||
|
||||
//
|
||||
// Calculate an "aligned" address (Logical or Virtual) per
|
||||
// a specific alignment value.
|
||||
//
|
||||
FORCEINLINE
|
||||
PVOID
|
||||
FX_ALIGN_VIRTUAL_ADDRESS(
|
||||
__in PVOID VA,
|
||||
__in size_t AlignTo
|
||||
)
|
||||
{
|
||||
return (PVOID)(((ULONG_PTR)VA + AlignTo) & ~AlignTo);
|
||||
}
|
||||
|
||||
FORCEINLINE
|
||||
ULONGLONG
|
||||
FX_ALIGN_LOGICAL_ADDRESS(
|
||||
__in PHYSICAL_ADDRESS LA,
|
||||
__in size_t AlignTo
|
||||
)
|
||||
{
|
||||
return (LA.QuadPart + AlignTo) & ~((ULONGLONG)AlignTo);
|
||||
}
|
||||
|
||||
//
|
||||
// Declare the FxCommonBuffer class
|
||||
//
|
||||
class FxCommonBuffer : public FxNonPagedObject {
|
||||
|
||||
public:
|
||||
|
||||
FxCommonBuffer(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in FxDmaEnabler * pDmaEnabler
|
||||
);
|
||||
|
||||
virtual
|
||||
BOOLEAN
|
||||
Dispose(
|
||||
VOID
|
||||
);
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
AllocateCommonBuffer(
|
||||
__in size_t Length
|
||||
);
|
||||
|
||||
VOID
|
||||
FreeCommonBuffer(
|
||||
VOID
|
||||
);
|
||||
|
||||
__forceinline
|
||||
PHYSICAL_ADDRESS
|
||||
GetAlignedLogicalAddress(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_BufferAlignedLA;
|
||||
}
|
||||
|
||||
__forceinline
|
||||
PVOID
|
||||
GetAlignedVirtualAddress(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_BufferAlignedVA;
|
||||
}
|
||||
|
||||
__forceinline
|
||||
size_t
|
||||
GetLength(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_Length;
|
||||
}
|
||||
|
||||
__forceinline
|
||||
VOID
|
||||
SetAlignment(
|
||||
__in ULONG Alignment
|
||||
)
|
||||
{
|
||||
m_Alignment = Alignment;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
//
|
||||
// Unaligned virtual address
|
||||
//
|
||||
PVOID m_BufferRawVA;
|
||||
|
||||
//
|
||||
// Aligned virtual address
|
||||
//
|
||||
PVOID m_BufferAlignedVA;
|
||||
|
||||
//
|
||||
// Aligned logical address
|
||||
//
|
||||
PHYSICAL_ADDRESS m_BufferAlignedLA;
|
||||
|
||||
//
|
||||
// Unaligned logical address
|
||||
//
|
||||
PHYSICAL_ADDRESS m_BufferRawLA;
|
||||
|
||||
//
|
||||
// Pointer to the DMA enabler
|
||||
//
|
||||
FxDmaEnabler * m_DmaEnabler;
|
||||
|
||||
//
|
||||
// Length specified by the caller
|
||||
//
|
||||
size_t m_Length;
|
||||
|
||||
//
|
||||
// Actual length used to allocate buffer after adding the alignement
|
||||
// value.
|
||||
//
|
||||
size_t m_RawLength;
|
||||
|
||||
//
|
||||
// Alignment of the allocated buffer.
|
||||
//
|
||||
size_t m_Alignment;
|
||||
|
||||
};
|
||||
|
||||
#endif // _FXCOMMONBUFFER_H_
|
1559
sdk/lib/drivers/wdf/kmdf/inc/private/fxdmatransaction.hpp
Normal file
1559
sdk/lib/drivers/wdf/kmdf/inc/private/fxdmatransaction.hpp
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,168 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxDmaTransactionCallbacks.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the FxDmaTransaction object callbacks
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _FXDMATRANSACTIONCALLBACKS_H
|
||||
#define _FXDMATRANSACTIONCALLBACKS_H
|
||||
|
||||
//
|
||||
// FxDmaTransactionProgramDma or FxDmaTransactionReserveDma callback delegate
|
||||
// These are mutually exclusive callbacks and are packed together in
|
||||
// the callback structure (C++ won't allow two classes with constructors
|
||||
// to be together in a union, so the containing class can't do the
|
||||
// packing)
|
||||
//
|
||||
class FxDmaTransactionProgramOrReserveDma : public FxCallback {
|
||||
|
||||
public:
|
||||
union {
|
||||
PFN_WDF_PROGRAM_DMA ProgramDma;
|
||||
PFN_WDF_RESERVE_DMA ReserveDma;
|
||||
} Method;
|
||||
|
||||
FxDmaTransactionProgramOrReserveDma(
|
||||
VOID
|
||||
) :
|
||||
FxCallback()
|
||||
{
|
||||
Method.ProgramDma = NULL;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
InvokeProgramDma(
|
||||
__in WDFDMATRANSACTION Transaction,
|
||||
__in WDFDEVICE Device,
|
||||
__in PVOID Context,
|
||||
__in WDF_DMA_DIRECTION Direction,
|
||||
__in PSCATTER_GATHER_LIST SgList
|
||||
)
|
||||
{
|
||||
if (Method.ProgramDma) {
|
||||
BOOLEAN cc;
|
||||
|
||||
CallbackStart();
|
||||
cc = Method.ProgramDma( Transaction,
|
||||
Device,
|
||||
Context,
|
||||
Direction,
|
||||
SgList );
|
||||
CallbackEnd();
|
||||
|
||||
return cc;
|
||||
}
|
||||
else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
InvokeReserveDma(
|
||||
__in WDFDMATRANSACTION Transaction,
|
||||
__in PVOID Context
|
||||
)
|
||||
{
|
||||
if (Method.ReserveDma) {
|
||||
CallbackStart();
|
||||
Method.ReserveDma( Transaction, Context );
|
||||
CallbackEnd();
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
Clear(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
Method.ProgramDma = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// FxDmaTransactionConfigureChannel callback delegate
|
||||
//
|
||||
|
||||
class FxDmaTransactionConfigureChannel : public FxCallback {
|
||||
|
||||
public:
|
||||
PFN_WDF_DMA_TRANSACTION_CONFIGURE_DMA_CHANNEL Method;
|
||||
|
||||
FxDmaTransactionConfigureChannel(
|
||||
VOID
|
||||
) :
|
||||
FxCallback()
|
||||
{
|
||||
Method = NULL;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
BOOLEAN
|
||||
Invoke(
|
||||
__in WDFDMATRANSACTION DmaTransaction,
|
||||
__in WDFDEVICE Device,
|
||||
__in PVOID Context,
|
||||
__in_opt PMDL Mdl,
|
||||
__in size_t Offset,
|
||||
__in size_t Length
|
||||
)
|
||||
{
|
||||
BOOLEAN b = TRUE;
|
||||
if (Method) {
|
||||
CallbackStart();
|
||||
b = Method( DmaTransaction, Device, Context, Mdl, Offset, Length );
|
||||
CallbackEnd();
|
||||
}
|
||||
return b;
|
||||
}
|
||||
};
|
||||
|
||||
//
|
||||
// FxDmaTransactionTransferComplete callback delegate
|
||||
//
|
||||
|
||||
class FxDmaTransactionTransferComplete : public FxCallback {
|
||||
|
||||
public:
|
||||
PFN_WDF_DMA_TRANSACTION_DMA_TRANSFER_COMPLETE Method;
|
||||
|
||||
FxDmaTransactionTransferComplete(
|
||||
VOID
|
||||
) :
|
||||
FxCallback()
|
||||
{
|
||||
Method = NULL;
|
||||
}
|
||||
|
||||
VOID
|
||||
Invoke(
|
||||
__in WDFDMATRANSACTION Transaction,
|
||||
__in WDFDEVICE Device,
|
||||
__in WDFCONTEXT Context,
|
||||
__in WDF_DMA_DIRECTION Direction,
|
||||
__in DMA_COMPLETION_STATUS Status
|
||||
)
|
||||
{
|
||||
if (Method) {
|
||||
CallbackStart();
|
||||
Method( Transaction, Device, Context, Direction, Status );
|
||||
CallbackEnd();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif // _FXDMATRANSACTIONCALLBACKS_H
|
201
sdk/lib/drivers/wdf/kmdf/inc/private/fxdpc.hpp
Normal file
201
sdk/lib/drivers/wdf/kmdf/inc/private/fxdpc.hpp
Normal file
|
@ -0,0 +1,201 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxDpc.hpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements a frameworks managed DPC that
|
||||
can synchrononize with driver frameworks object locks.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef _FXDPC_H_
|
||||
#define _FXDPC_H_
|
||||
|
||||
//
|
||||
// Driver Frameworks DPC Design:
|
||||
//
|
||||
// The driver frameworks provides an optional DPC wrapper object that allows
|
||||
// the creation of a reference counted DPC object that can synchronize
|
||||
// automatically with certain frameworks objects.
|
||||
//
|
||||
// This provides automatic synchronization between the DPC's execution, and the
|
||||
// frameworks objects' event callbacks into the device driver.
|
||||
//
|
||||
// The WDFDPC object is designed to be re-useable, in which it can be re-linked
|
||||
// into the DPC queue after firing.
|
||||
//
|
||||
// In many cases, the KDPC struct is embedded inside another structure that
|
||||
// represents a device command block. These device command blocks are typically
|
||||
// submitted to another device driver. So the calling driver, which is utilizing
|
||||
// the driver frameworks would not likely have an opportunity to make
|
||||
// changes to this. In order to support this, the caller can optionally supply
|
||||
// a DPC object pointer to Initialize, and the WDFDPC object will use this
|
||||
// embedded user supplied DPC object, and pass its address as the RawDpc
|
||||
// parameter to the callback function.
|
||||
//
|
||||
// If the user does not supply a DPC pointer by passing NULL, then the
|
||||
// internal DPC object is used, and RawDPC is NULL.
|
||||
//
|
||||
// Calling GetDpcPtr returns the DPC to be used, and could be
|
||||
// the caller supplied DPC, or the embedded one depending on
|
||||
// whether the caller supplied a user DPC pointer to Initialize.
|
||||
//
|
||||
// The GetDpcPtr allows linking of the WDFDPC object into various DPC
|
||||
// lists by the driver.
|
||||
//
|
||||
|
||||
class FxDpc : public FxNonPagedObject {
|
||||
|
||||
private:
|
||||
|
||||
KDPC m_Dpc;
|
||||
|
||||
//
|
||||
// This is the Framework object who is associated with the DPC
|
||||
// if supplied
|
||||
//
|
||||
FxObject* m_Object;
|
||||
|
||||
//
|
||||
// This is the callback lock for the object this DPC will
|
||||
// synchronize with
|
||||
//
|
||||
FxCallbackLock* m_CallbackLock;
|
||||
|
||||
//
|
||||
// This is the object whose reference count actually controls
|
||||
// the lifetime of the m_CallbackLock
|
||||
//
|
||||
FxObject* m_CallbackLockObject;
|
||||
|
||||
//
|
||||
// This is the user supplied callback function
|
||||
//
|
||||
PFN_WDF_DPC m_Callback;
|
||||
|
||||
// Ensures only one of either Delete or Cleanup runs down the object
|
||||
BOOLEAN m_RunningDown;
|
||||
|
||||
public:
|
||||
static
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
_Create(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PWDF_DPC_CONFIG Config,
|
||||
__in PWDF_OBJECT_ATTRIBUTES Attributes,
|
||||
__in FxObject* ParentObject,
|
||||
__out WDFDPC* Dpc
|
||||
);
|
||||
|
||||
FxDpc(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals
|
||||
);
|
||||
|
||||
virtual
|
||||
~FxDpc(
|
||||
VOID
|
||||
);
|
||||
|
||||
KDPC*
|
||||
GetDpcPtr(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return &m_Dpc;
|
||||
}
|
||||
|
||||
WDFOBJECT
|
||||
GetObject(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (m_Object != NULL) {
|
||||
return m_Object->GetObjectHandle();
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Initialize the DPC using either the caller supplied DPC
|
||||
struct, or if NULL, our own internal one.
|
||||
|
||||
Arguments:
|
||||
|
||||
Returns:
|
||||
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
Initialize(
|
||||
__in PWDF_OBJECT_ATTRIBUTES Attributes,
|
||||
__in PWDF_DPC_CONFIG Config,
|
||||
__in FxObject* ParentObject,
|
||||
__out WDFDPC* Dpc
|
||||
);
|
||||
|
||||
virtual
|
||||
BOOLEAN
|
||||
Dispose(
|
||||
VOID
|
||||
);
|
||||
|
||||
BOOLEAN
|
||||
Cancel(
|
||||
__in BOOLEAN Wait
|
||||
);
|
||||
|
||||
VOID
|
||||
DpcHandler(
|
||||
__in PKDPC Dpc,
|
||||
__in PVOID SystemArgument1,
|
||||
__in PVOID SystemArgument2
|
||||
);
|
||||
|
||||
private:
|
||||
|
||||
//
|
||||
// Called from Dispose, or cleanup list to perform final flushing of any
|
||||
// outstanding DPC's and dereferencing of objects.
|
||||
//
|
||||
VOID
|
||||
FlushAndRundown(
|
||||
);
|
||||
|
||||
static
|
||||
KDEFERRED_ROUTINE
|
||||
FxDpcThunk;
|
||||
|
||||
static
|
||||
VOID
|
||||
WorkItemThunk(
|
||||
PDEVICE_OBJECT DeviceObject,
|
||||
PVOID Context
|
||||
);
|
||||
};
|
||||
|
||||
#endif // _FXDPC_H_
|
||||
|
6943
sdk/lib/drivers/wdf/kmdf/inc/private/fxdynamics.h
Normal file
6943
sdk/lib/drivers/wdf/kmdf/inc/private/fxdynamics.h
Normal file
File diff suppressed because it is too large
Load diff
18
sdk/lib/drivers/wdf/kmdf/inc/private/fxdynamicswrapper.h
Normal file
18
sdk/lib/drivers/wdf/kmdf/inc/private/fxdynamicswrapper.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
//
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
//
|
||||
//
|
||||
// Since #include'ing FxDymamics.h requires a bunch of headers before it, we
|
||||
// do this in one place because multiple spots in the code include this header.
|
||||
//
|
||||
|
||||
extern "C" {
|
||||
#pragma warning(disable:4200) // zero-sized array in struct/union
|
||||
#include <usbdrivr.h>
|
||||
#pragma warning(default:4200)
|
||||
|
||||
#include <wdfusb.h>
|
||||
#include <wdfminiport.h>
|
||||
#include "FxDynamics.h"
|
||||
#include "VfFxDynamics.h"
|
||||
}
|
87
sdk/lib/drivers/wdf/kmdf/inc/private/fxlibrarycommon.h
Normal file
87
sdk/lib/drivers/wdf/kmdf/inc/private/fxlibrarycommon.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
//
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
//
|
||||
#ifndef __FX_LIBRARY_COMMON_H__
|
||||
#define __FX_LIBRARY_COMMON_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
extern ULONG WdfLdrDbgPrintOn;
|
||||
extern PCHAR WdfLdrType;
|
||||
|
||||
extern WDFVERSION WdfVersion;
|
||||
|
||||
extern RTL_OSVERSIONINFOW gOsVersion;
|
||||
|
||||
#define _LIT_(a) # a
|
||||
#define LITERAL(a) _LIT_(a)
|
||||
|
||||
#define __PrintUnfiltered(...) \
|
||||
DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, __VA_ARGS__);
|
||||
|
||||
#define __Print(_x_) \
|
||||
{ \
|
||||
if (WdfLdrDbgPrintOn) { \
|
||||
DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL, "%s: ", WdfLdrType); \
|
||||
__PrintUnfiltered _x_ \
|
||||
} \
|
||||
}
|
||||
|
||||
#define WDF_ENHANCED_VERIFIER_OPTIONS_VALUE_NAME L"EnhancedVerifierOptions"
|
||||
|
||||
typedef
|
||||
NTSTATUS
|
||||
(*PFN_RTL_GET_VERSION)(
|
||||
__out PRTL_OSVERSIONINFOW VersionInformation
|
||||
);
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxLibraryCommonCommission(
|
||||
VOID
|
||||
);
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxLibraryCommonDecommission(
|
||||
VOID
|
||||
);
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxLibraryCommonRegisterClient(
|
||||
__inout PWDF_BIND_INFO Info,
|
||||
__deref_out PWDF_DRIVER_GLOBALS * WdfDriverGlobals,
|
||||
__in_opt PCLIENT_INFO ClientInfo
|
||||
);
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxLibraryCommonUnregisterClient(
|
||||
__in PWDF_BIND_INFO Info,
|
||||
__in PWDF_DRIVER_GLOBALS WdfDriverGlobals
|
||||
);
|
||||
|
||||
VOID
|
||||
GetEnhancedVerifierOptions(
|
||||
__in PCLIENT_INFO ClientInfo,
|
||||
__out PULONG Options
|
||||
);
|
||||
|
||||
VOID
|
||||
LibraryLogEvent(
|
||||
__in PDRIVER_OBJECT DriverObject,
|
||||
__in NTSTATUS ErrorCode,
|
||||
__in NTSTATUS FinalStatus,
|
||||
__in PWSTR ErrorInsertionString,
|
||||
__in_bcount(RawDataLen) PVOID RawDataBuf,
|
||||
__in USHORT RawDataLen
|
||||
);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif // __cplusplus
|
||||
|
||||
#endif // __FX_LIBRARY_COMMON_H__
|
38
sdk/lib/drivers/wdf/kmdf/inc/private/fxprobeandlock.h
Normal file
38
sdk/lib/drivers/wdf/kmdf/inc/private/fxprobeandlock.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
//
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
//
|
||||
#ifndef __FXPROBEANDLOCK_H__
|
||||
#define __FXPROBEANDLOCK_H__
|
||||
|
||||
extern "C" {
|
||||
|
||||
//
|
||||
// These are defined in a C file in src\support\ProbeAndLock.c
|
||||
// to avoid C++ exception handling issues.
|
||||
//
|
||||
// They do not raise the exception beyond the C function, but
|
||||
// translate it into an NTSTATUS before returning.
|
||||
//
|
||||
|
||||
NTSTATUS
|
||||
FxProbeAndLockForRead(
|
||||
__in PMDL Mdl,
|
||||
__in KPROCESSOR_MODE AccessMode
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
FxProbeAndLockForWrite(
|
||||
__in PMDL Mdl,
|
||||
__in KPROCESSOR_MODE AccessMode
|
||||
);
|
||||
|
||||
NTSTATUS
|
||||
FxProbeAndLockWithAccess(
|
||||
__in PMDL Mdl,
|
||||
__in KPROCESSOR_MODE AccessMode,
|
||||
__in LOCK_OPERATION Operation
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
#endif __FXPROBEANDLOCK_H__
|
161
sdk/lib/drivers/wdf/kmdf/inc/private/ifxmemory.hpp
Normal file
161
sdk/lib/drivers/wdf/kmdf/inc/private/ifxmemory.hpp
Normal file
|
@ -0,0 +1,161 @@
|
|||
//
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
//
|
||||
/*++
|
||||
|
||||
Module Name:
|
||||
|
||||
IFxMemory.hpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Abstract base class for a memory object. It is necessary to split the
|
||||
memory interface away from an FxObject derived base class so that we can
|
||||
hand out WDFMEMORY handles that are embedded within other FxObject derived
|
||||
classes without having to embed another FxObject derived class within the
|
||||
parent.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef __IFX_MEMORY_HPP__
|
||||
#define __IFX_MEMORY_HPP__
|
||||
|
||||
// begin_wpp enum
|
||||
enum IFxMemoryFlags {
|
||||
IFxMemoryFlagReadOnly = 0x0001,
|
||||
};
|
||||
// end_wpp
|
||||
|
||||
|
||||
class IFxMemory {
|
||||
public:
|
||||
virtual
|
||||
PVOID
|
||||
GetBuffer(
|
||||
VOID
|
||||
) =0;
|
||||
|
||||
virtual
|
||||
size_t
|
||||
GetBufferSize(
|
||||
VOID
|
||||
) =0;
|
||||
|
||||
virtual
|
||||
PMDL
|
||||
GetMdl(
|
||||
VOID
|
||||
) =0;
|
||||
|
||||
virtual
|
||||
WDFMEMORY
|
||||
GetHandle(
|
||||
VOID
|
||||
) =0;
|
||||
|
||||
//
|
||||
// Value returned is a bit field from the enum IFxMemoryFlags
|
||||
//
|
||||
virtual
|
||||
USHORT
|
||||
GetFlags(
|
||||
VOID
|
||||
) =0;
|
||||
|
||||
virtual
|
||||
PFX_DRIVER_GLOBALS
|
||||
GetDriverGlobals(
|
||||
VOID
|
||||
) =0;
|
||||
|
||||
virtual
|
||||
ULONG
|
||||
AddRef(
|
||||
__in PVOID Tag,
|
||||
__in LONG Line,
|
||||
__in_opt PSTR File
|
||||
) =0;
|
||||
|
||||
virtual
|
||||
ULONG
|
||||
Release(
|
||||
__in PVOID Tag,
|
||||
__in LONG Line,
|
||||
__in_opt PSTR File
|
||||
) =0;
|
||||
|
||||
virtual
|
||||
VOID
|
||||
Delete(
|
||||
VOID
|
||||
) =0;
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
ValidateMemoryOffsets(
|
||||
__in_opt PWDFMEMORY_OFFSET Offsets
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
size_t total;
|
||||
|
||||
if (Offsets == NULL) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
status = RtlSizeTAdd(Offsets->BufferLength, Offsets->BufferOffset, &total);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (total > GetBufferSize()) {
|
||||
return STATUS_INTEGER_OVERFLOW;
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
CopyFromPtr(
|
||||
__in_opt PWDFMEMORY_OFFSET DestinationOffsets,
|
||||
__in_bcount(SourceBufferLength) PVOID SourceBuffer,
|
||||
__in size_t SourceBufferLength,
|
||||
__in_opt PWDFMEMORY_OFFSET SourceOffsets
|
||||
);
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
CopyToPtr(
|
||||
__in_opt PWDFMEMORY_OFFSET SourceOffsets,
|
||||
__out_bcount(DestinationBufferLength) PVOID DestinationBuffer,
|
||||
__in size_t DestinationBufferLength,
|
||||
__in_opt PWDFMEMORY_OFFSET DestinationOffsets
|
||||
);
|
||||
|
||||
protected:
|
||||
static
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
_CopyPtrToPtr(
|
||||
__in_bcount(SourceBufferLength) PVOID SourceBuffer,
|
||||
__in size_t SourceBufferLength,
|
||||
__in_opt PWDFMEMORY_OFFSET SourceOffsets,
|
||||
__out_bcount(DestinationBufferLength) PVOID DestinationBuffer,
|
||||
__in size_t DestinationBufferLength,
|
||||
__in_opt PWDFMEMORY_OFFSET DestinationOffsets
|
||||
);
|
||||
};
|
||||
|
||||
#endif // __IFX_MEMORY_HPP__
|
6484
sdk/lib/drivers/wdf/kmdf/inc/private/vffxdynamics.h
Normal file
6484
sdk/lib/drivers/wdf/kmdf/inc/private/vffxdynamics.h
Normal file
File diff suppressed because it is too large
Load diff
2173
sdk/lib/drivers/wdf/kmdf/inc/private/wdf10.h
Normal file
2173
sdk/lib/drivers/wdf/kmdf/inc/private/wdf10.h
Normal file
File diff suppressed because it is too large
Load diff
2203
sdk/lib/drivers/wdf/kmdf/inc/private/wdf11.h
Normal file
2203
sdk/lib/drivers/wdf/kmdf/inc/private/wdf11.h
Normal file
File diff suppressed because it is too large
Load diff
2896
sdk/lib/drivers/wdf/kmdf/inc/private/wdf111.h
Normal file
2896
sdk/lib/drivers/wdf/kmdf/inc/private/wdf111.h
Normal file
File diff suppressed because it is too large
Load diff
3064
sdk/lib/drivers/wdf/kmdf/inc/private/wdf113.h
Normal file
3064
sdk/lib/drivers/wdf/kmdf/inc/private/wdf113.h
Normal file
File diff suppressed because it is too large
Load diff
3079
sdk/lib/drivers/wdf/kmdf/inc/private/wdf115.h
Normal file
3079
sdk/lib/drivers/wdf/kmdf/inc/private/wdf115.h
Normal file
File diff suppressed because it is too large
Load diff
2209
sdk/lib/drivers/wdf/kmdf/inc/private/wdf15.h
Normal file
2209
sdk/lib/drivers/wdf/kmdf/inc/private/wdf15.h
Normal file
File diff suppressed because it is too large
Load diff
2228
sdk/lib/drivers/wdf/kmdf/inc/private/wdf17.h
Normal file
2228
sdk/lib/drivers/wdf/kmdf/inc/private/wdf17.h
Normal file
File diff suppressed because it is too large
Load diff
2410
sdk/lib/drivers/wdf/kmdf/inc/private/wdf19.h
Normal file
2410
sdk/lib/drivers/wdf/kmdf/inc/private/wdf19.h
Normal file
File diff suppressed because it is too large
Load diff
32
sdk/lib/drivers/wdf/kmdf/src/core/corepriv.hpp
Normal file
32
sdk/lib/drivers/wdf/kmdf/src/core/corepriv.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
corepriv.hpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Main driver framework private header.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
extern "C" {
|
||||
#include <ntddk.h>
|
||||
#include "wdf.h"
|
||||
}
|
||||
|
||||
#define WDF_REGISTRY_BASE_PATH L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Wdf"
|
||||
|
1219
sdk/lib/drivers/wdf/kmdf/src/core/fxbugcheckcallback.cpp
Normal file
1219
sdk/lib/drivers/wdf/kmdf/src/core/fxbugcheckcallback.cpp
Normal file
File diff suppressed because it is too large
Load diff
3268
sdk/lib/drivers/wdf/kmdf/src/core/fxchildlist.cpp
Normal file
3268
sdk/lib/drivers/wdf/kmdf/src/core/fxchildlist.cpp
Normal file
File diff suppressed because it is too large
Load diff
804
sdk/lib/drivers/wdf/kmdf/src/core/fxchildlistapi.cpp
Normal file
804
sdk/lib/drivers/wdf/kmdf/src/core/fxchildlistapi.cpp
Normal file
|
@ -0,0 +1,804 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
FxChildListApi.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module exposes the "C" interface to the FxChildList object.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxcorepch.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxChildListAPI.tmh"
|
||||
}
|
||||
|
||||
//
|
||||
// extern "C" the entire file
|
||||
//
|
||||
extern "C" {
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfChildListCreate)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Device,
|
||||
__in
|
||||
PWDF_CHILD_LIST_CONFIG Config,
|
||||
__in_opt
|
||||
PWDF_OBJECT_ATTRIBUTES DeviceListAttributes,
|
||||
__out
|
||||
WDFCHILDLIST* DeviceList
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxDevice* pDevice;
|
||||
FxChildList* pList;
|
||||
size_t totalDescriptionSize = 0;
|
||||
NTSTATUS status;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
FX_TYPE_DEVICE,
|
||||
(PVOID*)&pDevice,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Enter, WDFDEVICE %p", Device);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, Config);
|
||||
FxPointerNotNull(pFxDriverGlobals, DeviceList);
|
||||
|
||||
*DeviceList = NULL;
|
||||
|
||||
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = FxChildList::_ValidateConfig(pFxDriverGlobals,
|
||||
Config,
|
||||
&totalDescriptionSize);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"WDFDEVICE 0x%p Config is invalid", Device);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = FxValidateObjectAttributes(pFxDriverGlobals,
|
||||
DeviceListAttributes,
|
||||
FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = pDevice->AllocateEnumInfo();
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = FxChildList::_CreateAndInit(&pList,
|
||||
pFxDriverGlobals,
|
||||
DeviceListAttributes,
|
||||
totalDescriptionSize,
|
||||
pDevice,
|
||||
Config);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = pList->Commit(DeviceListAttributes,
|
||||
(WDFOBJECT*)DeviceList,
|
||||
pDevice);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Could not convert object to handle, %!STATUS!",
|
||||
status);
|
||||
pList->DeleteFromFailedCreate();
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
pDevice->SetDeviceTelemetryInfoFlags(DeviceInfoHasDynamicChildren);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFDEVICE
|
||||
WDFEXPORT(WdfChildListGetDevice)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCHILDLIST DeviceList
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxChildList* pList;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DeviceList,
|
||||
FX_TYPE_CHILD_LIST,
|
||||
(PVOID*)&pList,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Enter: WDFCHILDLIST %p", DeviceList);
|
||||
|
||||
return pList->GetDevice();
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfChildListRetrieveAddressDescription)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCHILDLIST DeviceList,
|
||||
__in
|
||||
PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription,
|
||||
__inout
|
||||
PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER AddressDescription
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxChildList* pList;
|
||||
NTSTATUS status;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DeviceList,
|
||||
FX_TYPE_CHILD_LIST,
|
||||
(PVOID*)&pList,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Enter: WDFCHILDLIST %p", DeviceList);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, IdentificationDescription);
|
||||
FxPointerNotNull(pFxDriverGlobals, AddressDescription);
|
||||
|
||||
if (pList->GetIdentificationDescriptionSize() !=
|
||||
IdentificationDescription->IdentificationDescriptionSize) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"identification description size %d incorrect, expected %d, %!STATUS!",
|
||||
IdentificationDescription->IdentificationDescriptionSize,
|
||||
pList->GetIdentificationDescriptionSize(), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if (pList->HasAddressDescriptions() == FALSE) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"cannot retrieve an address description from a list"
|
||||
" which was not initialized to use them, %!STATUS!",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if (pList->GetAddressDescriptionSize() !=
|
||||
AddressDescription->AddressDescriptionSize) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"description size %d incorrect, expected %d, %!STATUS!",
|
||||
AddressDescription->AddressDescriptionSize,
|
||||
pList->GetAddressDescriptionSize(), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
status = pList->GetAddressDescription(IdentificationDescription,
|
||||
AddressDescription);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Exit: WDFCHILDLIST %p, %!STATUS!",
|
||||
DeviceList, status);
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
VOID
|
||||
WDFEXPORT(WdfChildListBeginScan)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCHILDLIST DeviceList
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxChildList* pList;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DeviceList,
|
||||
FX_TYPE_CHILD_LIST,
|
||||
(PVOID*)&pList,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Enter: WDFCHILDLIST %p", DeviceList);
|
||||
|
||||
pList->BeginScan();
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
VOID
|
||||
WDFEXPORT(WdfChildListEndScan)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCHILDLIST DeviceList
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxChildList* pList;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DeviceList,
|
||||
FX_TYPE_CHILD_LIST,
|
||||
(PVOID*)&pList,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Enter: WDFCHILDLIST %p", DeviceList);
|
||||
|
||||
pList->EndScan();
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
VOID
|
||||
WDFEXPORT(WdfChildListBeginIteration)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCHILDLIST DeviceList,
|
||||
__in
|
||||
PWDF_CHILD_LIST_ITERATOR Iterator
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxChildList* pList;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DeviceList,
|
||||
FX_TYPE_CHILD_LIST,
|
||||
(PVOID*)&pList,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Enter: WDFCHILDLIST %p", DeviceList);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, Iterator);
|
||||
|
||||
if (Iterator->Size != sizeof(WDF_CHILD_LIST_ITERATOR)) {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Iterator Size %d not correct, expected %d, %!STATUS!",
|
||||
Iterator->Size, sizeof(WDF_CHILD_LIST_ITERATOR),
|
||||
STATUS_INFO_LENGTH_MISMATCH);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((Iterator->Flags & ~WdfRetrieveAllChildren) != 0) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Iterator Flags 0x%x not correct, valid mask 0x%x, %!STATUS!",
|
||||
Iterator->Flags, WdfRetrieveAllChildren, STATUS_INVALID_PARAMETER);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return;
|
||||
}
|
||||
|
||||
RtlZeroMemory(&Iterator->Reserved[0], sizeof(Iterator->Reserved));
|
||||
|
||||
pList->BeginIteration(Iterator);
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfChildListRetrieveNextDevice)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCHILDLIST DeviceList,
|
||||
__in
|
||||
PWDF_CHILD_LIST_ITERATOR Iterator,
|
||||
__out
|
||||
WDFDEVICE* Device,
|
||||
__inout_opt
|
||||
PWDF_CHILD_RETRIEVE_INFO Info
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxChildList* pList;
|
||||
NTSTATUS status;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DeviceList,
|
||||
FX_TYPE_CHILD_LIST,
|
||||
(PVOID*)&pList,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, Iterator);
|
||||
FxPointerNotNull(pFxDriverGlobals, Device);
|
||||
|
||||
*Device = NULL;
|
||||
|
||||
if (Iterator->Size != sizeof(WDF_CHILD_LIST_ITERATOR)) {
|
||||
status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Iterator Size %d not correct, expected %d, %!STATUS!",
|
||||
Iterator->Size, sizeof(WDF_CHILD_LIST_ITERATOR), status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((Iterator->Flags & ~WdfRetrieveAllChildren) != 0) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Iterator Flags 0x%x not correct, valid mask 0x%x, %!STATUS!",
|
||||
Iterator->Flags, WdfRetrieveAllChildren, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (Info != NULL) {
|
||||
if (Info->Size != sizeof(WDF_CHILD_RETRIEVE_INFO)) {
|
||||
status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Invalid RetrieveInfo Size %d, expected %d, %!STATUS!",
|
||||
Info->Size, sizeof(WDF_CHILD_RETRIEVE_INFO), status);
|
||||
return status;
|
||||
}
|
||||
if (Info->IdentificationDescription != NULL
|
||||
&&
|
||||
pList->GetIdentificationDescriptionSize() !=
|
||||
Info->IdentificationDescription->IdentificationDescriptionSize) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"identification description size %d incorrect, expected %d"
|
||||
"%!STATUS!",
|
||||
Info->IdentificationDescription->IdentificationDescriptionSize,
|
||||
pList->GetIdentificationDescriptionSize(), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if (Info->AddressDescription != NULL) {
|
||||
if (pList->HasAddressDescriptions() == FALSE) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"cannot retrieve an address description from a list"
|
||||
" which was not initialized to use them, %!STATUS!",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
else if (pList->GetAddressDescriptionSize() !=
|
||||
Info->AddressDescription->AddressDescriptionSize) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"address description size %d incorrect, expected %d, %!STATUS!",
|
||||
Info->AddressDescription->AddressDescriptionSize,
|
||||
pList->GetAddressDescriptionSize(), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pList->GetNextDevice(Device, Iterator, Info);
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
VOID
|
||||
WDFEXPORT(WdfChildListEndIteration)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCHILDLIST DeviceList,
|
||||
__in
|
||||
PWDF_CHILD_LIST_ITERATOR Iterator
|
||||
)
|
||||
{
|
||||
FxChildList* pList;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DeviceList,
|
||||
FX_TYPE_CHILD_LIST,
|
||||
(PVOID*)&pList,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Enter: WDFCHILDLIST %p", DeviceList);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, Iterator);
|
||||
|
||||
if (Iterator->Size != sizeof(WDF_CHILD_LIST_ITERATOR)) {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Iterator Size %d not correct, expected %d, %!STATUS!",
|
||||
Iterator->Size, sizeof(WDF_CHILD_LIST_ITERATOR),
|
||||
STATUS_INFO_LENGTH_MISMATCH);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((Iterator->Flags & ~WdfRetrieveAllChildren) != 0) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Iterator Flags 0x%x not correct, valid mask 0x%x, %!STATUS!",
|
||||
Iterator->Flags, WdfRetrieveAllChildren, STATUS_INVALID_PARAMETER);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return;
|
||||
}
|
||||
|
||||
pList->EndIteration(Iterator);
|
||||
}
|
||||
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfChildListAddOrUpdateChildDescriptionAsPresent)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCHILDLIST DeviceList,
|
||||
__in
|
||||
PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription,
|
||||
__in_opt
|
||||
PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER AddressDescription
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxChildList* pList;
|
||||
NTSTATUS status;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DeviceList,
|
||||
FX_TYPE_CHILD_LIST,
|
||||
(PVOID*)&pList,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Enter: WDFCHILDLIST %p", DeviceList);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, IdentificationDescription);
|
||||
|
||||
if (AddressDescription != NULL) {
|
||||
if (pList->HasAddressDescriptions() == FALSE) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"cannot retrieve an address description from a list"
|
||||
" which was not initialized to use them, %!STATUS!", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
if (pList->GetAddressDescriptionSize() !=
|
||||
AddressDescription->AddressDescriptionSize) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"address description size %d incorrect, expected %d, %!STATUS!",
|
||||
AddressDescription->AddressDescriptionSize,
|
||||
pList->GetAddressDescriptionSize(), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (pList->HasAddressDescriptions()) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Must provide a valid AddressDescription because the"
|
||||
" WDFCHILDLIST 0x%p is configured with AddressDescriptionSize,"
|
||||
" %!STATUS!", DeviceList, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (pList->GetIdentificationDescriptionSize() !=
|
||||
IdentificationDescription->IdentificationDescriptionSize) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"identification description size %d incorrect, expected %d, %!STATUS!",
|
||||
IdentificationDescription->IdentificationDescriptionSize,
|
||||
pList->GetIdentificationDescriptionSize(), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
status = pList->Add(IdentificationDescription, AddressDescription);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Exit: WDFCHILDLIST %p, %!STATUS!", DeviceList, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfChildListUpdateChildDescriptionAsMissing)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCHILDLIST DeviceList,
|
||||
__in
|
||||
PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
NTSTATUS status;
|
||||
FxChildList* pList;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DeviceList,
|
||||
FX_TYPE_CHILD_LIST,
|
||||
(PVOID*)&pList,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, IdentificationDescription);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Enter: WDFCHILDLIST %p", DeviceList);
|
||||
|
||||
if (pList->GetIdentificationDescriptionSize() !=
|
||||
IdentificationDescription->IdentificationDescriptionSize) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"identification description size %d incorrect, expected %d, %!STATUS!",
|
||||
IdentificationDescription->IdentificationDescriptionSize,
|
||||
pList->GetIdentificationDescriptionSize(), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
status = pList->UpdateAsMissing(IdentificationDescription);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Exit: WDFCHILDLIST %p, %!STATUS!",
|
||||
DeviceList, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
VOID
|
||||
WDFEXPORT(WdfChildListUpdateAllChildDescriptionsAsPresent)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCHILDLIST DeviceList
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxChildList* pList;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DeviceList,
|
||||
FX_TYPE_CHILD_LIST,
|
||||
(PVOID*)&pList,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Enter: WDFCHILDLIST %p", DeviceList);
|
||||
|
||||
pList->UpdateAllAsPresent();
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Exit: WDFCHILDLIST %p", DeviceList);
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFDEVICE
|
||||
WDFEXPORT(WdfChildListRetrievePdo)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCHILDLIST DeviceList,
|
||||
__inout
|
||||
PWDF_CHILD_RETRIEVE_INFO RetrieveInfo
|
||||
)
|
||||
{
|
||||
FxChildList* pList;
|
||||
PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER pId;
|
||||
PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER pAddr;
|
||||
FxDevice* device;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DeviceList,
|
||||
FX_TYPE_CHILD_LIST,
|
||||
(PVOID*)&pList,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Enter: WDFCHILDLIST %p", DeviceList);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, RetrieveInfo);
|
||||
|
||||
if (RetrieveInfo->Size != sizeof(WDF_CHILD_RETRIEVE_INFO)) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Invalid RetrieveInfo Size %x, expected %d, %!STATUS!",
|
||||
RetrieveInfo->Size, sizeof(WDF_CHILD_RETRIEVE_INFO),
|
||||
STATUS_INFO_LENGTH_MISMATCH);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pId = RetrieveInfo->IdentificationDescription;
|
||||
if (pId == NULL) {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Invalid ID Description, %!STATUS!",
|
||||
STATUS_INVALID_PARAMETER);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pList->GetIdentificationDescriptionSize() !=
|
||||
pId->IdentificationDescriptionSize) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"identification description size %d incorrect, expected %d",
|
||||
pId->IdentificationDescriptionSize,
|
||||
pList->GetIdentificationDescriptionSize());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pAddr = RetrieveInfo->AddressDescription;
|
||||
if (pAddr != NULL) {
|
||||
if (pList->HasAddressDescriptions() == FALSE) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"cannot retrieve an address description from a list"
|
||||
" which was not initialized to use them, %!STATUS!",
|
||||
STATUS_INVALID_DEVICE_REQUEST);
|
||||
return NULL;
|
||||
}
|
||||
else if (pList->GetAddressDescriptionSize() != pAddr->AddressDescriptionSize) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"address description size %d incorrect, expected %d",
|
||||
pAddr->AddressDescriptionSize, pList->GetAddressDescriptionSize());
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
RetrieveInfo->Status = WdfChildListRetrieveDeviceUndefined;
|
||||
|
||||
device = pList->GetDeviceFromId(RetrieveInfo);
|
||||
|
||||
WDFDEVICE handle;
|
||||
|
||||
if (device != NULL) {
|
||||
handle = device->GetHandle();
|
||||
}
|
||||
else {
|
||||
handle = NULL;
|
||||
}
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Exit: WDFCHILDLIST %p, WDFDEVICE Pdo %p, "
|
||||
"%!WDF_CHILD_LIST_RETRIEVE_DEVICE_STATUS!",
|
||||
DeviceList, handle, RetrieveInfo->Status);
|
||||
|
||||
return handle;
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
BOOLEAN
|
||||
WDFEXPORT(WdfChildListRequestChildEject)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCHILDLIST DeviceList,
|
||||
__in
|
||||
PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription
|
||||
)
|
||||
{
|
||||
FxChildList* pList;
|
||||
FxDevice* device;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DeviceList,
|
||||
FX_TYPE_CHILD_LIST,
|
||||
(PVOID*)&pList,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"Enter: WDFCHILDLIST %p", DeviceList);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, IdentificationDescription);
|
||||
|
||||
if (pList->GetIdentificationDescriptionSize() !=
|
||||
IdentificationDescription->IdentificationDescriptionSize) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"identification description size 0x%x incorrect, expected 0x%x",
|
||||
IdentificationDescription->IdentificationDescriptionSize,
|
||||
pList->GetIdentificationDescriptionSize());
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
WDF_CHILD_RETRIEVE_INFO info;
|
||||
|
||||
WDF_CHILD_RETRIEVE_INFO_INIT(&info, IdentificationDescription);
|
||||
|
||||
device = pList->GetDeviceFromId(&info);
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_VERBOSE, TRACINGPNP,
|
||||
"found: WDFCHILDLIST %p, WDFDEVICE PDO %p",
|
||||
DeviceList, device == NULL ? NULL : device->GetHandle());
|
||||
|
||||
if (device != NULL) {
|
||||
PDEVICE_OBJECT pdo;
|
||||
|
||||
//
|
||||
// Make sure we have a valid PDO that can be ejected
|
||||
//
|
||||
pdo = device->GetSafePhysicalDevice();
|
||||
|
||||
if (pdo != NULL) {
|
||||
IoRequestDeviceEject(pdo);
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"PDO WDFDEVICE %p not reported yet to pnp, cannot eject!",
|
||||
device->GetHandle());
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
} // extern "C" of entire file
|
29
sdk/lib/drivers/wdf/kmdf/src/core/fxcorepch.hpp
Normal file
29
sdk/lib/drivers/wdf/kmdf/src/core/fxcorepch.hpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
fxcorepch.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains header definitions and include files needed by all
|
||||
modules in fx\core
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef __FX_CORE_PCH_H__
|
||||
#define __FX_CORE_PCH_H__
|
||||
|
||||
#include "corepriv.hpp"
|
||||
#include <fx.hpp>
|
||||
|
||||
#endif // __FX_CORE_PCH_H__
|
464
sdk/lib/drivers/wdf/kmdf/src/core/fxdevicefdoapi.cpp
Normal file
464
sdk/lib/drivers/wdf/kmdf/src/core/fxdevicefdoapi.cpp
Normal file
|
@ -0,0 +1,464 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxDeviceFdoApi.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module exposes the "C" interface to the FxDevice object.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxcorepch.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxDeviceFdoApi.tmh"
|
||||
}
|
||||
|
||||
//
|
||||
// Extern "C" the rest of the file
|
||||
//
|
||||
extern "C" {
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfFdoAddStaticChild)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Fdo,
|
||||
__in
|
||||
WDFDEVICE Child
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Adds a statically enumerated child to the static device list.
|
||||
|
||||
Arguments:
|
||||
Fdo - the parent of the child
|
||||
|
||||
Child - the child to add
|
||||
|
||||
Return Value:
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
FxStaticChildDescription description;
|
||||
FxDevice* pFdo;
|
||||
FxDevice* pPdo;
|
||||
FxPkgFdo* pPkgFdo;
|
||||
NTSTATUS status;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
Fdo,
|
||||
FX_TYPE_DEVICE,
|
||||
(PVOID*)&pFdo);
|
||||
|
||||
//
|
||||
// Verify type
|
||||
//
|
||||
if (pFdo->IsLegacy() || pFdo->IsFdo() == FALSE) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFdo->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"WDFDEVICE 0x%p is either legacy or is not a Fdo, %!STATUS!",
|
||||
Fdo, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
Child,
|
||||
FX_TYPE_DEVICE,
|
||||
(PVOID*)&pPdo);
|
||||
|
||||
if (pPdo->IsLegacy() || pPdo->IsPdo() == FALSE) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFdo->GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"WDFDEVICE Child 0x%p is either legacy or is not a PDO, %!STATUS!",
|
||||
Child, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
pPkgFdo = pFdo->GetFdoPkg();
|
||||
|
||||
//
|
||||
// Try to add the device to the list. We use the FxDevice* of the PDO as the
|
||||
// unique ID in the list.
|
||||
//
|
||||
description.Header.IdentificationDescriptionSize = sizeof(description);
|
||||
description.Pdo = pPdo;
|
||||
|
||||
status = pPkgFdo->m_StaticDeviceList->Add(&description.Header, NULL, NULL);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
pFdo->SetDeviceTelemetryInfoFlags(DeviceInfoHasStaticChildren);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
VOID
|
||||
WDFEXPORT(WdfFdoLockStaticChildListForIteration)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Fdo
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Locks the static child list for iteration. Any adds or removes that occur
|
||||
while the list is locked are pended until it is unlocked. Locking can
|
||||
be nested. When the unlock count is zero, the changes are evaluated.
|
||||
|
||||
Arguments:
|
||||
Fdo - the parent who owns the list of static children
|
||||
|
||||
Return Value:
|
||||
None
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
WDF_CHILD_LIST_ITERATOR iterator;
|
||||
FxDevice* pDevice;
|
||||
FxPkgFdo* pPkgFdo;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
Fdo,
|
||||
FX_TYPE_DEVICE,
|
||||
(PVOID*)&pDevice,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
//
|
||||
// Verify type
|
||||
//
|
||||
if (pDevice->IsLegacy() || (pDevice->IsFdo() == FALSE)) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Invalid WDFDEVICE %p is not an FDO", Fdo);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return;
|
||||
}
|
||||
|
||||
pPkgFdo = pDevice->GetFdoPkg();
|
||||
|
||||
//
|
||||
// Create a fake iterator to begin iteration. We will not need it in the
|
||||
// retrieve next static child call.
|
||||
//
|
||||
WDF_CHILD_LIST_ITERATOR_INIT(&iterator, WdfRetrieveAllChildren);
|
||||
|
||||
pPkgFdo->m_StaticDeviceList->BeginIteration(&iterator);
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFDEVICE
|
||||
WDFEXPORT(WdfFdoRetrieveNextStaticChild)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Fdo,
|
||||
__in
|
||||
WDFDEVICE PreviousChild,
|
||||
__in
|
||||
ULONG Flags
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Returns the next static child in the list based on the PreviousChild and
|
||||
Flags values.
|
||||
|
||||
Arguments:
|
||||
Fdo - the parent which owns the static child list
|
||||
|
||||
PreviousChild - The child returned on the last call to this DDI. If NULL,
|
||||
returns the first static child specified by the Flags criteria
|
||||
|
||||
Flags - combination of values from WDF_RETRIEVE_CHILD_FLAGS.
|
||||
WdfRetrievePresentChildren - reports children who have been reported as
|
||||
present to pnp
|
||||
WdfRetrieveMissingChildren = reports children who have been reported as
|
||||
missing to pnp
|
||||
WdfRetrievePendingChildren = reports children who have been added to the
|
||||
list, but not yet reported to pnp
|
||||
|
||||
Return Value:
|
||||
next WDFDEVICE handle representing a static child or NULL
|
||||
|
||||
--*/
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxDevice* pDevice;
|
||||
FxPkgFdo* pPkgFdo;
|
||||
WDFDEVICE next;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
Fdo,
|
||||
FX_TYPE_DEVICE,
|
||||
(PVOID*)&pDevice,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
//
|
||||
// validate Flags
|
||||
//
|
||||
if (Flags == 0 || (Flags & ~WdfRetrieveAllChildren) != 0) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Invalid Flags 0x%x", Flags);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Verify type
|
||||
//
|
||||
if (pDevice->IsLegacy() || (pDevice->IsFdo() == FALSE)) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"WDFDEVICE %p is not an FDO", Fdo);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pPkgFdo = pDevice->GetFdoPkg();
|
||||
|
||||
next = pPkgFdo->m_StaticDeviceList->GetNextStaticDevice(PreviousChild, Flags);
|
||||
|
||||
return next;
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
VOID
|
||||
WDFEXPORT(WdfFdoUnlockStaticChildListFromIteration)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Fdo
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Unlocks the static child list from iteration. Upon the last unlock, any
|
||||
pended modifications to the list will be applied.
|
||||
|
||||
Arguments:
|
||||
Fdo - the parent who owns the static child list
|
||||
|
||||
Return Value:
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
WDF_CHILD_LIST_ITERATOR iterator;
|
||||
FxDevice* pDevice;
|
||||
FxPkgFdo* pPkgFdo;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
Fdo,
|
||||
FX_TYPE_DEVICE,
|
||||
(PVOID*)&pDevice,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
//
|
||||
// Verify type
|
||||
//
|
||||
if (pDevice->IsLegacy() || (pDevice->IsFdo() == FALSE)) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"WDFDEVICE %p is not an FDO", Fdo);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Local iterator used to end iteration. WdfRetrieveAllChildren is an
|
||||
// arbitrary value.
|
||||
//
|
||||
WDF_CHILD_LIST_ITERATOR_INIT(&iterator, WdfRetrieveAllChildren);
|
||||
|
||||
pPkgFdo = pDevice->GetFdoPkg();
|
||||
pPkgFdo->m_StaticDeviceList->EndIteration(&iterator);
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfFdoQueryForInterface)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Fdo,
|
||||
__in
|
||||
LPCGUID InterfaceType,
|
||||
__out
|
||||
PINTERFACE Interface,
|
||||
__in
|
||||
USHORT Size,
|
||||
__in
|
||||
USHORT Version,
|
||||
__in_opt
|
||||
PVOID InterfaceSpecificData
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Sends a query interface pnp request to the top of the stack (which means that
|
||||
the request will travel through this device before going down the stack).
|
||||
|
||||
Arguments:
|
||||
Fdo - the device stack which is being queried
|
||||
|
||||
InterfaceType - interface type specifier
|
||||
|
||||
Interface - Interface block which will be filled in by the component which
|
||||
responds to the query interface
|
||||
|
||||
Size - size in bytes of Interfce
|
||||
|
||||
Version - version of InterfaceType being requested
|
||||
|
||||
InterfaceSpecificData - Additional data associated with Interface
|
||||
|
||||
Return Value:
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxDeviceBase* pDeviceBase;
|
||||
FxDevice* pDevice;
|
||||
FxQueryInterfaceParams params = { (PVOID*) &pDevice, FX_TYPE_DEVICE, 0 };
|
||||
NTSTATUS status;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
Fdo,
|
||||
FX_TYPE_DEVICE_BASE,
|
||||
(PVOID*)&pDeviceBase,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
pDevice = NULL;
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, InterfaceType);
|
||||
FxPointerNotNull(pFxDriverGlobals, Interface);
|
||||
|
||||
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// See if we have a full fledged WDFDEVICE or a miniport WDFDEVICE
|
||||
//
|
||||
if (NT_SUCCESS(pDeviceBase->QueryInterface(¶ms))) {
|
||||
//
|
||||
// Verify type
|
||||
//
|
||||
if (pDevice->IsLegacy() || (pDevice->IsFdo() == FALSE)) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"WDFDEVICE 0x%p Device is either legacy or is not a Fdo %!STATUS!",
|
||||
Fdo, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// miniport WDFDEVICE, nothing to check
|
||||
//
|
||||
DO_NOTHING();
|
||||
}
|
||||
|
||||
return pDeviceBase->QueryForInterface(
|
||||
InterfaceType, Interface, Size, Version, InterfaceSpecificData);
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFCHILDLIST
|
||||
WDFEXPORT(WdfFdoGetDefaultChildList)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Fdo
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Returns the default dynamic child list associated with the FDO. For a
|
||||
valid handle to be returned, the driver must have configured the default
|
||||
list in its device init phase.
|
||||
|
||||
Arguments:
|
||||
Fdo - the FDO being asked to return the handle
|
||||
|
||||
Return Value:
|
||||
a valid handle value or NULL
|
||||
|
||||
--*/
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxDevice* pDevice;
|
||||
FxPkgFdo* pPkgFdo;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
Fdo,
|
||||
FX_TYPE_DEVICE,
|
||||
(PVOID*)&pDevice,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
//
|
||||
// Verify type
|
||||
//
|
||||
if (pDevice->IsLegacy() || (pDevice->IsFdo() == FALSE)) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"WDFDEVICE %p is not an FDO", Fdo);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pPkgFdo = pDevice->GetFdoPkg();
|
||||
|
||||
if (pPkgFdo->m_DefaultDeviceList != NULL) {
|
||||
return (WDFCHILDLIST) pPkgFdo->m_DefaultDeviceList->GetObjectHandle();
|
||||
}
|
||||
else {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Default child list for FDO %p not configured, call "
|
||||
"WdfFdoInitSetDefaultChildListConfig to do so", Fdo);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
} // extern "C"
|
491
sdk/lib/drivers/wdf/kmdf/src/core/fxdevicepdoapi.cpp
Normal file
491
sdk/lib/drivers/wdf/kmdf/src/core/fxdevicepdoapi.cpp
Normal file
|
@ -0,0 +1,491 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxDevicePdoApi.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module exposes the "C" interface to the FxDevice object.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxcorepch.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxDevicePdoApi.tmh"
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
GetPdoPackageFromDeviceHandle(
|
||||
__in
|
||||
IN PFX_DRIVER_GLOBALS CallersGlobals,
|
||||
__in
|
||||
WDFDEVICE Device,
|
||||
__in
|
||||
PCHAR FunctionName,
|
||||
__out
|
||||
FxPkgPdo **Package,
|
||||
__out
|
||||
PFX_DRIVER_GLOBALS* ObjectGlobals,
|
||||
__out_opt
|
||||
FxDevice **OutDevice = NULL
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
FxDevice *pDevice;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(CallersGlobals,
|
||||
Device,
|
||||
FX_TYPE_DEVICE,
|
||||
(PVOID*) &pDevice,
|
||||
ObjectGlobals);
|
||||
|
||||
//
|
||||
// If the optional "OutDevice" argument is present, return the pointer
|
||||
// to the device.
|
||||
//
|
||||
if (OutDevice != NULL) {
|
||||
*OutDevice = pDevice;
|
||||
}
|
||||
|
||||
//
|
||||
// Check to see if a PDO package is installed on the device.
|
||||
//
|
||||
if (pDevice->IsPdo()) {
|
||||
*Package = (FxPkgPdo *) pDevice->GetPdoPkg();
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
DoTraceLevelMessage((*ObjectGlobals), TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"%s: Incorrect device handle supplied (0x%p). "
|
||||
"Device is not a PDO.", FunctionName, Device);
|
||||
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Extern "C" the rest of the file file
|
||||
//
|
||||
extern "C" {
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfPdoMarkMissing)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Device
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
NTSTATUS status;
|
||||
FxPkgPdo *pPkgPdo;
|
||||
FxDevice *pDevice;
|
||||
|
||||
status = GetPdoPackageFromDeviceHandle(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
__FUNCTION__,
|
||||
&pPkgPdo,
|
||||
&pFxDriverGlobals,
|
||||
&pDevice);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
//
|
||||
// Check to see if the device is enumerated off of a child list. If so,
|
||||
// have the child list object perform any necessary actions.
|
||||
//
|
||||
status = pPkgPdo->m_OwningChildList->UpdateDeviceAsMissing(pDevice);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFAPI
|
||||
VOID
|
||||
WDFEXPORT(WdfPdoRequestEject)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Device
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
FxPkgPdo *pPkgPdo;
|
||||
FxDevice *pDevice;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
|
||||
status = GetPdoPackageFromDeviceHandle(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
__FUNCTION__,
|
||||
&pPkgPdo,
|
||||
&pFxDriverGlobals,
|
||||
&pDevice);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
PDEVICE_OBJECT pdo;
|
||||
|
||||
pdo = pDevice->GetSafePhysicalDevice();
|
||||
|
||||
if (pdo != NULL) {
|
||||
IoRequestDeviceEject(pdo);
|
||||
}
|
||||
else {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"PDO WDFDEVICE %p not reported yet to pnp, cannot eject!",
|
||||
Device);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
}
|
||||
}
|
||||
else {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Can only eject PDOs, %!STATUS!", status);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
}
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFDEVICE
|
||||
WDFEXPORT(WdfPdoGetParent)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Device
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
NTSTATUS status;
|
||||
FxPkgPdo *pPkgPdo;
|
||||
FxDevice *pDevice;
|
||||
|
||||
status = GetPdoPackageFromDeviceHandle(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
__FUNCTION__,
|
||||
&pPkgPdo,
|
||||
&pFxDriverGlobals,
|
||||
&pDevice);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
return pDevice->m_ParentDevice->GetHandle();
|
||||
}
|
||||
else {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Can only eject PDOs, %!STATUS!", status);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFAPI
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfPdoRetrieveIdentificationDescription)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Device,
|
||||
__inout
|
||||
PWDF_CHILD_IDENTIFICATION_DESCRIPTION_HEADER IdentificationDescription
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
NTSTATUS status;
|
||||
FxPkgPdo *pPkgPdo;
|
||||
|
||||
status = GetPdoPackageFromDeviceHandle(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
__FUNCTION__,
|
||||
&pPkgPdo,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, IdentificationDescription);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
FxChildList* pList;
|
||||
|
||||
if (pPkgPdo->m_Description == NULL) {
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
pList = pPkgPdo->m_Description->GetParentList();
|
||||
|
||||
//
|
||||
// The fact that a statically enumerated PDO is enumerated using an
|
||||
// FxChildList should not be exposed to the driver. Besides, the driver
|
||||
// does not know the definition of the identificaiton descirption anyways.
|
||||
//
|
||||
if (pList->IsStaticList() ||
|
||||
pList->GetIdentificationDescriptionSize() !=
|
||||
IdentificationDescription->IdentificationDescriptionSize) {
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
pList->CopyId(IdentificationDescription,
|
||||
pPkgPdo->m_Description->GetId());
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFAPI
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfPdoRetrieveAddressDescription)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Device,
|
||||
__inout
|
||||
PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER AddressDescription
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
NTSTATUS status;
|
||||
FxPkgPdo *pPkgPdo;
|
||||
|
||||
status = GetPdoPackageFromDeviceHandle(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
__FUNCTION__,
|
||||
&pPkgPdo,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, AddressDescription);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
FxChildList* pList;
|
||||
|
||||
if (pPkgPdo->m_Description == NULL) {
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
pList = pPkgPdo->m_Description->GetParentList();
|
||||
|
||||
//
|
||||
// A call to pList->IsStaticList() in the if below is not needed because
|
||||
// a static list does not have address descriptions. Make sure this
|
||||
// assumption is not violated through the ASSERT().
|
||||
//
|
||||
ASSERT(pList->IsStaticList() == FALSE);
|
||||
|
||||
if (pList->HasAddressDescriptions() == FALSE ||
|
||||
pList->GetAddressDescriptionSize() !=
|
||||
AddressDescription->AddressDescriptionSize) {
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
pList->GetAddressDescriptionFromEntry(pPkgPdo->m_Description,
|
||||
AddressDescription);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFAPI
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfPdoUpdateAddressDescription)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Device,
|
||||
__inout
|
||||
PWDF_CHILD_ADDRESS_DESCRIPTION_HEADER AddressDescription
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
NTSTATUS status;
|
||||
FxPkgPdo *pPkgPdo;
|
||||
|
||||
status = GetPdoPackageFromDeviceHandle(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
__FUNCTION__,
|
||||
&pPkgPdo,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, AddressDescription);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
FxChildList* pList;
|
||||
|
||||
if (pPkgPdo->m_Description == NULL) {
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
pList = pPkgPdo->m_Description->GetParentList();
|
||||
|
||||
if (pList->GetAddressDescriptionSize() !=
|
||||
AddressDescription->AddressDescriptionSize) {
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
pList->UpdateAddressDescriptionFromEntry(pPkgPdo->m_Description,
|
||||
AddressDescription);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfPdoAddEjectionRelationsPhysicalDevice)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Device,
|
||||
__in
|
||||
PDEVICE_OBJECT PhysicalDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Registers a PDO from another non descendant (not verifiable though) pnp
|
||||
stack to be reported as also requiring eject when this PDO is ejected.
|
||||
|
||||
The PDO could be another device enumerated by this driver.
|
||||
|
||||
Arguments:
|
||||
Device - the PDO for this driver
|
||||
|
||||
PhysicalDevice - PDO for the other stack
|
||||
|
||||
Return Value:
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxPkgPdo* pPkgPdo;
|
||||
NTSTATUS status;
|
||||
|
||||
status = GetPdoPackageFromDeviceHandle(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
__FUNCTION__,
|
||||
&pPkgPdo,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, PhysicalDevice);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = pPkgPdo->AddEjectionDevice(PhysicalDevice);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
VOID
|
||||
WDFEXPORT(WdfPdoRemoveEjectionRelationsPhysicalDevice)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Device,
|
||||
__in
|
||||
PDEVICE_OBJECT PhysicalDevice
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Deregisters a PDO from another non descendant (not verifiable though) pnp
|
||||
stack so that it will not be reported as also requiring eject when this PDO
|
||||
is ejected.
|
||||
|
||||
Arguments:
|
||||
Device - the PDO for this driver
|
||||
|
||||
PhysicalDevice - PDO for the other stack
|
||||
|
||||
Return Value:
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxPkgPdo* pPkgPdo;
|
||||
NTSTATUS status;
|
||||
|
||||
status = GetPdoPackageFromDeviceHandle(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
__FUNCTION__,
|
||||
&pPkgPdo,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, PhysicalDevice);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return; // status;
|
||||
}
|
||||
|
||||
pPkgPdo->RemoveEjectionDevice(PhysicalDevice);
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
VOID
|
||||
WDFEXPORT(WdfPdoClearEjectionRelationsDevices)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Device
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Deregisters all PDOs so that they will not be reported as also requiring
|
||||
eject when this PDO is ejected.
|
||||
|
||||
Arguments:
|
||||
Device - this driver's PDO
|
||||
|
||||
Return Value:
|
||||
None
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxPkgPdo* pPkgPdo;
|
||||
NTSTATUS status;
|
||||
|
||||
status = GetPdoPackageFromDeviceHandle(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
__FUNCTION__,
|
||||
&pPkgPdo,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return; // status;
|
||||
}
|
||||
|
||||
pPkgPdo->ClearEjectionDevicesList();
|
||||
}
|
||||
|
||||
} // extern "C"
|
||||
|
412
sdk/lib/drivers/wdf/kmdf/src/core/fxdpc.cpp
Normal file
412
sdk/lib/drivers/wdf/kmdf/src/core/fxdpc.cpp
Normal file
|
@ -0,0 +1,412 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxDpc.hpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements a frameworks managed DPC that
|
||||
can synchrononize with driver frameworks object locks.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxcorepch.hpp"
|
||||
|
||||
#include "FxDpc.hpp"
|
||||
|
||||
// Tracing support
|
||||
extern "C" {
|
||||
#include "FxDpc.tmh"
|
||||
}
|
||||
|
||||
//
|
||||
// Public constructors
|
||||
//
|
||||
|
||||
FxDpc::FxDpc(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals
|
||||
) :
|
||||
FxNonPagedObject(FX_TYPE_DPC, sizeof(FxDpc), FxDriverGlobals)
|
||||
{
|
||||
m_Object = NULL;
|
||||
m_CallbackLock = NULL;
|
||||
m_CallbackLockObject = NULL;
|
||||
m_Callback = NULL;
|
||||
m_RunningDown = FALSE;
|
||||
|
||||
//
|
||||
// Mark the object has having passive level dispose so that KeFlushQueuedDpcs
|
||||
// can be called in Dispose().
|
||||
//
|
||||
MarkPassiveDispose(ObjectDoNotLock);
|
||||
|
||||
MarkDisposeOverride(ObjectDoNotLock);
|
||||
}
|
||||
|
||||
|
||||
FxDpc::~FxDpc()
|
||||
{
|
||||
//
|
||||
// If this hits, its because someone destroyed the DPC by
|
||||
// removing too many references by mistake without calling WdfObjectDelete
|
||||
//
|
||||
if (m_Object != NULL) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Destroy WDFDPC %p destroyed without calling WdfObjectDelete, or by"
|
||||
" Framework processing DeviceRemove. Possible reference count "
|
||||
"problem?", GetObjectHandleUnchecked());
|
||||
FxVerifierDbgBreakPoint(GetDriverGlobals());
|
||||
}
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxDpc::_Create(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PWDF_DPC_CONFIG Config,
|
||||
__in PWDF_OBJECT_ATTRIBUTES Attributes,
|
||||
__in FxObject* ParentObject,
|
||||
__out WDFDPC* Dpc
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Create an FxDpc factory method
|
||||
|
||||
Arguments:
|
||||
|
||||
All arguments have been valided by the FxDpcApi stub.
|
||||
|
||||
Returns:
|
||||
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
{
|
||||
FxDpc* pFxDpc;
|
||||
NTSTATUS status;
|
||||
|
||||
pFxDpc = new(FxDriverGlobals, Attributes) FxDpc(FxDriverGlobals);
|
||||
|
||||
if (pFxDpc == NULL) {
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
status = pFxDpc->Initialize(
|
||||
Attributes,
|
||||
Config,
|
||||
ParentObject,
|
||||
Dpc
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
pFxDpc->DeleteFromFailedCreate();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxDpc::Initialize(
|
||||
__in PWDF_OBJECT_ATTRIBUTES Attributes,
|
||||
__in PWDF_DPC_CONFIG Config,
|
||||
__in FxObject* ParentObject,
|
||||
__out WDFDPC* Dpc
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
IFxHasCallbacks* pCallbacks;
|
||||
NTSTATUS status;
|
||||
KDPC* pDpc;
|
||||
|
||||
pFxDriverGlobals = GetDriverGlobals();
|
||||
pDpc = NULL;
|
||||
pCallbacks = NULL;
|
||||
|
||||
pDpc = &m_Dpc;
|
||||
|
||||
//
|
||||
// Set user's callback function
|
||||
//
|
||||
m_Callback = Config->EvtDpcFunc;
|
||||
|
||||
//
|
||||
// Initialize the DPC to point to our thunk
|
||||
//
|
||||
KeInitializeDpc(
|
||||
pDpc, // Dpc
|
||||
FxDpcThunk, // DeferredRoutine
|
||||
this // DeferredContext
|
||||
);
|
||||
|
||||
//
|
||||
// As long as we are associated, the parent object holds a reference
|
||||
// count on the DPC.
|
||||
//
|
||||
// We keep an extra reference count since on Dispose, we wait until
|
||||
// all outstanding DPC's complete before allowing finalization.
|
||||
//
|
||||
// This reference must be taken early before we return any failure,
|
||||
// since Dispose() expects this extra reference, and Dispose() will
|
||||
// be called even if we return a failure status right now.
|
||||
//
|
||||
ADDREF(this);
|
||||
|
||||
//
|
||||
// DPC's can be parented by, and optionally serialize with an FxDevice or
|
||||
// an FxQueue.
|
||||
//
|
||||
m_DeviceBase = FxDeviceBase::_SearchForDevice(ParentObject, &pCallbacks);
|
||||
|
||||
if (m_DeviceBase == NULL) {
|
||||
return STATUS_INVALID_DEVICE_REQUEST;
|
||||
}
|
||||
|
||||
//
|
||||
// Configure Serialization for the DPC and callbacks on the supplied object
|
||||
//
|
||||
status = _GetEffectiveLock(
|
||||
ParentObject,
|
||||
pCallbacks,
|
||||
Config->AutomaticSerialization,
|
||||
FALSE,
|
||||
&m_CallbackLock,
|
||||
&m_CallbackLockObject
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
if (status == STATUS_WDF_INCOMPATIBLE_EXECUTION_LEVEL) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"ParentObject %p can not automatically synchronize callbacks "
|
||||
"with a DPC since it is configured for passive level callback "
|
||||
"constraints. Set AutomaticSerialization to FALSE. %!STATUS!",
|
||||
Attributes->ParentObject, status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// We automatically synchronize with and reference count
|
||||
// the lifetime of the framework object to prevent any DPC races
|
||||
// that can access the object while it is going away.
|
||||
//
|
||||
|
||||
//
|
||||
// The caller supplied object is the object the caller wants the
|
||||
// DPC to be associated with, and the framework must ensure this
|
||||
// object remains live until the DPC object is destroyed. Otherwise,
|
||||
// it could access either object context memory, or an object API
|
||||
// on a freed object.
|
||||
//
|
||||
// Due to the locking model of the framework, the lock may actually
|
||||
// be owned by a higher level object as well. This is the lockObject
|
||||
// returned. As long was we are a child of this object, the lockObject
|
||||
// does not need to be dereferenced since it will notify us of Cleanup
|
||||
// before it goes away.
|
||||
//
|
||||
|
||||
//
|
||||
// Associate the FxDpc with the object. When this object gets deleted or
|
||||
// disposed, it will notify our Dispose function as well.
|
||||
//
|
||||
|
||||
//
|
||||
// Add a reference to the parent object we are associated with.
|
||||
// We will be notified of Cleanup to release this reference.
|
||||
//
|
||||
ParentObject->ADDREF(this);
|
||||
|
||||
// Save the ptr to the object the DPC is associated with
|
||||
m_Object = ParentObject;
|
||||
|
||||
//
|
||||
// Attributes->ParentObject is the same as ParentObject. Since we already
|
||||
// converted it to an object, use that.
|
||||
//
|
||||
status = Commit(Attributes, (WDFOBJECT*)Dpc, ParentObject);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxDpc::Cancel(
|
||||
__in BOOLEAN Wait
|
||||
)
|
||||
{
|
||||
BOOLEAN result;
|
||||
|
||||
result = KeRemoveQueueDpc(GetDpcPtr());
|
||||
|
||||
//
|
||||
// If result == FALSE, then the DPC could already be running.
|
||||
//
|
||||
// If the caller supplies Wait == TRUE, they want to wait and
|
||||
// ensure on return the DPC has finished running.
|
||||
//
|
||||
// The trick here is to implement this without adding execessive
|
||||
// overhead to the "normal" path, such as tracking reference counts,
|
||||
// locking, signaling events to waiting threads, etc.
|
||||
//
|
||||
// So we take the expensive approach for the Cancel call in the
|
||||
// case the caller wants to wait, and misses the DPC window. In
|
||||
// this case we will just do the system wide FlushQueuedDpc's to
|
||||
// ensure the DPC has finished running before return.
|
||||
//
|
||||
if( Wait && !result ) {
|
||||
|
||||
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||
|
||||
KeFlushQueuedDpcs();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxDpc::DpcHandler(
|
||||
__in PKDPC Dpc,
|
||||
__in PVOID SystemArgument1,
|
||||
__in PVOID SystemArgument2
|
||||
)
|
||||
{
|
||||
UNREFERENCED_PARAMETER(Dpc);
|
||||
UNREFERENCED_PARAMETER(SystemArgument1);
|
||||
UNREFERENCED_PARAMETER(SystemArgument2);
|
||||
|
||||
FX_TRACK_DRIVER(GetDriverGlobals());
|
||||
|
||||
if (m_Callback != NULL) {
|
||||
|
||||
FxPerfTraceDpc(&m_Callback);
|
||||
|
||||
if (m_CallbackLock != NULL) {
|
||||
KIRQL irql = 0;
|
||||
|
||||
m_CallbackLock->Lock(&irql);
|
||||
m_Callback((WDFDPC)(this->GetObjectHandle()));
|
||||
m_CallbackLock->Unlock(irql);
|
||||
}
|
||||
else {
|
||||
m_Callback((WDFDPC)(this->GetObjectHandle()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FxDpc::FxDpcThunk(
|
||||
__in PKDPC Dpc,
|
||||
__in PVOID DeferredContext,
|
||||
__in PVOID SystemArgument1,
|
||||
__in PVOID SystemArgument2
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This is the C routine called by the kernels DPC handler
|
||||
|
||||
Arguments:
|
||||
|
||||
Dpc - our DPC object associated with our Timer
|
||||
DeferredContext - Context for the DPC that we setup in DriverEntry
|
||||
SystemArgument1 -
|
||||
SystemArgument2 -
|
||||
|
||||
Return Value:
|
||||
|
||||
Nothing.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
FxDpc* pDpc = (FxDpc*)DeferredContext;
|
||||
|
||||
pDpc->DpcHandler(
|
||||
Dpc,
|
||||
SystemArgument1,
|
||||
SystemArgument2
|
||||
);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Called when DeleteObject is called, or when the parent
|
||||
// is being deleted or Disposed.
|
||||
//
|
||||
// Also invoked directly by the cleanup list at our request after
|
||||
// a Dispose occurs and must be deferred if not at passive level.
|
||||
//
|
||||
BOOLEAN
|
||||
FxDpc::Dispose()
|
||||
{
|
||||
// MarkPassiveDispose() in Initialize ensures this
|
||||
ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);
|
||||
|
||||
m_RunningDown = TRUE;
|
||||
|
||||
FlushAndRundown();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
//
|
||||
// Called by the system work item to finish the rundown
|
||||
//
|
||||
VOID
|
||||
FxDpc::FlushAndRundown()
|
||||
{
|
||||
FxObject* pObject;
|
||||
|
||||
//
|
||||
// If we have the KeFlushQueuedDpcs function call it
|
||||
// to ensure the DPC routine is no longer running before
|
||||
// we release the final reference and memory to the framework objects
|
||||
//
|
||||
KeFlushQueuedDpcs();
|
||||
|
||||
//
|
||||
// Release our reference count to the associated parent object if present
|
||||
//
|
||||
if (m_Object != NULL) {
|
||||
pObject = m_Object;
|
||||
m_Object = NULL;
|
||||
|
||||
pObject->RELEASE(this);
|
||||
}
|
||||
|
||||
//
|
||||
// Perform our final release to ourselves, destroying the FxDpc
|
||||
//
|
||||
RELEASE(this);
|
||||
}
|
289
sdk/lib/drivers/wdf/kmdf/src/core/fxdpcapi.cpp
Normal file
289
sdk/lib/drivers/wdf/kmdf/src/core/fxdpcapi.cpp
Normal file
|
@ -0,0 +1,289 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxDpcApi.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This implements the WDFDPC API's
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxcorepch.hpp"
|
||||
|
||||
#include "FxDpc.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxDpcApi.tmh"
|
||||
}
|
||||
|
||||
//
|
||||
// extern "C" the entire file
|
||||
//
|
||||
extern "C" {
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfDpcCreate)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
PWDF_DPC_CONFIG Config,
|
||||
__in
|
||||
PWDF_OBJECT_ATTRIBUTES Attributes,
|
||||
__out
|
||||
WDFDPC * Dpc
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Create a DPC object that will call the supplied function with
|
||||
context when it fires. It returns a handle to the WDFDPC object.
|
||||
|
||||
Arguments:
|
||||
|
||||
Config - WDF_DPC_CONFIG structure.
|
||||
|
||||
Attributes - WDF_OBJECT_ATTRIBUTES to set the parent object and to request
|
||||
a context memory allocation, and a DestroyCallback.
|
||||
|
||||
Dpc - Pointer to location to returnt he resulting WDFDPC handle.
|
||||
|
||||
Returns:
|
||||
|
||||
STATUS_SUCCESS - A WDFDPC handle has been created.
|
||||
|
||||
Notes:
|
||||
|
||||
The WDFDPC object is deleted either when the DEVICE or QUEUE it is
|
||||
associated as its parent with is deleted, or WdfObjectDelete is called.
|
||||
|
||||
If the DPC is used to access WDM objects, a Cleanup callback should
|
||||
be registered to allow references to be released.
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxObject* pParent;
|
||||
NTSTATUS status;
|
||||
|
||||
pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
|
||||
status = FxValidateObjectAttributesForParentHandle(pFxDriverGlobals,
|
||||
Attributes,
|
||||
FX_VALIDATE_OPTION_PARENT_REQUIRED);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
|
||||
Attributes->ParentObject,
|
||||
FX_TYPE_OBJECT,
|
||||
(PVOID*)&pParent,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, Config);
|
||||
FxPointerNotNull(pFxDriverGlobals, Dpc);
|
||||
|
||||
if (Config->Size != sizeof(WDF_DPC_CONFIG)) {
|
||||
status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"WDF_DPC_CONFIG got Size %d, expected %d, %!STATUS!",
|
||||
Config->Size, sizeof(WDF_DPC_CONFIG), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
status = FxValidateObjectAttributes(
|
||||
pFxDriverGlobals,
|
||||
Attributes
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
status = FxDpc::_Create(pFxDriverGlobals, Config, Attributes, pParent, Dpc);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
__drv_maxIRQL(HIGH_LEVEL)
|
||||
KDPC*
|
||||
WDFEXPORT(WdfDpcWdmGetDpc)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDPC Dpc
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Return the KDPC* object pointer so that it may be linked into
|
||||
a DPC list.
|
||||
|
||||
Arguments:
|
||||
|
||||
WDFDPC - Handle to WDFDPC object created with WdfDpcCreate.
|
||||
|
||||
Returns:
|
||||
|
||||
KDPC*
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
FxDpc* pFxDpc;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
Dpc,
|
||||
FX_TYPE_DPC,
|
||||
(PVOID*)&pFxDpc);
|
||||
|
||||
return pFxDpc->GetDpcPtr();
|
||||
}
|
||||
|
||||
|
||||
__drv_maxIRQL(HIGH_LEVEL)
|
||||
BOOLEAN
|
||||
WDFEXPORT(WdfDpcEnqueue)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDPC Dpc
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Enqueue the DPC to run at a system determined time
|
||||
|
||||
Arguments:
|
||||
|
||||
WDFDPC - Handle to WDFDPC object created with WdfDpcCreate.
|
||||
|
||||
Returns:
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
FxDpc* pFxDpc;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
Dpc,
|
||||
FX_TYPE_DPC,
|
||||
(PVOID*)&pFxDpc);
|
||||
|
||||
return KeInsertQueueDpc(pFxDpc->GetDpcPtr(), NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
__drv_when(Wait == __true, __drv_maxIRQL(PASSIVE_LEVEL))
|
||||
__drv_when(Wait == __false, __drv_maxIRQL(HIGH_LEVEL))
|
||||
BOOLEAN
|
||||
WDFEXPORT(WdfDpcCancel)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDPC Dpc,
|
||||
__in
|
||||
BOOLEAN Wait
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Attempt to cancel the DPC and returns status
|
||||
|
||||
Arguments:
|
||||
|
||||
WDFDPC - Handle to WDFDPC object created with WdfDpcCreate.
|
||||
|
||||
Returns:
|
||||
|
||||
TRUE - DPC was cancelled, and was not run
|
||||
|
||||
FALSE - DPC was not cancelled, has run, is running, or will run
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxDpc* pFxDpc;
|
||||
NTSTATUS status;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
Dpc,
|
||||
FX_TYPE_DPC,
|
||||
(PVOID*)&pFxDpc,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
if (Wait) {
|
||||
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return pFxDpc->Cancel(Wait);
|
||||
}
|
||||
|
||||
|
||||
|
||||
__drv_maxIRQL(HIGH_LEVEL)
|
||||
WDFOBJECT
|
||||
WDFEXPORT(WdfDpcGetParentObject)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDPC Dpc
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
Return the parent parent object supplied to WdfDpcCreate.
|
||||
|
||||
Arguments:
|
||||
|
||||
WDFDPC - Handle to WDFDPC object created with WdfDpcCreate.
|
||||
|
||||
Returns:
|
||||
|
||||
--*/
|
||||
|
||||
{
|
||||
FxDpc* pFxDpc;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
Dpc,
|
||||
FX_TYPE_DPC,
|
||||
(PVOID*)&pFxDpc);
|
||||
|
||||
return pFxDpc->GetObject();
|
||||
}
|
||||
|
||||
} // extern "C"
|
677
sdk/lib/drivers/wdf/kmdf/src/core/fxsystemthread.cpp
Normal file
677
sdk/lib/drivers/wdf/kmdf/src/core/fxsystemthread.cpp
Normal file
|
@ -0,0 +1,677 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxSystemThread.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This is the implementation of the FxSystemThread object.
|
||||
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxcorepch.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxSystemThread.tmh"
|
||||
}
|
||||
|
||||
|
||||
FxSystemThread::FxSystemThread(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals
|
||||
) :
|
||||
FxNonPagedObject(FX_TYPE_SYSTEMTHREAD, 0, FxDriverGlobals)
|
||||
{
|
||||
|
||||
m_Initialized = FALSE;
|
||||
m_ThreadPtr = NULL;
|
||||
m_Exit = FALSE;
|
||||
m_PEThread = NULL;
|
||||
|
||||
//m_Spinup.WorkerRoutine = NULL; // Async-Thread-Spinup
|
||||
m_Reaper.WorkerRoutine = NULL;
|
||||
|
||||
InitializeListHead(&m_WorkList);
|
||||
m_InitEvent.Initialize(NotificationEvent, FALSE);
|
||||
m_WorkEvent.Initialize(NotificationEvent, FALSE);
|
||||
}
|
||||
|
||||
FxSystemThread::~FxSystemThread() {
|
||||
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxSystemThread::_CreateAndInit(
|
||||
__deref_out FxSystemThread** SystemThread,
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in WDFDEVICE Device,
|
||||
__in PDEVICE_OBJECT DeviceObject
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
FxSystemThread *pThread = NULL;
|
||||
|
||||
*SystemThread = NULL;
|
||||
|
||||
pThread = new(FxDriverGlobals) FxSystemThread(FxDriverGlobals);
|
||||
if (pThread == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"WDFDEVICE 0x%p !devobj %p could not allocate a thread for handling "
|
||||
"power requests %!STATUS!",
|
||||
Device, DeviceObject, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if (pThread->Initialize() == FALSE) {
|
||||
status = STATUS_UNSUCCESSFUL;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"WDFDEVICE 0x%p, !devobj %p, could not initialize power thread, "
|
||||
"%!STATUS!",
|
||||
Device, DeviceObject, status);
|
||||
|
||||
pThread->DeleteFromFailedCreate();
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
*SystemThread = pThread;
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Create the system thread in order to be able to service work items
|
||||
//
|
||||
// It is recommended this is done from the system process context
|
||||
// since the threads handle is available to the user mode process
|
||||
// for a temporary window. XP and later supports OBJ_KERNELHANDLE, but
|
||||
// DriverFrameworks must support W2K with the same binary.
|
||||
//
|
||||
// It is safe to call this at DriverEntry which is in the system process
|
||||
// to create an initial driver thread, and this driver thread should be
|
||||
// used for creating any child driver threads on demand.
|
||||
//
|
||||
BOOLEAN
|
||||
FxSystemThread::Initialize()
|
||||
{
|
||||
NTSTATUS status;
|
||||
KIRQL irql;
|
||||
|
||||
Lock(&irql);
|
||||
|
||||
// Frameworks bug if this is called with a thread already running
|
||||
ASSERT(m_ThreadPtr == NULL);
|
||||
|
||||
ASSERT(m_Initialized == FALSE);
|
||||
|
||||
m_Initialized = TRUE;
|
||||
|
||||
Unlock(irql);
|
||||
|
||||
status = CreateThread();
|
||||
|
||||
return NT_SUCCESS(status) ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxSystemThread::CreateThread(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
HANDLE threadHandle;
|
||||
NTSTATUS status;
|
||||
|
||||
//
|
||||
// Take an extra object reference on ourselves to account
|
||||
// for the system thread referencing the object while it is running.
|
||||
//
|
||||
// The thread itself will release this reference in its exit routine
|
||||
//
|
||||
ADDREF(FxSystemThread::StaticThreadThunk);
|
||||
|
||||
status = PsCreateSystemThread(
|
||||
&threadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL, // Obja
|
||||
NULL, // hProcess
|
||||
NULL, // CLIENT_ID,
|
||||
FxSystemThread::StaticThreadThunk,
|
||||
this
|
||||
);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
m_Initialized = FALSE;
|
||||
|
||||
DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Could not create system thread %!STATUS!", status);
|
||||
//
|
||||
// Release the reference taken above due to failure
|
||||
//
|
||||
RELEASE(FxSystemThread::StaticThreadThunk);
|
||||
}
|
||||
else {
|
||||
status = ObReferenceObjectByHandle(
|
||||
threadHandle,
|
||||
THREAD_ALL_ACCESS,
|
||||
NULL,
|
||||
KernelMode,
|
||||
&m_ThreadPtr,
|
||||
NULL
|
||||
);
|
||||
|
||||
ASSERT(NT_SUCCESS(status));
|
||||
|
||||
// We can now close the thread handle since we have a pointer reference
|
||||
ZwClose(threadHandle);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// This is called to tell the thread to exit.
|
||||
//
|
||||
// It must be called from thread context such as
|
||||
// the driver unload routine since it will wait for the
|
||||
// thread to exit.
|
||||
//
|
||||
BOOLEAN
|
||||
FxSystemThread::ExitThread()
|
||||
{
|
||||
NTSTATUS Status;
|
||||
KIRQL irql;
|
||||
|
||||
Lock(&irql);
|
||||
|
||||
if( !m_Initialized ) {
|
||||
Unlock(irql);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if( m_Exit ) {
|
||||
ASSERT(FALSE); // This is not race free, so don't allow it
|
||||
Unlock(irql);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Tell the system thread to exit
|
||||
m_Exit = TRUE;
|
||||
|
||||
//
|
||||
// The thread could still be spinning up, so we must handle this condition.
|
||||
//
|
||||
if( m_ThreadPtr == NULL ) {
|
||||
|
||||
Unlock(irql);
|
||||
|
||||
KeEnterCriticalRegion();
|
||||
|
||||
// Wait for thread to start
|
||||
Status = m_InitEvent.WaitFor(Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
UNREFERENCED_PARAMETER(Status);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
//
|
||||
// Now we have a thread, wait for it to go away
|
||||
//
|
||||
ASSERT(m_ThreadPtr != NULL);
|
||||
}
|
||||
else {
|
||||
Unlock(irql);
|
||||
}
|
||||
|
||||
m_WorkEvent.Set();
|
||||
|
||||
//
|
||||
// We can't be waiting in our own thread for the thread to exit.
|
||||
//
|
||||
ASSERT(IsCurrentThread() == FALSE);
|
||||
|
||||
KeEnterCriticalRegion();
|
||||
|
||||
// Wait for thread to exit
|
||||
Status = KeWaitForSingleObject(
|
||||
m_ThreadPtr,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL
|
||||
);
|
||||
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
UNREFERENCED_PARAMETER(Status);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
ObDereferenceObject(m_ThreadPtr);
|
||||
|
||||
//
|
||||
// Now safe to unload the driver or object
|
||||
// the thread worker is pointing to
|
||||
//
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxSystemThread::ExitThreadAsync(
|
||||
__inout FxSystemThread* Reaper
|
||||
)
|
||||
{
|
||||
KIRQL irql;
|
||||
|
||||
//
|
||||
// Without a top level reaper, the frameworks can not ensure
|
||||
// all worker threads have exited at driver unload in the async
|
||||
// case. If this is a top level thread, then DriverUnload should
|
||||
// call the synchronous ExitThread() method.
|
||||
//
|
||||
ASSERT(Reaper != NULL);
|
||||
|
||||
Lock(&irql);
|
||||
|
||||
if( !m_Initialized ) {
|
||||
Unlock(irql);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if( m_Exit ) {
|
||||
ASSERT(FALSE);
|
||||
Unlock(irql);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// Tell the system thread to exit
|
||||
m_Exit = TRUE;
|
||||
|
||||
// Add a reference which will be released by the reaper
|
||||
ADDREF(FxSystemThread::StaticReaperThunk);
|
||||
|
||||
Unlock(irql);
|
||||
|
||||
m_WorkEvent.Set();
|
||||
|
||||
ASSERT(m_Reaper.WorkerRoutine == NULL);
|
||||
|
||||
// We are the only user of this field protected by setting m_Exit
|
||||
m_Reaper.WorkerRoutine = FxSystemThread::StaticReaperThunk;
|
||||
m_Reaper.Parameter = this;
|
||||
|
||||
Reaper->QueueWorkItem(&m_Reaper);
|
||||
|
||||
//
|
||||
// It is not safe to unload the driver until the reaper
|
||||
// thread has processed the work item and waited for this
|
||||
// thread to exit.
|
||||
//
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxSystemThread::QueueWorkItem(
|
||||
__inout PWORK_QUEUE_ITEM WorkItem
|
||||
)
|
||||
{
|
||||
KIRQL irql;
|
||||
BOOLEAN result;
|
||||
|
||||
Lock(&irql);
|
||||
|
||||
if (m_Exit) {
|
||||
result = FALSE;
|
||||
}
|
||||
else {
|
||||
result = TRUE;
|
||||
InsertTailList(&m_WorkList, &WorkItem->List);
|
||||
|
||||
m_WorkEvent.Set();
|
||||
}
|
||||
|
||||
Unlock(irql);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Attempt to cancel the work item.
|
||||
//
|
||||
// Returns TRUE if success.
|
||||
//
|
||||
// If returns FALSE, the work item
|
||||
// routine either has been called, is running,
|
||||
// or is about to be called.
|
||||
//
|
||||
BOOLEAN
|
||||
FxSystemThread::CancelWorkItem(
|
||||
__inout PWORK_QUEUE_ITEM WorkItem
|
||||
)
|
||||
{
|
||||
PLIST_ENTRY Entry;
|
||||
KIRQL irql;
|
||||
|
||||
Lock(&irql);
|
||||
|
||||
Entry = m_WorkList.Flink;
|
||||
|
||||
while( Entry != &this->m_WorkList ) {
|
||||
|
||||
if( Entry == &WorkItem->List ) {
|
||||
RemoveEntryList(&WorkItem->List);
|
||||
Unlock(irql);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
Entry = Entry->Flink;
|
||||
}
|
||||
|
||||
// Not found
|
||||
Unlock(irql);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxSystemThread::Thread()
|
||||
{
|
||||
NTSTATUS status;
|
||||
LIST_ENTRY head;
|
||||
PLIST_ENTRY ple;
|
||||
PWORK_QUEUE_ITEM pItem;
|
||||
|
||||
//DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
// "Created, entering work loop");
|
||||
|
||||
//
|
||||
// The worker thread will process all list entries before
|
||||
// checking for exit. This allows the top level FxDriver
|
||||
// thread to process all deferred cleanup work items at
|
||||
// driver unload.
|
||||
//
|
||||
// CancelWorkItem may be used to remove entries
|
||||
// before requesting a thread exit if the caller wants to
|
||||
// interrupt work queue processing.
|
||||
//
|
||||
|
||||
InitializeListHead(&head);
|
||||
|
||||
// Initialize for IsCurrentThread()
|
||||
m_PEThread = Mx::GetCurrentEThread();
|
||||
|
||||
// Set the event that the thread now exists
|
||||
m_InitEvent.Set();
|
||||
|
||||
for ( ; ; ) {
|
||||
KIRQL irql;
|
||||
|
||||
//
|
||||
// Lock the list so we are in sync with QueueWorkItem
|
||||
//
|
||||
Lock(&irql);
|
||||
|
||||
while(!IsListEmpty(&m_WorkList)) {
|
||||
//
|
||||
// Instead of popping each LIST_ENTRY off of the old list and
|
||||
// enqueueing it to the local list head, manipulate the first and
|
||||
// last entry in the list to point to our new head.
|
||||
//
|
||||
head.Flink = m_WorkList.Flink;
|
||||
head.Blink = m_WorkList.Blink;
|
||||
|
||||
// First link in the list point backwrad to the new head
|
||||
m_WorkList.Flink->Blink = &head;
|
||||
|
||||
// Last link in the list point fwd to the new head
|
||||
m_WorkList.Blink->Flink = &head;
|
||||
|
||||
ASSERT(!IsListEmpty(&head));
|
||||
|
||||
//
|
||||
// Reinitialize the work list head
|
||||
//
|
||||
InitializeListHead(&m_WorkList);
|
||||
|
||||
//
|
||||
// Process the workitems while unlocked so that the work item can
|
||||
// requeue itself if needed and work at passive level.
|
||||
//
|
||||
Unlock(irql);
|
||||
|
||||
while (!IsListEmpty(&head)) {
|
||||
ple = RemoveHeadList(&head);
|
||||
pItem = CONTAINING_RECORD(ple, WORK_QUEUE_ITEM, List);
|
||||
pItem->WorkerRoutine(pItem->Parameter);
|
||||
|
||||
//
|
||||
// NOTE: pItem may have been pool released by the called worker
|
||||
// routine, so it may not be accessed after the callback
|
||||
//
|
||||
}
|
||||
|
||||
//
|
||||
// Relock the list and repeat until the work list is empty
|
||||
//
|
||||
Lock(&irql);
|
||||
}
|
||||
|
||||
// No more items on list, check for exit
|
||||
if (m_Exit) {
|
||||
//DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
// "Terminating");
|
||||
|
||||
Unlock(irql);
|
||||
|
||||
// Release the object reference held by the thread
|
||||
RELEASE(FxSystemThread::StaticThreadThunk);
|
||||
|
||||
status = PsTerminateSystemThread(STATUS_SUCCESS);
|
||||
UNREFERENCED_PARAMETER(status);
|
||||
ASSERT(NT_SUCCESS(status));
|
||||
|
||||
// NOT REACHED
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// No work to do, clear event under lock to prevent a race with a work
|
||||
// enqueue
|
||||
//
|
||||
m_WorkEvent.Clear();
|
||||
|
||||
Unlock(irql);
|
||||
|
||||
// We are a system thread, so we do not need KeEnterCriticalRegion()
|
||||
status = m_WorkEvent.WaitFor(
|
||||
Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
UNREFERENCED_PARAMETER(status);
|
||||
ASSERT(NT_SUCCESS(status));
|
||||
}
|
||||
|
||||
// NOT REACHED
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
VOID
|
||||
FxSystemThread::Reaper()
|
||||
{
|
||||
NTSTATUS Status;
|
||||
KIRQL irql;
|
||||
|
||||
Lock(&irql);
|
||||
|
||||
ASSERT(m_Initialized);
|
||||
ASSERT(m_Exit);
|
||||
|
||||
//
|
||||
// The thread could still be spinning up, so we must handle this condition.
|
||||
//
|
||||
if( m_ThreadPtr == NULL ) {
|
||||
|
||||
Unlock(irql);
|
||||
|
||||
KeEnterCriticalRegion();
|
||||
|
||||
// Wait for thread to start
|
||||
Status = m_InitEvent.WaitFor(Executive, KernelMode, FALSE, NULL);
|
||||
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
UNREFERENCED_PARAMETER(Status);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
//
|
||||
// Now we have a thread, wait for it to go away
|
||||
//
|
||||
ASSERT(m_ThreadPtr != NULL);
|
||||
}
|
||||
else {
|
||||
Unlock(irql);
|
||||
}
|
||||
|
||||
KeEnterCriticalRegion();
|
||||
|
||||
// Wait for thread to exit
|
||||
Status = KeWaitForSingleObject(
|
||||
m_ThreadPtr,
|
||||
Executive,
|
||||
KernelMode,
|
||||
FALSE,
|
||||
NULL
|
||||
);
|
||||
|
||||
KeLeaveCriticalRegion();
|
||||
|
||||
UNREFERENCED_PARAMETER(Status);
|
||||
ASSERT(NT_SUCCESS(Status));
|
||||
|
||||
ObDereferenceObject(m_ThreadPtr);
|
||||
|
||||
RELEASE(FxSystemThread::StaticReaperThunk);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxSystemThread::StaticThreadThunk(
|
||||
__inout PVOID Context
|
||||
)
|
||||
{
|
||||
FxSystemThread* thread = (FxSystemThread*)Context;
|
||||
|
||||
thread->Thread();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
VOID
|
||||
FxSystemThread::StaticReaperThunk(
|
||||
__inout PVOID Context
|
||||
)
|
||||
{
|
||||
FxSystemThread* thread = (FxSystemThread*)Context;
|
||||
|
||||
thread->Reaper();
|
||||
}
|
||||
|
||||
|
530
sdk/lib/drivers/wdf/kmdf/src/core/tracing.cpp
Normal file
530
sdk/lib/drivers/wdf/kmdf/src/core/tracing.cpp
Normal file
|
@ -0,0 +1,530 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
Tracing.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements tracing for the driver frameworks
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxcorepch.hpp"
|
||||
|
||||
// We use DoTraceMessage
|
||||
extern "C" {
|
||||
#include "tracing.tmh"
|
||||
}
|
||||
|
||||
#include <initguid.h>
|
||||
#include "fxIFR.h" // shared struct between IFR and debug ext.
|
||||
#include "fxIFRKm.h" // kernel mode only IFR definitions
|
||||
|
||||
|
||||
//=============================================================================
|
||||
//
|
||||
//=============================================================================
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxTraceInitialize(
|
||||
VOID
|
||||
)
|
||||
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine initializes the frameworks tracing.
|
||||
|
||||
It must be called early on in the frameworks DriverEntry
|
||||
initialization.
|
||||
|
||||
Arguments:
|
||||
|
||||
None
|
||||
|
||||
Returns:
|
||||
|
||||
NTSTATUS code
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// Initialize the tracing package: Vista or later
|
||||
//
|
||||
WPP_INIT_TRACING(NULL, NULL);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
VOID
|
||||
TraceUninitialize(
|
||||
VOID
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
This routine uninitializes the frameworks tracing. It must be called just
|
||||
before DriverUnload
|
||||
|
||||
Arguments:
|
||||
None
|
||||
|
||||
Returns:
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// Vista and later
|
||||
//
|
||||
WPP_CLEANUP(NULL);
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxWmiTraceMessage(
|
||||
__in TRACEHANDLE LoggerHandle,
|
||||
__in ULONG MessageFlags,
|
||||
__in LPGUID MessageGuid,
|
||||
__in USHORT MessageNumber,
|
||||
__in ...
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
va_list va;
|
||||
|
||||
va_start(va, MessageNumber);
|
||||
|
||||
#pragma prefast(suppress:__WARNING_BUFFER_OVERFLOW, "Recommneded by EndClean");
|
||||
status = WmiTraceMessageVa(LoggerHandle,
|
||||
MessageFlags,
|
||||
MessageGuid,
|
||||
MessageNumber,
|
||||
va);
|
||||
va_end(va);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Subcomponents for the In-Flight Recorder follow.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ULONG
|
||||
FxIFRGetSize(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PCUNICODE_STRING RegistryPath
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Checks to see if the service has overriden the default number of pages that
|
||||
are in the IFR.
|
||||
|
||||
Arguments:
|
||||
RegistryPath - path to the service
|
||||
|
||||
Return Value:
|
||||
The size of the IFR to create in bytes (not pages!)
|
||||
|
||||
--*/
|
||||
{
|
||||
FxAutoRegKey service, parameters;
|
||||
NTSTATUS status;
|
||||
OBJECT_ATTRIBUTES oa;
|
||||
ULONG numPages;
|
||||
|
||||
//
|
||||
// This is the value used in case of any error while retrieving 'LogPages'
|
||||
// from the registry.
|
||||
//
|
||||
numPages = FxIFRMinLogPages;
|
||||
|
||||
//
|
||||
// External representation of the IFR is the "LogPages", so use that term when
|
||||
// overriding the size via the registry.
|
||||
//
|
||||
DECLARE_CONST_UNICODE_STRING(parametersPath, L"Parameters\\Wdf");
|
||||
DECLARE_CONST_UNICODE_STRING(valueName, L"LogPages");
|
||||
|
||||
InitializeObjectAttributes(&oa,
|
||||
(PUNICODE_STRING)RegistryPath,
|
||||
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
status = ZwOpenKey(&service.m_Key, KEY_READ, &oa);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto defaultValues;
|
||||
}
|
||||
|
||||
InitializeObjectAttributes(&oa,
|
||||
(PUNICODE_STRING)¶metersPath,
|
||||
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||
service.m_Key,
|
||||
NULL);
|
||||
|
||||
status = ZwOpenKey(¶meters.m_Key, KEY_READ, &oa);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto defaultValues;
|
||||
}
|
||||
|
||||
status = FxRegKey::_QueryULong(parameters.m_Key, &valueName, &numPages);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto defaultValues;
|
||||
}
|
||||
|
||||
if (numPages == 0) {
|
||||
numPages = FxIFRMinLogPages;
|
||||
}
|
||||
|
||||
defaultValues:
|
||||
//
|
||||
// Use FxIFRAvgLogPages if user specifies greater than FxIFRMaxLogPages and if
|
||||
// Verifier flag is on and so is Verbose flag.
|
||||
//
|
||||
if (numPages > FxIFRMaxLogPages) {
|
||||
if (FxDriverGlobals->FxVerifierOn && FxDriverGlobals->FxVerboseOn) {
|
||||
numPages = FxIFRAvgLogPages;
|
||||
}
|
||||
else {
|
||||
numPages = FxIFRMinLogPages;
|
||||
}
|
||||
}
|
||||
|
||||
return numPages * PAGE_SIZE;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxIFRStart(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PCUNICODE_STRING RegistryPath,
|
||||
__in MdDriverObject DriverObject
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine initialize the In-Flight Recorder (IFR).
|
||||
|
||||
The default log size is set by WDF_IFR_LOG_SIZE and currently
|
||||
is 4096 (one x86 page).
|
||||
This routine should be called very early in driver initialization
|
||||
to allow the capture of all significant events.
|
||||
|
||||
--*/
|
||||
{
|
||||
PWDF_IFR_HEADER pHeader;
|
||||
ULONG size;
|
||||
|
||||
UNREFERENCED_PARAMETER( DriverObject );
|
||||
|
||||
WDFCASSERT(FxIFRRecordSignature == WDF_IFR_RECORD_SIGNATURE);
|
||||
|
||||
//
|
||||
// Return early if IFR is disabled.
|
||||
//
|
||||
if (FxLibraryGlobals.IfrDisabled) {
|
||||
ASSERT(FxDriverGlobals->WdfLogHeader == NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (FxDriverGlobals == NULL || FxDriverGlobals->WdfLogHeader != NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
size = FxIFRGetSize(FxDriverGlobals, RegistryPath);
|
||||
|
||||
pHeader = (PWDF_IFR_HEADER) ExAllocatePoolWithTag(NonPagedPool,
|
||||
size,
|
||||
WDF_IFR_LOG_TAG );
|
||||
if (pHeader == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
RtlZeroMemory(pHeader, size);
|
||||
|
||||
//
|
||||
// Initialize the header.
|
||||
// Base will be where the IFR records are placed.
|
||||
// WPP_ThisDir_CTLGUID_FrameworksTraceGuid
|
||||
//
|
||||
RtlCopyMemory(&pHeader->Guid, (PVOID) &WdfTraceGuid, sizeof(GUID));
|
||||
|
||||
pHeader->Base = (PUCHAR) &pHeader[1];
|
||||
pHeader->Size = size - sizeof(WDF_IFR_HEADER);
|
||||
|
||||
pHeader->Offset.u.s.Current = 0;
|
||||
pHeader->Offset.u.s.Previous = 0;
|
||||
RtlStringCchCopyA(pHeader->DriverName, WDF_IFR_HEADER_NAME_LEN, FxDriverGlobals->Public.DriverName);
|
||||
|
||||
FxDriverGlobals->WdfLogHeader = pHeader;
|
||||
|
||||
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGDRIVER,
|
||||
"FxIFR logging started" );
|
||||
|
||||
if (size > FxIFRMinLogSize) {
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_INFORMATION, TRACINGDRIVER,
|
||||
"FxIFR has been started with a size override: size 0x%x bytes, "
|
||||
"# Pages %d. An extended IFR size may not be written to a minidump!",
|
||||
size, size/PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FxIFRStop(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine stops the In-Flight Recorder (IFR).
|
||||
|
||||
It should be called as late in the driver teardown as possible
|
||||
to allow for the capture of all significant events.
|
||||
|
||||
--*/
|
||||
{
|
||||
//
|
||||
// Return early if IFR is disabled.
|
||||
//
|
||||
if (FxLibraryGlobals.IfrDisabled) {
|
||||
ASSERT(FxDriverGlobals->WdfLogHeader == NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (FxDriverGlobals == NULL || FxDriverGlobals->WdfLogHeader == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Free the Log buffer.
|
||||
//
|
||||
ExFreePoolWithTag( FxDriverGlobals->WdfLogHeader, WDF_IFR_LOG_TAG );
|
||||
FxDriverGlobals->WdfLogHeader = NULL;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxIFR(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in UCHAR MessageLevel,
|
||||
__in ULONG MessageFlags,
|
||||
__in LPGUID MessageGuid,
|
||||
__in USHORT MessageNumber,
|
||||
__in ...
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
|
||||
This routine is the main In-Flight Recorder (IFR) routine.
|
||||
|
||||
It captures a WPP message to the IFR log.
|
||||
The IFR is always running, e.g. not WPP logger is necessary
|
||||
to start logging.
|
||||
|
||||
Arguments:
|
||||
|
||||
MessageLevel - The WPP message level for this event
|
||||
MessageFlags - The WPP message flags for this event (see trace GUID)
|
||||
MessageGuid - The tracewpp generated guid for module emitting this event.
|
||||
MessageNumber - The tracewpp generated message number within
|
||||
the emitting module.
|
||||
... - Variable arguments associates with the emitted message.
|
||||
|
||||
Returns:
|
||||
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
{
|
||||
size_t size;
|
||||
PWDF_IFR_RECORD record;
|
||||
PWDF_IFR_HEADER header;
|
||||
|
||||
UNREFERENCED_PARAMETER( MessageLevel );
|
||||
UNREFERENCED_PARAMETER( MessageFlags );
|
||||
|
||||
//
|
||||
// Return early if IFR is disabled.
|
||||
//
|
||||
if (FxLibraryGlobals.IfrDisabled) {
|
||||
ASSERT(FxDriverGlobals->WdfLogHeader == NULL);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if ( FxDriverGlobals->WdfLogHeader == NULL) {
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
//
|
||||
// Determine the number bytes to follow header
|
||||
//
|
||||
size = 0; // For Count of Bytes
|
||||
|
||||
//
|
||||
// Determine how much log space is needed for this
|
||||
// trace record's data.
|
||||
//
|
||||
{
|
||||
va_list ap;
|
||||
size_t argLen;
|
||||
|
||||
va_start(ap, MessageNumber);
|
||||
#pragma prefast(suppress: __WARNING_BUFFER_OVERFLOW, "Recommneded by EndClean");
|
||||
while ((va_arg(ap, PVOID)) != NULL) {
|
||||
|
||||
argLen = va_arg(ap, size_t);
|
||||
|
||||
if (argLen > 0) {
|
||||
|
||||
if (argLen > FxIFRMaxMessageSize) {
|
||||
goto drop_message;
|
||||
}
|
||||
size += (USHORT) argLen;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
//
|
||||
// NOTE: The final size must be 32-bit (ULONG) aligned.
|
||||
// This is necessary for IA64 to prevent Alignment Faults.
|
||||
//
|
||||
size += (size % sizeof(ULONG)) ? sizeof(ULONG) - (size % sizeof(ULONG)) : 0;
|
||||
|
||||
if (size > FxIFRMaxMessageSize) {
|
||||
goto drop_message;
|
||||
}
|
||||
}
|
||||
|
||||
size += sizeof(WDF_IFR_RECORD);
|
||||
|
||||
//
|
||||
// Allocate log space of the calculated size
|
||||
//
|
||||
{
|
||||
WDF_IFR_OFFSET offsetRet;
|
||||
WDF_IFR_OFFSET offsetCur;
|
||||
WDF_IFR_OFFSET offsetNew;
|
||||
USHORT usSize = (USHORT) size; // for a prefast artifact.
|
||||
|
||||
header = (PWDF_IFR_HEADER) FxDriverGlobals->WdfLogHeader;
|
||||
|
||||
FxVerifyLogHeader(FxDriverGlobals, header);
|
||||
|
||||
offsetRet.u.AsLONG = header->Offset.u.AsLONG;
|
||||
offsetNew.u.AsLONG = offsetRet.u.s.Current;
|
||||
|
||||
do {
|
||||
offsetCur.u.AsLONG = offsetRet.u.AsLONG;
|
||||
|
||||
if (&header->Base[header->Size] < &header->Base[offsetCur.u.s.Current+size]) {
|
||||
|
||||
offsetNew.u.s.Current = 0;
|
||||
offsetNew.u.s.Previous = offsetRet.u.s.Previous;
|
||||
|
||||
offsetRet.u.AsLONG =
|
||||
InterlockedCompareExchange( &header->Offset.u.AsLONG,
|
||||
offsetNew.u.AsLONG,
|
||||
offsetCur.u.AsLONG );
|
||||
|
||||
if (offsetCur.u.AsLONG != offsetRet.u.AsLONG) {
|
||||
continue;
|
||||
} else {
|
||||
offsetNew.u.s.Current = offsetCur.u.s.Current + usSize;
|
||||
offsetNew.u.s.Previous = offsetRet.u.s.Current;
|
||||
}
|
||||
} else {
|
||||
|
||||
offsetNew.u.s.Current = offsetCur.u.s.Current + usSize;
|
||||
offsetNew.u.s.Previous = offsetCur.u.s.Current;
|
||||
}
|
||||
|
||||
offsetRet.u.AsLONG =
|
||||
InterlockedCompareExchange( &header->Offset.u.AsLONG,
|
||||
offsetNew.u.AsLONG,
|
||||
offsetCur.u.AsLONG );
|
||||
|
||||
} while (offsetCur.u.AsLONG != offsetRet.u.AsLONG);
|
||||
|
||||
record = (PWDF_IFR_RECORD) &header->Base[offsetRet.u.s.Current];
|
||||
|
||||
// RtlZeroMemory( record, sizeof(WDF_IFR_RECORD) );
|
||||
|
||||
//
|
||||
// Build record (fill all fields!)
|
||||
//
|
||||
record->Signature = FxIFRRecordSignature;
|
||||
record->Length = (USHORT) size;
|
||||
record->PrevOffset = (USHORT) offsetRet.u.s.Previous;
|
||||
record->MessageNumber = MessageNumber;
|
||||
record->Sequence = InterlockedIncrement( &header->Sequence );
|
||||
record->MessageGuid = *MessageGuid;
|
||||
}
|
||||
|
||||
//
|
||||
// Move variable part of data into log.
|
||||
//
|
||||
{
|
||||
va_list ap;
|
||||
size_t argLen;
|
||||
PVOID source;
|
||||
PUCHAR argsData;
|
||||
|
||||
argsData = (UCHAR*) &record[1];
|
||||
|
||||
va_start(ap, MessageNumber);
|
||||
|
||||
while ((source = va_arg(ap, PVOID)) != NULL) {
|
||||
|
||||
argLen = va_arg(ap, size_t);
|
||||
|
||||
if (argLen > 0) {
|
||||
|
||||
RtlCopyMemory( argsData, source, argLen );
|
||||
argsData += argLen;
|
||||
}
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
FxVerifyLogHeader(FxDriverGlobals, header);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
|
||||
{
|
||||
//
|
||||
// Increment sequence number to indicate dropped message
|
||||
//
|
||||
drop_message:
|
||||
header = (PWDF_IFR_HEADER) FxDriverGlobals->WdfLogHeader;
|
||||
InterlockedIncrement( &header->Sequence );
|
||||
return STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
}
|
173
sdk/lib/drivers/wdf/kmdf/src/dma/base/fxcommonbuffer.cpp
Normal file
173
sdk/lib/drivers/wdf/kmdf/src/dma/base/fxcommonbuffer.cpp
Normal file
|
@ -0,0 +1,173 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxCommonBuffer.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
WDF CommonBuffer Object
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only.
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "FxDmaPCH.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxCommonBuffer.tmh"
|
||||
}
|
||||
|
||||
FxCommonBuffer::FxCommonBuffer(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in FxDmaEnabler * pDmaEnabler
|
||||
) :
|
||||
FxNonPagedObject(FX_TYPE_COMMON_BUFFER, sizeof(FxCommonBuffer), FxDriverGlobals)
|
||||
{
|
||||
m_DmaEnabler = pDmaEnabler;
|
||||
m_BufferRawVA = NULL; // allocated buffer base (unaligned)
|
||||
m_BufferAlignedVA = NULL; // aligned buffer base
|
||||
m_BufferAlignedLA.QuadPart = NULL; // aligned physical buffer base
|
||||
m_BufferRawLA.QuadPart = NULL; // allocated buffer phy base (unaligned)
|
||||
m_Length = 0;
|
||||
m_RawLength = 0;
|
||||
|
||||
MarkDisposeOverride(ObjectDoNotLock);
|
||||
|
||||
//
|
||||
// By default use the alignment of the dma enabler.
|
||||
//
|
||||
m_Alignment = m_DmaEnabler->GetAlignment();
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxCommonBuffer::Dispose()
|
||||
{
|
||||
FreeCommonBuffer();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxCommonBuffer::AllocateCommonBuffer(
|
||||
__in size_t Length
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals = GetDriverGlobals();
|
||||
ULONGLONG offset;
|
||||
ULONG result;
|
||||
|
||||
//
|
||||
// Must be running at PASIVE_LEVEL
|
||||
//
|
||||
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
m_Length = Length;
|
||||
|
||||
//
|
||||
// If required, add alignment to the length.
|
||||
// If alignment is <= page-1, we actually don't need to do it b/c
|
||||
// AllocateCommonBuffer allocates at least a page of memory, regardless
|
||||
// of the requested Length. If driver version is < v1.11, we still add the
|
||||
// alignment to the length for compatibility.
|
||||
//
|
||||
if (m_Alignment > PAGE_SIZE-1 ||
|
||||
pFxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,11) == FALSE) {
|
||||
|
||||
status = RtlSizeTAdd(Length, m_Alignment, &m_RawLength);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"WDFDMAENABLER %p AllocateCommonBuffer: overflow when adding Length "
|
||||
"%I64d + Alignment %I64d", GetObjectHandle(), Length, m_Alignment);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_RawLength = Length;
|
||||
}
|
||||
|
||||
m_DmaEnabler->AllocateCommonBuffer(m_RawLength,
|
||||
&m_BufferRawVA,
|
||||
&m_BufferRawLA);
|
||||
if (m_BufferRawVA) {
|
||||
|
||||
m_BufferAlignedVA = FX_ALIGN_VIRTUAL_ADDRESS(m_BufferRawVA, m_Alignment);
|
||||
m_BufferAlignedLA.QuadPart = FX_ALIGN_LOGICAL_ADDRESS(m_BufferRawLA, m_Alignment);
|
||||
|
||||
if (m_Alignment > PAGE_SIZE-1) {
|
||||
//
|
||||
// If the alignment mask is over a page-size then the aligned virtual
|
||||
// and aligned logical could be pointing to different locations
|
||||
// in memory. So ajdust the VA to match the LA address by adding
|
||||
// the offset of alignedLA and RawLA to VA. By doing this we
|
||||
// only guarantee alignment of LA when the page alignment exceeds PAGE_SIZE.
|
||||
//
|
||||
status = RtlULongLongSub(m_BufferAlignedLA.QuadPart,
|
||||
m_BufferRawLA.QuadPart,
|
||||
&offset);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"WDFDMAENABLER %p AllocateCommonBuffer: overflow when subtracting "
|
||||
"RawLA %I64x from AlignedLA %I64x",
|
||||
GetObjectHandle(), m_BufferRawLA.QuadPart, m_BufferAlignedLA.QuadPart);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = RtlULongLongToULong(offset, &result);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"WDFDMAENABLER %p AllocateCommonBuffer: overflow when "
|
||||
"converting from ULongLong %I64d to ULong",
|
||||
GetObjectHandle(), offset);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return status;
|
||||
}
|
||||
|
||||
m_BufferAlignedVA = WDF_PTR_ADD_OFFSET(m_BufferRawVA, result);
|
||||
}
|
||||
else {
|
||||
ASSERT(m_BufferAlignedVA == m_BufferRawVA);
|
||||
ASSERT(m_BufferAlignedLA.QuadPart == m_BufferRawLA.QuadPart);
|
||||
}
|
||||
} else {
|
||||
m_Length = 0;
|
||||
m_RawLength = 0;
|
||||
m_BufferAlignedVA = NULL;
|
||||
m_BufferAlignedLA.QuadPart = NULL;
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxCommonBuffer::FreeCommonBuffer(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// Free this CommonBuffer per DmaEnabler
|
||||
//
|
||||
if (m_BufferRawVA != NULL) {
|
||||
m_DmaEnabler->FreeCommonBuffer((ULONG) m_RawLength,
|
||||
m_BufferRawVA,
|
||||
m_BufferRawLA);
|
||||
}
|
||||
}
|
||||
|
||||
|
303
sdk/lib/drivers/wdf/kmdf/src/dma/base/fxcommonbufferapi.cpp
Normal file
303
sdk/lib/drivers/wdf/kmdf/src/dma/base/fxcommonbufferapi.cpp
Normal file
|
@ -0,0 +1,303 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxCommonBufferAPI.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Base for WDF CommonBuffer APIs
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only.
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "FxDmaPCH.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxCommonBufferAPI.tmh"
|
||||
}
|
||||
|
||||
//
|
||||
// Extern "C" the entire file
|
||||
//
|
||||
extern "C" {
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfCommonBufferCreate)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDMAENABLER DmaEnabler,
|
||||
__in
|
||||
__drv_when(Length == 0, __drv_reportError(Length cannot be zero))
|
||||
size_t Length,
|
||||
__in_opt
|
||||
WDF_OBJECT_ATTRIBUTES * Attributes,
|
||||
__out
|
||||
WDFCOMMONBUFFER * CommonBufferHandle
|
||||
)
|
||||
{
|
||||
FxCommonBuffer * pComBuf;
|
||||
FxDmaEnabler * pDmaEnabler;
|
||||
NTSTATUS status;
|
||||
WDFOBJECT handle;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
|
||||
//
|
||||
// Get validate DmaEnabler handle
|
||||
//
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DmaEnabler,
|
||||
FX_TYPE_DMA_ENABLER,
|
||||
(PVOID *) &pDmaEnabler,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, CommonBufferHandle);
|
||||
|
||||
*CommonBufferHandle = NULL;
|
||||
|
||||
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Basic parameter validation
|
||||
//
|
||||
if (Length == 0) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"Length is 0, %!STATUS!", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = FxValidateObjectAttributes(pFxDriverGlobals,
|
||||
Attributes,
|
||||
FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a new CommonBuffer object
|
||||
//
|
||||
pComBuf = new(pFxDriverGlobals, Attributes)
|
||||
FxCommonBuffer(pFxDriverGlobals, pDmaEnabler);
|
||||
|
||||
if (pComBuf == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"Could not allocate memory for a WDFCOMMONBUFFER, "
|
||||
"%!STATUS!", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Assign this FxCommonBuffer to its parent FxDmaEnabler object.
|
||||
//
|
||||
status = pComBuf->Commit(Attributes, (WDFOBJECT*)&handle, pDmaEnabler);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
//
|
||||
// Ok: now allocate a CommonBuffer via this DmaEnabler
|
||||
//
|
||||
status = pComBuf->AllocateCommonBuffer( Length );
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
//
|
||||
// Only return a valid handle on success.
|
||||
//
|
||||
*CommonBufferHandle = (WDFCOMMONBUFFER) handle;
|
||||
}
|
||||
else {
|
||||
pComBuf->DeleteFromFailedCreate();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfCommonBufferCreateWithConfig)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDMAENABLER DmaEnabler,
|
||||
__in
|
||||
__drv_when(Length == 0, __drv_reportError(Length cannot be zero))
|
||||
size_t Length,
|
||||
__in
|
||||
PWDF_COMMON_BUFFER_CONFIG Config,
|
||||
__in_opt
|
||||
WDF_OBJECT_ATTRIBUTES * Attributes,
|
||||
__out
|
||||
WDFCOMMONBUFFER * CommonBufferHandle
|
||||
)
|
||||
{
|
||||
FxCommonBuffer * pComBuf;
|
||||
FxDmaEnabler * pDmaEnabler;
|
||||
NTSTATUS status;
|
||||
WDFOBJECT handle;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
|
||||
//
|
||||
// Get validate DmaEnabler handle
|
||||
//
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DmaEnabler,
|
||||
FX_TYPE_DMA_ENABLER,
|
||||
(PVOID *) &pDmaEnabler,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
//
|
||||
// Basic parameter validation
|
||||
//
|
||||
FxPointerNotNull(pFxDriverGlobals, Config);
|
||||
|
||||
if (Config->Size != sizeof(WDF_COMMON_BUFFER_CONFIG)) {
|
||||
status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"WDF_COMMON_BUFFER_CONFIG Size 0x%x, expected 0x%x, %!STATUS!",
|
||||
Config->Size, sizeof(WDF_COMMON_BUFFER_CONFIG), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, CommonBufferHandle);
|
||||
|
||||
*CommonBufferHandle = NULL;
|
||||
|
||||
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (Length == 0) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"Length is 0, %!STATUS!", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = FxValidateObjectAttributes(pFxDriverGlobals,
|
||||
Attributes,
|
||||
FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED
|
||||
);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
pComBuf = new(pFxDriverGlobals, Attributes)
|
||||
FxCommonBuffer(pFxDriverGlobals, pDmaEnabler);
|
||||
|
||||
if (pComBuf == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"Could not allocate memory for a WDFCOMMONBUFFER, "
|
||||
"%!STATUS!", status);
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Assign this FxCommonBuffer to its parent FxDmaEnabler object.
|
||||
//
|
||||
status = pComBuf->Commit(Attributes, (WDFOBJECT*)&handle, pDmaEnabler);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
//
|
||||
// Set the alignment value before calling AllocateCommonBuffer.
|
||||
//
|
||||
pComBuf->SetAlignment(Config->AlignmentRequirement);
|
||||
status = pComBuf->AllocateCommonBuffer( Length );
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
//
|
||||
// Only return a valid handle on success.
|
||||
//
|
||||
*CommonBufferHandle = (WDFCOMMONBUFFER) handle;
|
||||
}
|
||||
else {
|
||||
pComBuf->DeleteFromFailedCreate();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
PVOID
|
||||
WDFEXPORT(WdfCommonBufferGetAlignedVirtualAddress)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCOMMONBUFFER CommonBuffer
|
||||
)
|
||||
{
|
||||
FxCommonBuffer * pComBuf;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
CommonBuffer,
|
||||
FX_TYPE_COMMON_BUFFER,
|
||||
(PVOID *) &pComBuf);
|
||||
|
||||
return pComBuf->GetAlignedVirtualAddress();
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
PHYSICAL_ADDRESS
|
||||
WDFEXPORT(WdfCommonBufferGetAlignedLogicalAddress)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCOMMONBUFFER CommonBuffer
|
||||
)
|
||||
{
|
||||
FxCommonBuffer * pComBuf;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
CommonBuffer,
|
||||
FX_TYPE_COMMON_BUFFER,
|
||||
(PVOID *) &pComBuf);
|
||||
|
||||
return pComBuf->GetAlignedLogicalAddress();
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
size_t
|
||||
WDFEXPORT(WdfCommonBufferGetLength)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFCOMMONBUFFER CommonBuffer
|
||||
)
|
||||
{
|
||||
FxCommonBuffer * pComBuf;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
CommonBuffer,
|
||||
FX_TYPE_COMMON_BUFFER,
|
||||
(PVOID *) &pComBuf);
|
||||
|
||||
return pComBuf->GetLength();
|
||||
}
|
||||
|
||||
} // extern "C"
|
1125
sdk/lib/drivers/wdf/kmdf/src/dma/base/fxdmaenabler.cpp
Normal file
1125
sdk/lib/drivers/wdf/kmdf/src/dma/base/fxdmaenabler.cpp
Normal file
File diff suppressed because it is too large
Load diff
516
sdk/lib/drivers/wdf/kmdf/src/dma/base/fxdmaenablerapi.cpp
Normal file
516
sdk/lib/drivers/wdf/kmdf/src/dma/base/fxdmaenablerapi.cpp
Normal file
|
@ -0,0 +1,516 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxDmaEnablerAPI.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Base for WDF DMA Enabler object APIs
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only.
|
||||
|
||||
Notes:
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "FxDmaPCH.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxDmaEnablerAPI.tmh"
|
||||
}
|
||||
|
||||
//
|
||||
// Extern "C" the entire file
|
||||
//
|
||||
extern "C" {
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfDmaEnablerCreate)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Device,
|
||||
__in
|
||||
WDF_DMA_ENABLER_CONFIG * Config,
|
||||
__in_opt
|
||||
WDF_OBJECT_ATTRIBUTES * Attributes,
|
||||
__out
|
||||
WDFDMAENABLER * DmaEnablerHandle
|
||||
)
|
||||
{
|
||||
FxDmaEnabler * pDmaEnabler;
|
||||
FxDeviceBase * pDevice;
|
||||
NTSTATUS status;
|
||||
WDFDMAENABLER handle;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxObject * pParent;
|
||||
WDF_DMA_ENABLER_CONFIG dmaConfig;
|
||||
|
||||
//
|
||||
// Validate the Device handle
|
||||
//
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
FX_TYPE_DEVICE_BASE,
|
||||
(PVOID *) &pDevice,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, DmaEnablerHandle);
|
||||
FxPointerNotNull(pFxDriverGlobals, Config);
|
||||
|
||||
*DmaEnablerHandle = NULL;
|
||||
|
||||
status = FxValidateObjectAttributes(pFxDriverGlobals, Attributes);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (Attributes != NULL && Attributes->ParentObject != NULL) {
|
||||
FxObjectHandleGetPtr(pFxDriverGlobals,
|
||||
Attributes->ParentObject,
|
||||
FX_TYPE_OBJECT,
|
||||
(PVOID*)&pParent);
|
||||
|
||||
if (pFxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,11)) {
|
||||
FxDeviceBase * pSearchDevice;
|
||||
|
||||
//
|
||||
// If a parent object is passed-in it must be descendent of device.
|
||||
// DmaEnabler stores device and uses it during dispose
|
||||
// (to remove it from dmaenabler list maintained at device level),
|
||||
// so DmaEnabler cannot outlive device.
|
||||
//
|
||||
|
||||
pSearchDevice = FxDeviceBase::_SearchForDevice(pParent, NULL);
|
||||
|
||||
if (pSearchDevice == NULL) {
|
||||
status = STATUS_WDF_OBJECT_ATTRIBUTES_INVALID;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"Attributes->ParentObject 0x%p must have WDFDEVICE as an "
|
||||
"eventual ancestor, %!STATUS!",
|
||||
Attributes->ParentObject, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
else if (pSearchDevice != pDevice) {
|
||||
status = STATUS_WDF_OBJECT_ATTRIBUTES_INVALID;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"Attributes->ParentObject 0x%p ancestor is WDFDEVICE %p, but "
|
||||
"not the same WDFDEVICE 0x%p passed to WdfDmaEnablerCreate, "
|
||||
"%!STATUS!",
|
||||
Attributes->ParentObject, pSearchDevice->GetHandle(),
|
||||
Device, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// For < 1.11 drivers we only allow pDevice to be the parent
|
||||
// since that is what we were blindly setting the parent to.
|
||||
//
|
||||
// Using the passed-in parent for such drivers could cause
|
||||
// side-effects such as earlier deletion of DmaEnabler object. So
|
||||
// we don't do that.
|
||||
//
|
||||
// We cause this verifier breakpoint to warn downlevel drivers
|
||||
// that the parent they passed in gets ignored.
|
||||
//
|
||||
if (pParent != pDevice) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_WARNING, TRACINGDMA,
|
||||
"For drivers bound to version <= 1.9 "
|
||||
"WdfDmaEnablerCreate uses WDFDEVICE as the "
|
||||
"parent object for the dma enabler object. "
|
||||
"Attributes->ParentObject 0x%p, which is different from "
|
||||
"WDFDEVICE 0x%p, gets ignored. Please note that DmaEnabler "
|
||||
"would be disposed only when device is disposed.",
|
||||
Attributes->ParentObject, Device);
|
||||
|
||||
if (pFxDriverGlobals->IsDownlevelVerificationEnabled()) {
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
}
|
||||
}
|
||||
|
||||
pParent = pDevice;
|
||||
}
|
||||
}
|
||||
else {
|
||||
pParent = pDevice;
|
||||
}
|
||||
|
||||
{
|
||||
ULONG expectedSize = pFxDriverGlobals->IsVersionGreaterThanOrEqualTo(1,11) ?
|
||||
sizeof(WDF_DMA_ENABLER_CONFIG) :
|
||||
sizeof(WDF_DMA_ENABLER_CONFIG_V1_9);
|
||||
|
||||
if (Config->Size != expectedSize) {
|
||||
status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"WDF_DMA_ENABLER_CONFIG Size 0x%x, expected 0x%x, %!STATUS!",
|
||||
Config->Size, expectedSize, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Normalize DMA config structure if necessary.
|
||||
//
|
||||
if (Config->Size < sizeof(WDF_DMA_ENABLER_CONFIG)) {
|
||||
//
|
||||
// Init new fields to default values.
|
||||
//
|
||||
WDF_DMA_ENABLER_CONFIG_INIT(&dmaConfig,
|
||||
Config->Profile,
|
||||
Config->MaximumLength);
|
||||
//
|
||||
// Copy over existing fields and readjust the struct size.
|
||||
//
|
||||
RtlCopyMemory(&dmaConfig, Config, Config->Size);
|
||||
dmaConfig.Size = sizeof(dmaConfig);
|
||||
|
||||
//
|
||||
// Use new config structure from now on.
|
||||
//
|
||||
Config = &dmaConfig;
|
||||
}
|
||||
}
|
||||
|
||||
switch (Config->Profile) {
|
||||
case WdfDmaProfilePacket:
|
||||
case WdfDmaProfileScatterGather:
|
||||
case WdfDmaProfilePacket64:
|
||||
case WdfDmaProfileScatterGather64:
|
||||
case WdfDmaProfileScatterGather64Duplex:
|
||||
case WdfDmaProfileScatterGatherDuplex:
|
||||
case WdfDmaProfileSystem:
|
||||
case WdfDmaProfileSystemDuplex:
|
||||
break;
|
||||
default:
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"DMA Profile value %d is unknown, %!STATUS!",
|
||||
Config->Profile, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (Config->MaximumLength == 0) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"Config MaximumLength of zero is invalid, %!STATUS!",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Ok: create a new DmaEnabler
|
||||
//
|
||||
pDmaEnabler = new(pFxDriverGlobals, Attributes)
|
||||
FxDmaEnabler( pFxDriverGlobals );
|
||||
|
||||
if (pDmaEnabler == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"Could not allocate memory for a WDFDMAENABLER, "
|
||||
"%!STATUS!", status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Assign this FxDmaEnabler to its parent FxDevice object.
|
||||
//
|
||||
status = pDmaEnabler->Commit(Attributes, (WDFOBJECT*)&handle, pParent);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
//
|
||||
// Ok: start this DmaEnabler.
|
||||
//
|
||||
status = pDmaEnabler->Initialize( Config, pDevice );
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
//
|
||||
// Only return a valid handle on success.
|
||||
//
|
||||
*DmaEnablerHandle = handle;
|
||||
}
|
||||
else {
|
||||
pDmaEnabler->DeleteFromFailedCreate();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
size_t
|
||||
WDFEXPORT(WdfDmaEnablerGetMaximumLength)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDMAENABLER DmaEnabler
|
||||
)
|
||||
{
|
||||
FxDmaEnabler * pDmaEnabler;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
DmaEnabler,
|
||||
FX_TYPE_DMA_ENABLER,
|
||||
(PVOID *) &pDmaEnabler);
|
||||
|
||||
return pDmaEnabler->GetMaximumLength();
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
size_t
|
||||
WDFEXPORT(WdfDmaEnablerGetMaximumScatterGatherElements)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDMAENABLER DmaEnabler
|
||||
)
|
||||
{
|
||||
FxDmaEnabler * pDmaEnabler;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
DmaEnabler,
|
||||
FX_TYPE_DMA_ENABLER,
|
||||
(PVOID *) &pDmaEnabler);
|
||||
|
||||
return pDmaEnabler->GetMaxSGElements();
|
||||
}
|
||||
|
||||
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
VOID
|
||||
WDFEXPORT(WdfDmaEnablerSetMaximumScatterGatherElements)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDMAENABLER DmaEnabler,
|
||||
__in
|
||||
__drv_when(MaximumElements == 0, __drv_reportError(MaximumElements cannot be zero))
|
||||
size_t MaximumElements
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxDmaEnabler * pDmaEnabler;
|
||||
NTSTATUS status;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DmaEnabler,
|
||||
FX_TYPE_DMA_ENABLER,
|
||||
(PVOID *) &pDmaEnabler,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (MaximumElements == 0) {
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"Cannot set MaximumElements of zero on WDFDMAENABLER %p",
|
||||
DmaEnabler);
|
||||
return;
|
||||
}
|
||||
|
||||
pDmaEnabler->SetMaxSGElements(MaximumElements);
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
size_t
|
||||
WDFEXPORT(WdfDmaEnablerGetFragmentLength)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDMAENABLER DmaEnabler,
|
||||
__in
|
||||
WDF_DMA_DIRECTION DmaDirection
|
||||
)
|
||||
{
|
||||
FxDmaEnabler * pDmaEnabler;
|
||||
size_t length;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DmaEnabler,
|
||||
FX_TYPE_DMA_ENABLER,
|
||||
(PVOID *) &pDmaEnabler,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
switch (DmaDirection) {
|
||||
|
||||
case WdfDmaDirectionReadFromDevice:
|
||||
length = pDmaEnabler->GetReadDmaDescription()->MaximumFragmentLength;
|
||||
break;
|
||||
|
||||
case WdfDmaDirectionWriteToDevice:
|
||||
length = pDmaEnabler->GetWriteDmaDescription()->MaximumFragmentLength;
|
||||
break;
|
||||
|
||||
default:
|
||||
length = 0;
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"Invalid value for Dma direction %d, %p",
|
||||
DmaDirection, DmaEnabler);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
break;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
PDMA_ADAPTER
|
||||
WDFEXPORT(WdfDmaEnablerWdmGetDmaAdapter)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDMAENABLER DmaEnabler,
|
||||
__in
|
||||
WDF_DMA_DIRECTION DmaDirection
|
||||
)
|
||||
{
|
||||
PDMA_ADAPTER adapter;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxDmaEnabler * pDmaEnabler;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DmaEnabler,
|
||||
FX_TYPE_DMA_ENABLER,
|
||||
(PVOID *) &pDmaEnabler,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
switch (DmaDirection) {
|
||||
|
||||
case WdfDmaDirectionReadFromDevice:
|
||||
adapter = pDmaEnabler->GetReadDmaDescription()->AdapterObject;
|
||||
break;
|
||||
|
||||
case WdfDmaDirectionWriteToDevice:
|
||||
adapter = pDmaEnabler->GetWriteDmaDescription()->AdapterObject;
|
||||
break;
|
||||
|
||||
default:
|
||||
adapter = NULL;
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"Invalid value for Dma direction %d, %p",
|
||||
DmaDirection, DmaEnabler);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
break;
|
||||
}
|
||||
|
||||
return adapter;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfDmaEnablerConfigureSystemProfile)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDMAENABLER DmaEnabler,
|
||||
__in
|
||||
PWDF_DMA_SYSTEM_PROFILE_CONFIG ProfileConfig,
|
||||
__in
|
||||
WDF_DMA_DIRECTION ConfigDirection
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxDmaEnabler * pDmaEnabler;
|
||||
|
||||
NTSTATUS status;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
DmaEnabler,
|
||||
FX_TYPE_DMA_ENABLER,
|
||||
(PVOID *) &pDmaEnabler,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
//
|
||||
// Verify the DMA config
|
||||
//
|
||||
|
||||
if (ProfileConfig == NULL)
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"ProfileConfig must be non-null, %!STATUS!",
|
||||
status);
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (ProfileConfig->Size != sizeof(WDF_DMA_SYSTEM_PROFILE_CONFIG))
|
||||
{
|
||||
status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"WDF_DMA_SYSTEM_PROFILE_CONFIG Size 0x%x, expected 0x%x, %!STATUS!",
|
||||
ProfileConfig->Size, sizeof(WDF_DMA_SYSTEM_PROFILE_CONFIG), status);
|
||||
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if (ProfileConfig->DmaDescriptor == NULL)
|
||||
{
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"ProfileConfig (%p) may not have NULL DmaDescriptor, %!STATUS!",
|
||||
ProfileConfig, status);
|
||||
|
||||
FxVerifierDbgBreakPoint(pFxDriverGlobals);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if (ConfigDirection != WdfDmaDirectionReadFromDevice &&
|
||||
ConfigDirection != WdfDmaDirectionWriteToDevice) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDMA,
|
||||
"ConfigDirection 0x%x is an invalid value, %!STATUS!",
|
||||
ConfigDirection, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
status = pDmaEnabler->ConfigureSystemAdapter(ProfileConfig,
|
||||
ConfigDirection);
|
||||
return status;
|
||||
}
|
||||
|
||||
} // extern "C"
|
7
sdk/lib/drivers/wdf/kmdf/src/dma/base/fxdmapch.hpp
Normal file
7
sdk/lib/drivers/wdf/kmdf/src/dma/base/fxdmapch.hpp
Normal file
|
@ -0,0 +1,7 @@
|
|||
//
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
//
|
||||
extern "C" {
|
||||
#include <ntddk.h>
|
||||
}
|
||||
#include <Fx.hpp>
|
2533
sdk/lib/drivers/wdf/kmdf/src/dma/base/fxdmatransaction.cpp
Normal file
2533
sdk/lib/drivers/wdf/kmdf/src/dma/base/fxdmatransaction.cpp
Normal file
File diff suppressed because it is too large
Load diff
1251
sdk/lib/drivers/wdf/kmdf/src/dma/base/fxdmatransactionapi.cpp
Normal file
1251
sdk/lib/drivers/wdf/kmdf/src/dma/base/fxdmatransactionapi.cpp
Normal file
File diff suppressed because it is too large
Load diff
760
sdk/lib/drivers/wdf/kmdf/src/dynamic/version/version.cpp
Normal file
760
sdk/lib/drivers/wdf/kmdf/src/dynamic/version/version.cpp
Normal file
|
@ -0,0 +1,760 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
Version.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module forms a loadable library from the WDF core libs
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ntverp.h>
|
||||
|
||||
extern "C" {
|
||||
#include <ntddk.h>
|
||||
#include <ntstrsafe.h>
|
||||
}
|
||||
|
||||
#define FX_DYNAMICS_GENERATE_TABLE 1
|
||||
|
||||
#include "fx.hpp"
|
||||
|
||||
#include <fxldr.h>
|
||||
#include "fxbugcheck.h"
|
||||
#include "wdfversionlog.h"
|
||||
|
||||
#define DRIVER_OBJECT_EXTENSION_IDENTIFIER DriverEntry
|
||||
#define DRIVER_PARAMETERS L"Parameters"
|
||||
#define REGISTRY_KMDF_MAJOR_VERSION L"MajorVersion"
|
||||
#define REGISTRY_KMDF_MINOR_VERSION L"MinorVersion"
|
||||
#define REGISTRY_KMDF_BUILD_NUMBER L"BuildNumber"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// These header files are referenced in order to make internal structures
|
||||
// available in public symbols. Various WDFKD debug commands use these
|
||||
// internal structures to provide information about WDF.
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "FxIFR.h"
|
||||
|
||||
extern "C" {
|
||||
|
||||
//
|
||||
// This is the collection of all structure/types to be make public.
|
||||
// This union forces the structure type-info into the PDB file.
|
||||
//
|
||||
union {
|
||||
|
||||
WDF_IFR_HEADER * typeWDF_IFR_HEADER;
|
||||
WDF_IFR_RECORD * typeWDF_IFR_RECORD;
|
||||
WDF_IFR_OFFSET * typeWDF_IFR_OFFSET;
|
||||
WDF_BIND_INFO * typeWDF_BIND_INFO;
|
||||
WDF_OBJECT_CONTEXT_TYPE_INFO * typeWDF_OBJECT_CONTEXT_TYPE_INFO;
|
||||
WDF_POWER_ROUTINE_TIMED_OUT_DATA * typeWDF_POWER_ROUTINE_TIMED_OUT_DATA;
|
||||
WDF_BUGCHECK_CODES * typeWDF_BUGCHECK_CODES;
|
||||
WDF_REQUEST_FATAL_ERROR_CODES * typeWDF_REQUEST_FATAL_ERROR_CODES;
|
||||
FX_OBJECT_INFO * typeFX_OBJECT_INFO;
|
||||
FX_POOL_HEADER * typeFX_POOL_HEADER;
|
||||
FX_POOL * typeFX_POOL;
|
||||
FxObject * typeFxObject;
|
||||
FxContextHeader * typeFxContextHeader;
|
||||
FX_DUMP_DRIVER_INFO_ENTRY * typeFX_DUMP_DRIVER_INFO_ENTRY;
|
||||
FxTargetSubmitSyncParams * typeFxTargetSubmitSyncParams;
|
||||
|
||||
} uAllPublicTypes;
|
||||
|
||||
} // extern "C" end
|
||||
|
||||
//----------------------------------------- ------------------------------------
|
||||
|
||||
extern "C" {
|
||||
|
||||
#include "FxDynamics.h"
|
||||
|
||||
#include "FxLibraryCommon.h"
|
||||
|
||||
#define KMDF_DEFAULT_NAME "Wdf" ## \
|
||||
LITERAL(__WDF_MAJOR_VERSION_STRING) ## \
|
||||
"000" //minor version
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// local prototype definitions
|
||||
//-----------------------------------------------------------------------------
|
||||
extern "C"
|
||||
DRIVER_UNLOAD DriverUnload;
|
||||
|
||||
extern "C"
|
||||
DRIVER_INITIALIZE DriverEntry;
|
||||
|
||||
extern "C"
|
||||
__drv_dispatchType(IRP_MJ_CREATE)
|
||||
__drv_dispatchType(IRP_MJ_CLEANUP)
|
||||
__drv_dispatchType(IRP_MJ_CLOSE)
|
||||
DRIVER_DISPATCH FxLibraryDispatch;
|
||||
|
||||
RTL_OSVERSIONINFOW gOsVersion = { sizeof(RTL_OSVERSIONINFOW) };
|
||||
|
||||
ULONG WdfLdrDbgPrintOn = 0;
|
||||
|
||||
PCHAR WdfLdrType = KMDF_DEFAULT_NAME;
|
||||
|
||||
} // extern "C"
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
extern "C"
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
WDF_LIBRARY_COMMISSION(
|
||||
VOID
|
||||
);
|
||||
|
||||
extern "C"
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
WDF_LIBRARY_DECOMMISSION(
|
||||
VOID
|
||||
);
|
||||
|
||||
extern "C"
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
WDF_LIBRARY_REGISTER_CLIENT(
|
||||
__inout PWDF_BIND_INFO Info,
|
||||
__deref_out PWDF_DRIVER_GLOBALS * WdfDriverGlobals,
|
||||
__deref_inout PVOID * Context
|
||||
);
|
||||
|
||||
extern "C"
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
WDF_LIBRARY_UNREGISTER_CLIENT(
|
||||
__in PWDF_BIND_INFO Info,
|
||||
__in PWDF_DRIVER_GLOBALS WdfDriverGlobals
|
||||
);
|
||||
|
||||
extern "C"
|
||||
VOID
|
||||
FxLibraryDeleteDevice(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
FxLibraryCleanup(
|
||||
VOID
|
||||
);
|
||||
|
||||
VOID
|
||||
WdfWriteKmdfVersionToRegistry(
|
||||
__in PDRIVER_OBJECT DriverObject,
|
||||
__in PUNICODE_STRING RegistryPath
|
||||
);
|
||||
|
||||
VOID
|
||||
WdfDeleteKmdfVersionFromRegistry(
|
||||
__in PDRIVER_OBJECT DriverObject
|
||||
);
|
||||
|
||||
typedef struct _DRV_EXTENSION {
|
||||
UNICODE_STRING ParametersRegistryPath;
|
||||
} DRV_EXTENSION, *PDRV_EXTENSION;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Library registeration information
|
||||
//-----------------------------------------------------------------------------
|
||||
extern "C" {
|
||||
#pragma prefast(suppress:__WARNING_ENCODE_MEMBER_FUNCTION_POINTER, "kernel component.");
|
||||
WDF_LIBRARY_INFO WdfLibraryInfo = {
|
||||
sizeof(WDF_LIBRARY_INFO),
|
||||
(PFNLIBRARYCOMMISSION) WDF_LIBRARY_COMMISSION,
|
||||
(PFNLIBRARYDECOMMISSION) WDF_LIBRARY_DECOMMISSION,
|
||||
(PFNLIBRARYREGISTERCLIENT) WDF_LIBRARY_REGISTER_CLIENT,
|
||||
(PFNLIBRARYUNREGISTERCLIENT) WDF_LIBRARY_UNREGISTER_CLIENT,
|
||||
{ __WDF_MAJOR_VERSION, __WDF_MINOR_VERSION, __WDF_BUILD_NUMBER }
|
||||
};
|
||||
|
||||
} // extern "C" end
|
||||
|
||||
extern "C"
|
||||
NTSTATUS
|
||||
FxLibraryDispatch (
|
||||
__in struct _DEVICE_OBJECT * DeviceObject,
|
||||
__in PIRP Irp
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
UNREFERENCED_PARAMETER(DeviceObject);
|
||||
ASSERT(FxLibraryGlobals.LibraryDeviceObject == DeviceObject);
|
||||
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
switch (IoGetCurrentIrpStackLocation(Irp)->MajorFunction) {
|
||||
case IRP_MJ_CREATE:
|
||||
//
|
||||
// To limit our exposure for this device object, only allow kernel mode
|
||||
// creates.
|
||||
//
|
||||
if (Irp->RequestorMode == KernelMode) {
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
break;
|
||||
|
||||
case IRP_MJ_CLEANUP:
|
||||
case IRP_MJ_CLOSE:
|
||||
//
|
||||
// Since we allowed a create to succeed, succeed the cleanup and close
|
||||
//
|
||||
status = STATUS_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
Irp->IoStatus.Status = status;
|
||||
Irp->IoStatus.Information = 0x0;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#define KMDF_DEVICE_NAME L"\\Device\\KMDF"
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxLibraryCreateDevice(
|
||||
__in PUNICODE_STRING DeviceName
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG i;
|
||||
|
||||
i = 0;
|
||||
|
||||
//
|
||||
// Repeatedly try to create a named device object until we run out of buffer
|
||||
// space or we succeed.
|
||||
//
|
||||
do {
|
||||
status = RtlUnicodeStringPrintf(DeviceName, L"%s%d", KMDF_DEVICE_NAME, i++);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a device with no device extension
|
||||
//
|
||||
status = IoCreateDevice(
|
||||
FxLibraryGlobals.DriverObject,
|
||||
0,
|
||||
DeviceName,
|
||||
FILE_DEVICE_UNKNOWN,
|
||||
0,
|
||||
FALSE,
|
||||
&FxLibraryGlobals.LibraryDeviceObject
|
||||
);
|
||||
} while (STATUS_OBJECT_NAME_COLLISION == status);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
//
|
||||
// Clear the initializing bit now because the loader will attempt to
|
||||
// open the device before we return from DriverEntry
|
||||
//
|
||||
ASSERT(FxLibraryGlobals.LibraryDeviceObject != NULL);
|
||||
FxLibraryGlobals.LibraryDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
VOID
|
||||
FxLibraryDeleteDevice(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
FxLibraryCleanup();
|
||||
}
|
||||
|
||||
VOID
|
||||
FxLibraryCleanup(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
if (FxLibraryGlobals.LibraryDeviceObject != NULL) {
|
||||
IoDeleteDevice(FxLibraryGlobals.LibraryDeviceObject);
|
||||
FxLibraryGlobals.LibraryDeviceObject = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C"
|
||||
NTSTATUS
|
||||
DriverEntry(
|
||||
__in PDRIVER_OBJECT DriverObject,
|
||||
__in PUNICODE_STRING RegistryPath
|
||||
)
|
||||
{
|
||||
UNICODE_STRING name;
|
||||
UNICODE_STRING string;
|
||||
NTSTATUS status;
|
||||
|
||||
//
|
||||
// This creates a local buffer which is big enough to hold a copy of the
|
||||
// constant string assigned to it. It does not point to the constant
|
||||
// string. As such, it is a writeable buffer.
|
||||
//
|
||||
// NOTE: KMDF_DEVICE_NAME L"XXXX" creates a concatenated string of
|
||||
// KMDF_DEVICE_NAME + L"XXXX". This is done to give us room for
|
||||
// appending a number up to 4 digits long after KMDF_DEVICE_NAME if
|
||||
// you want a null terminated string, 5 digits long if the string is
|
||||
// not null terminated (as is the case for a UNICODE_STRING)
|
||||
//
|
||||
WCHAR buffer[] = KMDF_DEVICE_NAME L"XXXX";
|
||||
|
||||
//
|
||||
// Initialize global to make NonPagedPool be treated as NxPool on Win8
|
||||
// and NonPagedPool on down-level
|
||||
//
|
||||
ExInitializeDriverRuntime(DrvRtPoolNxOptIn);
|
||||
|
||||
RtlInitUnicodeString(&string, WDF_REGISTRY_DBGPRINT_ON);
|
||||
|
||||
//
|
||||
// Determine if debug prints are on.
|
||||
//
|
||||
(void) WdfLdrDiagnosticsValueByNameAsULONG(&string, &WdfLdrDbgPrintOn);
|
||||
|
||||
__Print(("DriverEntry\n"));
|
||||
|
||||
DriverObject->DriverUnload = DriverUnload;
|
||||
|
||||
FxLibraryGlobals.DriverObject = DriverObject;
|
||||
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = FxLibraryDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = FxLibraryDispatch;
|
||||
DriverObject->MajorFunction[IRP_MJ_CLOSE] = FxLibraryDispatch;
|
||||
|
||||
RtlZeroMemory(&name, sizeof(name));
|
||||
name.Buffer = buffer;
|
||||
name.Length = 0x0;
|
||||
name.MaximumLength = sizeof(buffer);
|
||||
|
||||
//
|
||||
// We use the string when we declare the buffer to get the right sized
|
||||
// buffer. Now we want to make sure there are no contents before we
|
||||
// use it to create a device object.
|
||||
//
|
||||
RtlZeroMemory(buffer, sizeof(buffer));
|
||||
|
||||
status = FxLibraryCreateDevice(&name);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
__Print(("ERROR: FxLibraryCreateDevice failed with Status 0x%x\n", status));
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Register this library with WdfLdr
|
||||
//
|
||||
// NOTE: Once WdfRegisterLibrary returns NT_SUCCESS() we must return
|
||||
// NT_SUCCESS from DriverEntry!
|
||||
//
|
||||
status = WdfRegisterLibrary( &WdfLibraryInfo, RegistryPath, &name );
|
||||
if (!NT_SUCCESS(status)) {
|
||||
__Print(("ERROR: WdfRegisterLibrary failed with Status 0x%x\n", status));
|
||||
FxLibraryCleanup();
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Write KMDF version to registry
|
||||
//
|
||||
WdfWriteKmdfVersionToRegistry(DriverObject, RegistryPath);
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
extern "C"
|
||||
VOID
|
||||
DriverUnload(
|
||||
__in PDRIVER_OBJECT DriverObject
|
||||
)
|
||||
{
|
||||
__Print(("DriverUnload\n"));
|
||||
|
||||
//
|
||||
// Delete KMDF version from registry before destroying the Driver Object
|
||||
//
|
||||
WdfDeleteKmdfVersionFromRegistry(DriverObject);
|
||||
|
||||
//
|
||||
// Make sure everything is deleted. Since the driver is considered a legacy
|
||||
// driver, it can be unloaded while there are still outstanding device objects.
|
||||
//
|
||||
FxLibraryCleanup();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
extern "C"
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
WDF_LIBRARY_COMMISSION(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return FxLibraryCommonCommission();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
extern "C"
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
WDF_LIBRARY_DECOMMISSION(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return FxLibraryCommonDecommission();
|
||||
}
|
||||
|
||||
#define EVTLOG_MESSAGE_SIZE 70
|
||||
#define RAW_DATA_SIZE 4
|
||||
|
||||
extern "C"
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
WDF_LIBRARY_REGISTER_CLIENT(
|
||||
__in PWDF_BIND_INFO Info,
|
||||
__deref_out PWDF_DRIVER_GLOBALS * WdfDriverGlobals,
|
||||
__deref_inout PVOID * Context
|
||||
)
|
||||
{
|
||||
NTSTATUS status = STATUS_INVALID_PARAMETER;
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
WCHAR insertString[EVTLOG_MESSAGE_SIZE];
|
||||
ULONG rawData[RAW_DATA_SIZE];
|
||||
PCLIENT_INFO clientInfo = NULL;
|
||||
|
||||
__Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) ": enter\n"));
|
||||
|
||||
clientInfo = (PCLIENT_INFO)*Context;
|
||||
*Context = NULL;
|
||||
|
||||
ASSERT(Info->Version.Major == WdfLibraryInfo.Version.Major);
|
||||
|
||||
//
|
||||
// NOTE: If the currently loaded library < drivers minor version fail the load
|
||||
// instead of binding to a lower minor version. The reason for that if there
|
||||
// is a newer API or new contract change made the driver shouldn't be using older
|
||||
// API than it was compiled with.
|
||||
//
|
||||
|
||||
if (Info->Version.Minor > WdfLibraryInfo.Version.Minor) {
|
||||
status = RtlStringCchPrintfW(insertString,
|
||||
RTL_NUMBER_OF(insertString),
|
||||
L"Driver Version: %d.%d Kmdf Lib. Version: %d.%d",
|
||||
Info->Version.Major,
|
||||
Info->Version.Minor,
|
||||
WdfLibraryInfo.Version.Major,
|
||||
WdfLibraryInfo.Version.Minor);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
__Print(("ERROR: RtlStringCchPrintfW failed with Status 0x%x\n", status));
|
||||
return status;
|
||||
}
|
||||
rawData[0] = Info->Version.Major;
|
||||
rawData[1] = Info->Version.Minor;
|
||||
rawData[2] = WdfLibraryInfo.Version.Major;
|
||||
rawData[3] = WdfLibraryInfo.Version.Minor;
|
||||
|
||||
LibraryLogEvent(FxLibraryGlobals.DriverObject,
|
||||
WDFVER_MINOR_VERSION_NOT_SUPPORTED,
|
||||
STATUS_OBJECT_TYPE_MISMATCH,
|
||||
insertString,
|
||||
rawData,
|
||||
sizeof(rawData) );
|
||||
//
|
||||
// this looks like the best status to return
|
||||
//
|
||||
return STATUS_OBJECT_TYPE_MISMATCH;
|
||||
|
||||
}
|
||||
|
||||
status = FxLibraryCommonRegisterClient(Info,
|
||||
WdfDriverGlobals,
|
||||
clientInfo);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
//
|
||||
// The context will be a pointer to FX_DRIVER_GLOBALS
|
||||
//
|
||||
*Context = GetFxDriverGlobals(*WdfDriverGlobals);
|
||||
|
||||
//
|
||||
// Set the WDF_BIND_INFO structure pointer in FxDriverGlobals
|
||||
//
|
||||
pFxDriverGlobals = GetFxDriverGlobals(*WdfDriverGlobals);
|
||||
pFxDriverGlobals->WdfBindInfo = Info;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
extern "C"
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
WDF_LIBRARY_UNREGISTER_CLIENT(
|
||||
__in PWDF_BIND_INFO Info,
|
||||
__in PWDF_DRIVER_GLOBALS WdfDriverGlobals
|
||||
)
|
||||
{
|
||||
return FxLibraryCommonUnregisterClient(Info, WdfDriverGlobals);
|
||||
}
|
||||
|
||||
VOID
|
||||
WdfWriteKmdfVersionToRegistry(
|
||||
__in PDRIVER_OBJECT DriverObject,
|
||||
__in PUNICODE_STRING RegistryPath
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
OBJECT_ATTRIBUTES objectAttributes;
|
||||
HANDLE driverKey;
|
||||
HANDLE parametersKey;
|
||||
UNICODE_STRING valueName;
|
||||
UNICODE_STRING parametersPath;
|
||||
PDRV_EXTENSION driverExtension;
|
||||
|
||||
driverKey = NULL;
|
||||
parametersKey = NULL;
|
||||
driverExtension = NULL;
|
||||
|
||||
RtlInitUnicodeString(¶metersPath, DRIVER_PARAMETERS);
|
||||
|
||||
InitializeObjectAttributes(&objectAttributes,
|
||||
RegistryPath,
|
||||
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
status = ZwOpenKey(&driverKey, KEY_CREATE_SUB_KEY, &objectAttributes);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
__Print(("WdfWriteKmdfVersionToRegistry: Failed to open HKLM\\%S\n",
|
||||
RegistryPath->Buffer));
|
||||
goto out;
|
||||
}
|
||||
|
||||
InitializeObjectAttributes(&objectAttributes,
|
||||
¶metersPath,
|
||||
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||
driverKey,
|
||||
NULL);
|
||||
|
||||
//
|
||||
// Open or create key and get a handle
|
||||
//
|
||||
status = ZwCreateKey(¶metersKey,
|
||||
KEY_SET_VALUE,
|
||||
&objectAttributes,
|
||||
0,
|
||||
(PUNICODE_STRING) NULL,
|
||||
REG_OPTION_VOLATILE,
|
||||
NULL);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
__Print(("WdfWriteKmdfVersionToRegistry: Failed to open HKLM\\%S\\%S\n",
|
||||
RegistryPath->Buffer, parametersPath.Buffer));
|
||||
goto out;
|
||||
}
|
||||
|
||||
//
|
||||
// Set Major Version
|
||||
//
|
||||
RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MAJOR_VERSION);
|
||||
|
||||
status = ZwSetValueKey(parametersKey,
|
||||
&valueName,
|
||||
0,
|
||||
REG_DWORD,
|
||||
&WdfLibraryInfo.Version.Major,
|
||||
sizeof(WdfLibraryInfo.Version.Major));
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
__Print(("WdfWriteKmdfVersionToRegistry: Failed to set Major Version\n"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
//
|
||||
// Set Minor Version
|
||||
//
|
||||
RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MINOR_VERSION);
|
||||
|
||||
status = ZwSetValueKey(parametersKey,
|
||||
&valueName,
|
||||
0,
|
||||
REG_DWORD,
|
||||
&WdfLibraryInfo.Version.Minor,
|
||||
sizeof(WdfLibraryInfo.Version.Minor));
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
__Print(("WdfWriteKmdfVersionToRegistry: Failed to set Minor Version\n"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Set Build Number
|
||||
//
|
||||
RtlInitUnicodeString(&valueName, REGISTRY_KMDF_BUILD_NUMBER);
|
||||
|
||||
status = ZwSetValueKey(parametersKey,
|
||||
&valueName,
|
||||
0,
|
||||
REG_DWORD,
|
||||
&WdfLibraryInfo.Version.Build,
|
||||
sizeof(WdfLibraryInfo.Version.Build));
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
__Print(("WdfWriteKmdfVersionToRegistry: Failed to set Build Number\n"));
|
||||
goto out;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a Driver Extension to store the registry path, where we write the
|
||||
// version of the wdf01000.sys that's loaded in memory
|
||||
//
|
||||
status = IoAllocateDriverObjectExtension(DriverObject,
|
||||
(PVOID) DRIVER_OBJECT_EXTENSION_IDENTIFIER,
|
||||
sizeof(DRV_EXTENSION),
|
||||
(PVOID *)&driverExtension);
|
||||
|
||||
if (!NT_SUCCESS(status) || driverExtension == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
driverExtension->ParametersRegistryPath.Buffer = (PWCHAR) ExAllocatePoolWithTag(
|
||||
PagedPool,
|
||||
RegistryPath->MaximumLength,
|
||||
FX_TAG);
|
||||
if (driverExtension->ParametersRegistryPath.Buffer == NULL) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
driverExtension->ParametersRegistryPath.MaximumLength = RegistryPath->MaximumLength;
|
||||
RtlCopyUnicodeString(&(driverExtension->ParametersRegistryPath), RegistryPath);
|
||||
|
||||
out:
|
||||
if (driverKey != NULL) {
|
||||
ZwClose(driverKey);
|
||||
}
|
||||
|
||||
if (parametersKey != NULL) {
|
||||
ZwClose(parametersKey);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
VOID
|
||||
WdfDeleteKmdfVersionFromRegistry(
|
||||
__in PDRIVER_OBJECT DriverObject
|
||||
)
|
||||
{
|
||||
PUNICODE_STRING registryPath;
|
||||
OBJECT_ATTRIBUTES objectAttributes;
|
||||
HANDLE driverKey;
|
||||
HANDLE parametersKey;
|
||||
UNICODE_STRING valueName;
|
||||
NTSTATUS status;
|
||||
UNICODE_STRING parametersPath;
|
||||
PDRV_EXTENSION driverExtension;
|
||||
|
||||
RtlInitUnicodeString(¶metersPath, DRIVER_PARAMETERS);
|
||||
|
||||
driverKey = NULL;
|
||||
parametersKey = NULL;
|
||||
|
||||
driverExtension = (PDRV_EXTENSION)IoGetDriverObjectExtension(DriverObject,
|
||||
DRIVER_OBJECT_EXTENSION_IDENTIFIER);
|
||||
|
||||
if (driverExtension == NULL || driverExtension->ParametersRegistryPath.Buffer == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
registryPath = &driverExtension->ParametersRegistryPath;
|
||||
|
||||
InitializeObjectAttributes(&objectAttributes,
|
||||
registryPath,
|
||||
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||
NULL,
|
||||
NULL);
|
||||
|
||||
status = ZwOpenKey(&driverKey, KEY_SET_VALUE, &objectAttributes);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
InitializeObjectAttributes(&objectAttributes,
|
||||
¶metersPath,
|
||||
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
|
||||
driverKey,
|
||||
NULL);
|
||||
//
|
||||
// Open the key for deletion
|
||||
//
|
||||
status = ZwOpenKey(¶metersKey,
|
||||
DELETE,
|
||||
&objectAttributes);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MAJOR_VERSION);
|
||||
ZwDeleteValueKey(parametersKey, &valueName);
|
||||
|
||||
RtlInitUnicodeString(&valueName, REGISTRY_KMDF_MINOR_VERSION);
|
||||
ZwDeleteValueKey(parametersKey, &valueName);
|
||||
|
||||
RtlInitUnicodeString(&valueName, REGISTRY_KMDF_BUILD_NUMBER);
|
||||
ZwDeleteValueKey(parametersKey, &valueName);
|
||||
|
||||
ZwDeleteKey(parametersKey);
|
||||
|
||||
out:
|
||||
if (driverExtension->ParametersRegistryPath.Buffer != NULL) {
|
||||
ExFreePool(driverExtension->ParametersRegistryPath.Buffer);
|
||||
}
|
||||
|
||||
if (driverKey != NULL) {
|
||||
ZwClose(driverKey);
|
||||
}
|
||||
|
||||
if (parametersKey != NULL) {
|
||||
ZwClose(parametersKey);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxObjectInfoKm.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This file contains object info split from globals.cpp
|
||||
|
||||
This is because objects incorporated in KMDF and UMDF will differ
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxobjectpch.hpp"
|
||||
|
||||
#include "FxMemoryBufferPreallocated.hpp"
|
||||
#include "FxUserObject.hpp"
|
||||
#include "FxUsbDevice.hpp"
|
||||
#include "FxUsbPipe.hpp"
|
||||
#include "FxUsbInterface.hpp"
|
||||
|
||||
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_EXTERNAL_OBJECT_INFO_ENTRY(FxDpc, FX_TYPE_DPC, WDFDPC),
|
||||
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(FxWmiInstanceExternal, FX_TYPE_WMI_INSTANCE, WDFWMIINSTANCE),
|
||||
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(FxWmiIrpHandler, FX_TYPE_WMI_IRP_HANDLER),
|
||||
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),
|
||||
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxDmaEnabler, FX_TYPE_DMA_ENABLER, WDFDMAENABLER ),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxDmaTransactionBase, FX_TYPE_DMA_TRANSACTION, WDFDMATRANSACTION ),
|
||||
FX_EXTERNAL_OBJECT_INFO_ENTRY(FxCommonBuffer, FX_TYPE_COMMON_BUFFER, WDFCOMMONBUFFER ),
|
||||
};
|
||||
|
||||
ULONG FxObjectsInfoCount = sizeof(FxObjectsInfo)/sizeof(FX_OBJECT_INFO);
|
||||
|
||||
} //extern "C"
|
|
@ -0,0 +1,29 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
fxcorepch.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains header definitions and include files needed by all
|
||||
modules in FxToSharedInterface\FxObject
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef __FX_CORE_PCH_H__
|
||||
#define __FX_CORE_PCH_H__
|
||||
|
||||
#include "objectpriv.hpp"
|
||||
#include <fx.hpp>
|
||||
|
||||
#endif // __FX_CORE_PCH_H__
|
|
@ -0,0 +1,33 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
corepriv.hpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Private header file for FxToSharedInterface\FxObject directory
|
||||
It is then included in objectpch.hpp
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
extern "C" {
|
||||
#include <ntddk.h>
|
||||
#include "wdf.h"
|
||||
}
|
||||
|
||||
#define WDF_REGISTRY_BASE_PATH L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Wdf"
|
||||
|
439
sdk/lib/drivers/wdf/kmdf/src/irphandlers/wmi/fxwmiapi.cpp
Normal file
439
sdk/lib/drivers/wdf/kmdf/src/irphandlers/wmi/fxwmiapi.cpp
Normal file
|
@ -0,0 +1,439 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxWmiApi.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the C interface to the WMI package
|
||||
for the driver frameworks.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxwmipch.hpp"
|
||||
|
||||
//
|
||||
// Extern "C" the tmh file and all external APIs
|
||||
//
|
||||
extern "C" {
|
||||
#include "FxWmiAPI.tmh"
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfWmiProviderCreate)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Device,
|
||||
__in
|
||||
PWDF_WMI_PROVIDER_CONFIG WmiProviderConfig,
|
||||
__in_opt
|
||||
PWDF_OBJECT_ATTRIBUTES ProviderAttributes,
|
||||
__out
|
||||
WDFWMIPROVIDER* WmiProvider
|
||||
)
|
||||
{
|
||||
FxDevice* pDevice;
|
||||
FxPowerPolicyOwnerSettings* ownerSettings;
|
||||
FxWmiProvider* pProvider;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
FX_TYPE_DEVICE,
|
||||
(PVOID*) &pDevice);
|
||||
|
||||
FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), WmiProviderConfig);
|
||||
FxPointerNotNull(GetFxDriverGlobals(DriverGlobals), WmiProvider);
|
||||
|
||||
//
|
||||
// If the Device is a power policy owner then do not allow client drivers
|
||||
// to register for GUID_POWER_DEVICE_ENABLE or GUID_POWER_DEVICE_WAKE_ENABLE
|
||||
// if the framework has already register a provider for those guids.
|
||||
//
|
||||
if (pDevice->m_PkgPnp->IsPowerPolicyOwner()) {
|
||||
ownerSettings = pDevice->m_PkgPnp->m_PowerPolicyMachine.m_Owner;
|
||||
|
||||
if ((FxIsEqualGuid(&WmiProviderConfig->Guid,
|
||||
&GUID_POWER_DEVICE_ENABLE) &&
|
||||
ownerSettings->m_IdleSettings.WmiInstance != NULL) ||
|
||||
|
||||
(FxIsEqualGuid(&WmiProviderConfig->Guid,
|
||||
&GUID_POWER_DEVICE_WAKE_ENABLE) &&
|
||||
ownerSettings->m_WakeSettings.WmiInstance != NULL)) {
|
||||
|
||||
DoTraceLevelMessage(GetFxDriverGlobals(DriverGlobals), TRACE_LEVEL_ERROR,
|
||||
TRACINGDEVICE, "WMI Guid already registered by "
|
||||
"framework");
|
||||
return STATUS_WMI_GUID_DISCONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
return FxWmiProvider::_Create(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
ProviderAttributes,
|
||||
WmiProviderConfig,
|
||||
WmiProvider,
|
||||
&pProvider);
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfWmiInstanceCreate)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Device,
|
||||
__in
|
||||
PWDF_WMI_INSTANCE_CONFIG InstanceConfig,
|
||||
__in_opt
|
||||
PWDF_OBJECT_ATTRIBUTES InstanceAttributes,
|
||||
__out_opt
|
||||
WDFWMIINSTANCE* Instance
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxWmiProvider* pProvider;
|
||||
FxWmiInstanceExternal* pInstance;
|
||||
WDFWMIINSTANCE hInstance;
|
||||
NTSTATUS status;
|
||||
|
||||
pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
|
||||
pInstance = NULL;
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, InstanceConfig);
|
||||
|
||||
if (InstanceConfig->Size != sizeof(WDF_WMI_INSTANCE_CONFIG)) {
|
||||
status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Expected InstanceConfig Size %d, got %d, %!STATUS!",
|
||||
InstanceConfig->Size, sizeof(*InstanceConfig),
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if (InstanceConfig->Provider == NULL &&
|
||||
InstanceConfig->ProviderConfig == NULL) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"InstanceConfig %p Provider and ProviderConfig are both NULL, only "
|
||||
"one can be, %!STATUS!", InstanceConfig, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
else if (InstanceConfig->Provider != NULL &&
|
||||
InstanceConfig->ProviderConfig != NULL) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"InstanceConfig %p Provider %p and ProviderConfig %p are both not "
|
||||
"NULL, only one can be, %!STATUS!", InstanceConfig,
|
||||
InstanceConfig->Provider, InstanceConfig->ProviderConfig, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if (InstanceConfig->Provider != NULL) {
|
||||
FxObjectHandleGetPtrAndGlobals(pFxDriverGlobals,
|
||||
InstanceConfig->Provider,
|
||||
FX_TYPE_WMI_PROVIDER,
|
||||
(PVOID*) &pProvider,
|
||||
&pFxDriverGlobals);
|
||||
}
|
||||
else {
|
||||
FxDevice* pDevice;
|
||||
FxPowerPolicyOwnerSettings* ownerSettings;
|
||||
WDFWMIPROVIDER hProvider;
|
||||
|
||||
hProvider = NULL;
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
FX_TYPE_DEVICE,
|
||||
(PVOID*) &pDevice);
|
||||
|
||||
//
|
||||
// If the Device is a power policy owner then do not allow client drivers
|
||||
// to register for GUID_POWER_DEVICE_ENABLE or GUID_POWER_DEVICE_WAKE_ENABLE
|
||||
// if the framework has already register a provider for those guids.
|
||||
//
|
||||
if (pDevice->m_PkgPnp->IsPowerPolicyOwner()) {
|
||||
ownerSettings = pDevice->m_PkgPnp->m_PowerPolicyMachine.m_Owner;
|
||||
|
||||
if ((FxIsEqualGuid(&InstanceConfig->ProviderConfig->Guid,
|
||||
&GUID_POWER_DEVICE_ENABLE) &&
|
||||
ownerSettings->m_IdleSettings.WmiInstance != NULL) ||
|
||||
|
||||
(FxIsEqualGuid(&InstanceConfig->ProviderConfig->Guid,
|
||||
&GUID_POWER_DEVICE_WAKE_ENABLE) &&
|
||||
ownerSettings->m_WakeSettings.WmiInstance != NULL)) {
|
||||
|
||||
status = STATUS_WMI_GUID_DISCONNECTED;
|
||||
DoTraceLevelMessage(GetFxDriverGlobals(DriverGlobals), TRACE_LEVEL_ERROR,
|
||||
TRACINGDEVICE, "WMI Guid already registered by "
|
||||
"framework");
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
status = FxWmiProvider::_Create(pFxDriverGlobals,
|
||||
Device,
|
||||
NULL,
|
||||
InstanceConfig->ProviderConfig,
|
||||
&hProvider,
|
||||
&pProvider);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Use the object's globals and not the caller's
|
||||
//
|
||||
pFxDriverGlobals = pProvider->GetDriverGlobals();
|
||||
}
|
||||
|
||||
status = FxWmiInstanceExternal::_Create(pFxDriverGlobals,
|
||||
pProvider,
|
||||
InstanceConfig,
|
||||
InstanceAttributes,
|
||||
&hInstance,
|
||||
&pInstance);
|
||||
|
||||
if (NT_SUCCESS(status) && InstanceConfig->Register) {
|
||||
status = pProvider->AddInstance(pInstance);
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (Instance != NULL) {
|
||||
*Instance = hInstance;
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// Something went wrong, cleanup
|
||||
//
|
||||
if (pInstance != NULL) {
|
||||
//
|
||||
// This will remove the instance from the provider's list as well.
|
||||
//
|
||||
pInstance->DeleteFromFailedCreate();
|
||||
}
|
||||
|
||||
//
|
||||
// Only remove the provider if we created it in this function
|
||||
//
|
||||
if (InstanceConfig->ProviderConfig != NULL) {
|
||||
pProvider->DeleteFromFailedCreate();
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
WDFAPI
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFDEVICE
|
||||
WDFEXPORT(WdfWmiProviderGetDevice)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFWMIPROVIDER WmiProvider
|
||||
)
|
||||
{
|
||||
FxWmiProvider *pProvider;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
WmiProvider,
|
||||
FX_TYPE_WMI_PROVIDER,
|
||||
(PVOID*) &pProvider);
|
||||
|
||||
return pProvider->GetDevice()->GetHandle();
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
BOOLEAN
|
||||
WDFEXPORT(WdfWmiProviderIsEnabled)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFWMIPROVIDER WmiProvider,
|
||||
__in
|
||||
WDF_WMI_PROVIDER_CONTROL ProviderControl
|
||||
)
|
||||
{
|
||||
FxWmiProvider *pProvider;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
WmiProvider,
|
||||
FX_TYPE_WMI_PROVIDER,
|
||||
(PVOID*) &pProvider);
|
||||
|
||||
return pProvider->IsEnabled(ProviderControl);
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
ULONGLONG
|
||||
WDFEXPORT(WdfWmiProviderGetTracingHandle)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFWMIPROVIDER WmiProvider
|
||||
)
|
||||
{
|
||||
FxWmiProvider *pProvider;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
WmiProvider,
|
||||
FX_TYPE_WMI_PROVIDER,
|
||||
(PVOID*) &pProvider);
|
||||
|
||||
return pProvider->GetTracingHandle();
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfWmiInstanceRegister)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFWMIINSTANCE WmiInstance
|
||||
)
|
||||
{
|
||||
FxWmiInstanceExternal* pInstance;
|
||||
FxWmiProvider* pProvider;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
WmiInstance,
|
||||
FX_TYPE_WMI_INSTANCE,
|
||||
(PVOID*) &pInstance);
|
||||
|
||||
pProvider = pInstance->GetProvider();
|
||||
|
||||
return pProvider->AddInstance(pInstance);
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
VOID
|
||||
WDFEXPORT(WdfWmiInstanceDeregister)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFWMIINSTANCE WmiInstance
|
||||
)
|
||||
{
|
||||
FxWmiInstanceExternal* pInstance;
|
||||
FxWmiProvider* pProvider;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
WmiInstance,
|
||||
FX_TYPE_WMI_INSTANCE,
|
||||
(PVOID*) &pInstance);
|
||||
|
||||
pProvider = pInstance->GetProvider();
|
||||
pProvider->RemoveInstance(pInstance);
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFDEVICE
|
||||
WDFEXPORT(WdfWmiInstanceGetDevice)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFWMIINSTANCE WmiInstance
|
||||
)
|
||||
{
|
||||
FxWmiInstanceExternal* pInstance;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
WmiInstance,
|
||||
FX_TYPE_WMI_INSTANCE,
|
||||
(PVOID*) &pInstance);
|
||||
|
||||
return pInstance->GetDevice()->GetHandle();
|
||||
}
|
||||
|
||||
__drv_maxIRQL(DISPATCH_LEVEL)
|
||||
WDFWMIPROVIDER
|
||||
WDFEXPORT(WdfWmiInstanceGetProvider)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFWMIINSTANCE WmiInstance
|
||||
)
|
||||
{
|
||||
FxWmiInstanceExternal *pInstance;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
WmiInstance,
|
||||
FX_TYPE_WMI_INSTANCE,
|
||||
(PVOID*) &pInstance);
|
||||
|
||||
return pInstance->GetProvider()->GetHandle();
|
||||
}
|
||||
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(APC_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfWmiInstanceFireEvent)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFWMIINSTANCE WmiInstance,
|
||||
__in_opt
|
||||
ULONG EventDataSize,
|
||||
__in_bcount_opt(EventDataSize)
|
||||
PVOID EventData
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Fires an event based on the instance handle.
|
||||
|
||||
Arguments:
|
||||
WmiInstance - instance which the event is associated with
|
||||
EventDataSize - size of EventData in bytes
|
||||
EventData - buffer associated with the event
|
||||
|
||||
Return Value:
|
||||
NTSTATUS
|
||||
|
||||
--*/
|
||||
{
|
||||
FxWmiInstanceExternal* pInstance;
|
||||
NTSTATUS status;
|
||||
|
||||
FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
|
||||
WmiInstance,
|
||||
FX_TYPE_WMI_INSTANCE,
|
||||
(PVOID*) &pInstance);
|
||||
|
||||
status = FxVerifierCheckIrqlLevel(pInstance->GetDriverGlobals(), APC_LEVEL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
return pInstance->FireEvent(EventData, EventDataSize);
|
||||
}
|
||||
|
||||
} // extern "C"
|
684
sdk/lib/drivers/wdf/kmdf/src/irphandlers/wmi/fxwmiinstance.cpp
Normal file
684
sdk/lib/drivers/wdf/kmdf/src/irphandlers/wmi/fxwmiinstance.cpp
Normal file
|
@ -0,0 +1,684 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxWmiInstance.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the FxWmiInstance object and its derivations
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxwmipch.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxWmiInstance.tmh"
|
||||
}
|
||||
|
||||
FxWmiInstance::FxWmiInstance(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in USHORT ObjectSize,
|
||||
__in FxWmiProvider* Provider
|
||||
) :
|
||||
FxNonPagedObject(FX_TYPE_WMI_INSTANCE, ObjectSize, FxDriverGlobals)
|
||||
{
|
||||
InitializeListHead(&m_ListEntry);
|
||||
m_Provider = Provider;
|
||||
m_Provider->ADDREF(this);
|
||||
MarkDisposeOverride(ObjectDoNotLock);
|
||||
}
|
||||
|
||||
FxWmiInstance::~FxWmiInstance()
|
||||
{
|
||||
ASSERT(IsListEmpty(&m_ListEntry));
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxWmiInstance::Dispose(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
m_Provider->RemoveInstance(this);
|
||||
m_Provider->RELEASE(this);
|
||||
|
||||
//
|
||||
// Object is being deleted, remove this object from the provider's list
|
||||
// of instances. If we don't do this, the provider will have a list which
|
||||
// contains entries which have been freed.
|
||||
//
|
||||
return __super::Dispose();
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxWmiInstance::FireEvent(
|
||||
__in_bcount_opt(EventBufferSize) PVOID EventBuffer,
|
||||
__inout ULONG EventBufferSize
|
||||
)
|
||||
{
|
||||
ULONG sizeNeeded;
|
||||
PWNODE_SINGLE_INSTANCE pNode;
|
||||
NTSTATUS status;
|
||||
|
||||
if (EventBuffer == NULL) {
|
||||
EventBufferSize = 0;
|
||||
}
|
||||
|
||||
sizeNeeded = sizeof(WNODE_SINGLE_INSTANCE) + EventBufferSize;
|
||||
|
||||
//
|
||||
// IoWMIWriteEvent will free the memory by calling ExFreePool. This means
|
||||
// we cannot use a framework allocate function.
|
||||
//
|
||||
pNode = (PWNODE_SINGLE_INSTANCE)
|
||||
ExAllocatePoolWithTag(NonPagedPool, sizeNeeded, GetDriverGlobals()->Tag);
|
||||
|
||||
if (pNode != NULL) {
|
||||
RtlCopyMemory(&pNode->WnodeHeader.Guid,
|
||||
m_Provider->GetGUID(),
|
||||
sizeof(GUID));
|
||||
|
||||
pNode->WnodeHeader.ProviderId = IoWMIDeviceObjectToProviderId(
|
||||
GetDevice()->GetDeviceObject());
|
||||
pNode->WnodeHeader.BufferSize = sizeNeeded;
|
||||
pNode->WnodeHeader.Flags = WNODE_FLAG_SINGLE_INSTANCE |
|
||||
WNODE_FLAG_EVENT_ITEM |
|
||||
WNODE_FLAG_STATIC_INSTANCE_NAMES;
|
||||
KeQuerySystemTime(&pNode->WnodeHeader.TimeStamp);
|
||||
|
||||
pNode->InstanceIndex = m_Provider->GetInstanceIndex(this);
|
||||
pNode->SizeDataBlock = EventBufferSize;
|
||||
pNode->DataBlockOffset = sizeof(WNODE_SINGLE_INSTANCE);
|
||||
|
||||
if (EventBuffer != NULL) {
|
||||
RtlCopyMemory(&pNode->VariableData, EventBuffer, EventBufferSize);
|
||||
}
|
||||
|
||||
//
|
||||
// Upon success, IoWMIWriteEvent will free pNode.
|
||||
//
|
||||
status = IoWMIWriteEvent(pNode);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
ExFreePool(pNode);
|
||||
}
|
||||
}
|
||||
else {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"WDFWMIINSTANCE %p insufficient resources to fire event,%!STATUS!",
|
||||
GetHandle(), status);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
FxWmiInstanceExternal::FxWmiInstanceExternal(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PWDF_WMI_INSTANCE_CONFIG Config,
|
||||
__in FxWmiProvider* Provider
|
||||
) :
|
||||
FxWmiInstance(FxDriverGlobals, sizeof(FxWmiInstanceExternal), Provider),
|
||||
m_QueryInstanceCallback(FxDriverGlobals),
|
||||
m_SetInstanceCallback(FxDriverGlobals),
|
||||
m_SetItemCallback(FxDriverGlobals),
|
||||
m_ExecuteMethodCallback(FxDriverGlobals)
|
||||
{
|
||||
m_ContextLength = 0;
|
||||
m_UseContextForQuery = Config->UseContextForQuery;
|
||||
|
||||
if (m_UseContextForQuery == FALSE) {
|
||||
m_QueryInstanceCallback.m_Method = Config->EvtWmiInstanceQueryInstance;
|
||||
}
|
||||
m_SetInstanceCallback.m_Method = Config->EvtWmiInstanceSetInstance;
|
||||
m_SetItemCallback.m_Method = Config->EvtWmiInstanceSetItem;
|
||||
|
||||
m_ExecuteMethodCallback.m_Method = Config->EvtWmiInstanceExecuteMethod;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxWmiInstanceExternal::_Create(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in FxWmiProvider* Provider,
|
||||
__in PWDF_WMI_INSTANCE_CONFIG WmiInstanceConfig,
|
||||
__in_opt PWDF_OBJECT_ATTRIBUTES InstanceAttributes,
|
||||
__out WDFWMIINSTANCE* WmiInstance,
|
||||
__out FxWmiInstanceExternal** Instance
|
||||
)
|
||||
{
|
||||
FxWmiInstanceExternal* pInstance;
|
||||
WDFWMIINSTANCE hInstance;
|
||||
NTSTATUS status;
|
||||
size_t contextSize;
|
||||
|
||||
contextSize = 0;
|
||||
*Instance = 0;
|
||||
|
||||
*WmiInstance = NULL;
|
||||
|
||||
//
|
||||
// For event only providers, you cannot specify any callbacks or context
|
||||
// usage.
|
||||
//
|
||||
if (Provider->IsEventOnly() &&
|
||||
(WmiInstanceConfig->UseContextForQuery ||
|
||||
WmiInstanceConfig->EvtWmiInstanceQueryInstance != NULL ||
|
||||
WmiInstanceConfig->EvtWmiInstanceSetInstance != NULL ||
|
||||
WmiInstanceConfig->EvtWmiInstanceSetItem != NULL ||
|
||||
WmiInstanceConfig->EvtWmiInstanceExecuteMethod != NULL)) {
|
||||
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"WDFWMIPROVIDER %p is event only and UseContextForQuery (%d) is TRUE,"
|
||||
" or a callback (query instance %p, set instance %p, set item %p, "
|
||||
"executue method %p) is not NULL, %!STATUS!",
|
||||
Provider->GetHandle(), WmiInstanceConfig->UseContextForQuery,
|
||||
WmiInstanceConfig->EvtWmiInstanceQueryInstance,
|
||||
WmiInstanceConfig->EvtWmiInstanceSetInstance,
|
||||
WmiInstanceConfig->EvtWmiInstanceSetItem,
|
||||
WmiInstanceConfig->EvtWmiInstanceExecuteMethod, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
status = FxValidateObjectAttributes(FxDriverGlobals,
|
||||
InstanceAttributes,
|
||||
FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (WmiInstanceConfig->UseContextForQuery) {
|
||||
//
|
||||
// UseContextForQuery only supported for read only instances.
|
||||
// ExecuteMethod has undefined side affects, so we allow it.
|
||||
//
|
||||
if (WmiInstanceConfig->EvtWmiInstanceSetInstance != NULL ||
|
||||
WmiInstanceConfig->EvtWmiInstanceSetItem != NULL) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"UseContextForQuery set, i.e. a read only instance, but "
|
||||
"EvtWmiInstanceSetInstance %p or EvtWmiInstanceSetItem %p is "
|
||||
"set, %!STATUS!",
|
||||
WmiInstanceConfig->EvtWmiInstanceSetInstance,
|
||||
WmiInstanceConfig->EvtWmiInstanceSetItem, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// We must have a context to use for the query
|
||||
//
|
||||
if (InstanceAttributes == NULL ||
|
||||
InstanceAttributes->ContextTypeInfo == NULL) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"UseContextForQuery set, but InstanceAttributes %p is null or "
|
||||
"there is no associated type, %!STATUS!",
|
||||
InstanceAttributes, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
contextSize = InstanceAttributes->ContextTypeInfo->ContextSize;
|
||||
|
||||
if (InstanceAttributes->ContextSizeOverride != 0) {
|
||||
status = RtlSizeTAdd(contextSize,
|
||||
InstanceAttributes->ContextSizeOverride,
|
||||
&contextSize);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"Overlfow adding contextSize %I64d with size override %I64d, "
|
||||
"%!STATUS!", contextSize,
|
||||
InstanceAttributes->ContextSizeOverride, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
if (contextSize > ULONG_MAX) {
|
||||
//
|
||||
// Since we are casting to a ULONG below, detect loss of data here
|
||||
// (only really applicable on 64 bit machines where sizeof(size_t) !=
|
||||
// sizeof(ULONG)
|
||||
//
|
||||
status = STATUS_INTEGER_OVERFLOW;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"context size %I64d can be %d large, %!STATUS!",
|
||||
contextSize, ULONG_MAX, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure the context is the minimum the buffer size.
|
||||
//
|
||||
if (contextSize < Provider->GetMinInstanceBufferSize()) {
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"context size %I64d is less then the WDFWMIPROVIDER %p min size "
|
||||
"of %d, %!STATUS!",
|
||||
contextSize, Provider->GetHandle(),
|
||||
Provider->GetMinInstanceBufferSize(), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
pInstance = new(FxDriverGlobals, InstanceAttributes)
|
||||
FxWmiInstanceExternal(FxDriverGlobals, WmiInstanceConfig, Provider);
|
||||
|
||||
if (pInstance == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
FxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"could not allocate memory for WDFWMIINSTANCE, %!STATUS!",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if (contextSize > 0) {
|
||||
pInstance->SetContextForQueryLength((ULONG) contextSize);
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
status = pInstance->Commit(
|
||||
InstanceAttributes, (PWDFOBJECT) &hInstance, Provider);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
//
|
||||
// Assign the handle back to the caller.
|
||||
//
|
||||
*WmiInstance = hInstance;
|
||||
}
|
||||
else {
|
||||
//
|
||||
// On failure, DeleteFromFailedCreate will delete the object and
|
||||
// the Dispose callback will remove the instance from the provider's
|
||||
// list.
|
||||
//
|
||||
DO_NOTHING();
|
||||
}
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
*Instance = pInstance;
|
||||
}
|
||||
else {
|
||||
pInstance->DeleteFromFailedCreate();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxWmiInstanceExternal::IsQueryInstanceSupported(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// If we have a function pointer to call or we are using the context
|
||||
// as the buffer, query instance is supported.
|
||||
//
|
||||
// Also, if neither of the first 2 are true, we need to support query
|
||||
// instance if the device has an execute method callback b/c WMI will
|
||||
// send a query instance to this instance which much succeed for the
|
||||
// execute method irp to be sent.
|
||||
//
|
||||
return (m_UseContextForQuery ||
|
||||
m_QueryInstanceCallback.m_Method != NULL ||
|
||||
m_ExecuteMethodCallback.m_Method != NULL) ? TRUE
|
||||
: FALSE;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_sameIRQL
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
FxWmiInstanceExternal::QueryInstance(
|
||||
__inout ULONG OutBufferSize,
|
||||
__out_bcount(OutBufferSize) PVOID OutBuffer,
|
||||
__out PULONG BufferUsed
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
if (m_UseContextForQuery) {
|
||||
//
|
||||
// No matter what, we are reporting the length of the context. If the
|
||||
// buffer is too small, it is used to report the desired buffer length.
|
||||
// Otherwise, it is the amount of data we copied to the query buffer.
|
||||
//
|
||||
*BufferUsed = m_ContextLength;
|
||||
|
||||
if (OutBufferSize < m_ContextLength) {
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"WDFWMIINSTANCE %p query instance using context for query, "
|
||||
"query buffer length %d, context length %d, %!STATUS!",
|
||||
GetHandle(), OutBufferSize, m_ContextLength, status);
|
||||
}
|
||||
else {
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
RtlCopyMemory(OutBuffer,
|
||||
&GetContextHeader()->Context[0],
|
||||
m_ContextLength);
|
||||
}
|
||||
}
|
||||
else if (m_QueryInstanceCallback.m_Method != NULL) {
|
||||
BYTE dummy;
|
||||
|
||||
if (OutBufferSize == 0) {
|
||||
ASSERT(m_Provider->GetMinInstanceBufferSize() == 0);
|
||||
OutBuffer = (PVOID) &dummy;
|
||||
OutBufferSize = sizeof(dummy);
|
||||
}
|
||||
|
||||
status = m_QueryInstanceCallback.Invoke(
|
||||
GetDevice()->GetHandle(),
|
||||
GetHandle(),
|
||||
OutBufferSize,
|
||||
OutBuffer,
|
||||
BufferUsed
|
||||
);
|
||||
|
||||
if (status == STATUS_PENDING) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"WDFWMIINSTANCE %p was queried and returned %!STATUS!, which is "
|
||||
"not an allowed return value", GetHandle(), status);
|
||||
|
||||
FxVerifierDbgBreakPoint(GetDriverGlobals());
|
||||
|
||||
status = STATUS_UNSUCCESSFUL;
|
||||
*BufferUsed = 0;
|
||||
}
|
||||
else if (NT_SUCCESS(status)) {
|
||||
if (*BufferUsed > OutBufferSize) {
|
||||
//
|
||||
// Caller error, they returned more bytes in *BufferUsed then
|
||||
// was passed in via OutBufferSize, yet returned NT_SUCCESS
|
||||
//
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"WDFWMIINSTANCE %p was queried with buffer size %d, "
|
||||
" but returned %d bytes and %!STATUS!, should return "
|
||||
"!NT_SUCCESS in this case",
|
||||
GetHandle(), OutBufferSize, *BufferUsed, status);
|
||||
|
||||
FxVerifierDbgBreakPoint(GetDriverGlobals());
|
||||
|
||||
status = STATUS_UNSUCCESSFUL;
|
||||
*BufferUsed = 0;
|
||||
}
|
||||
else if (OutBuffer == &dummy && *BufferUsed > 0) {
|
||||
//
|
||||
// Convert success back to an error where we can report the
|
||||
// required size back to the caller.
|
||||
//
|
||||
status = STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
}
|
||||
else if (status == STATUS_BUFFER_TOO_SMALL) {
|
||||
if (m_Provider->GetMinInstanceBufferSize()) {
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"WDFWMIINSTANCE %p returned %!STATUS!, but it specified "
|
||||
"a minimum instance size %d in its WDFWMIPROVIDER %p",
|
||||
GetHandle(), status, m_Provider->GetMinInstanceBufferSize(),
|
||||
m_Provider->GetHandle());
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"This is a break in the contract. Minimum instance size "
|
||||
"should only be used for fixed sized instances");
|
||||
|
||||
FxVerifierDbgBreakPoint(GetDriverGlobals());
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
ASSERT(m_ExecuteMethodCallback.m_Method != NULL);
|
||||
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"WDFWMIINSTANCE %p was queried with no query callback and supports "
|
||||
"execute method (%p), zero bytes returned", GetHandle(),
|
||||
m_ExecuteMethodCallback.m_Method);
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
*BufferUsed = 0;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxWmiInstanceExternal::IsSetInstanceSupported(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_SetInstanceCallback.m_Method != NULL ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_sameIRQL
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
FxWmiInstanceExternal::SetInstance(
|
||||
__in ULONG InBufferSize,
|
||||
__in_bcount(InBufferSize) PVOID InBuffer
|
||||
)
|
||||
{
|
||||
return m_SetInstanceCallback.Invoke(
|
||||
GetDevice()->GetHandle(),
|
||||
GetHandle(),
|
||||
InBufferSize,
|
||||
InBuffer
|
||||
);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxWmiInstanceExternal::IsSetItemSupported(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_SetItemCallback.m_Method != NULL ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_sameIRQL
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
FxWmiInstanceExternal::SetItem(
|
||||
__in ULONG DataItemId,
|
||||
__in ULONG InBufferSize,
|
||||
__in_bcount(InBufferSize) PVOID InBuffer
|
||||
)
|
||||
{
|
||||
return m_SetItemCallback.Invoke(
|
||||
GetDevice()->GetHandle(),
|
||||
GetHandle(),
|
||||
DataItemId,
|
||||
InBufferSize,
|
||||
InBuffer
|
||||
);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxWmiInstanceExternal::IsExecuteMethodSupported(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_ExecuteMethodCallback.m_Method != NULL ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_sameIRQL
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
FxWmiInstanceExternal::ExecuteMethod(
|
||||
__in ULONG MethodId,
|
||||
__in ULONG InBufferSize,
|
||||
__inout ULONG OutBufferSize,
|
||||
__drv_when(InBufferSize >= OutBufferSize, __inout_bcount(InBufferSize))
|
||||
__drv_when(InBufferSize < OutBufferSize, __inout_bcount(OutBufferSize))
|
||||
PVOID Buffer,
|
||||
__out PULONG BufferUsed
|
||||
)
|
||||
{
|
||||
return m_ExecuteMethodCallback.Invoke(
|
||||
GetDevice()->GetHandle(),
|
||||
GetHandle(),
|
||||
MethodId,
|
||||
InBufferSize,
|
||||
OutBufferSize,
|
||||
Buffer,
|
||||
BufferUsed
|
||||
);
|
||||
}
|
||||
|
||||
FxWmiInstanceInternal::FxWmiInstanceInternal(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in FxWmiInstanceInternalCallbacks* Callbacks,
|
||||
__in FxWmiProvider* Provider
|
||||
) : FxWmiInstance(FxDriverGlobals, sizeof(FxWmiInstanceInternal), Provider)
|
||||
{
|
||||
m_QueryInstance = Callbacks->QueryInstance;
|
||||
m_SetInstance = Callbacks->SetInstance;
|
||||
m_SetItem = Callbacks->SetItem;
|
||||
m_ExecuteMethod = Callbacks->ExecuteMethod;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxWmiInstanceInternal::IsQueryInstanceSupported(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_QueryInstance != NULL ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_sameIRQL
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
FxWmiInstanceInternal::QueryInstance(
|
||||
__inout ULONG OutBufferSize,
|
||||
__out_bcount(OutBufferSize) PVOID OutBuffer,
|
||||
__out PULONG BufferUsed
|
||||
)
|
||||
{
|
||||
return m_QueryInstance(GetDevice(),
|
||||
this,
|
||||
OutBufferSize,
|
||||
OutBuffer,
|
||||
BufferUsed);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxWmiInstanceInternal::IsSetInstanceSupported(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_SetInstance != NULL ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_sameIRQL
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
FxWmiInstanceInternal::SetInstance(
|
||||
__in ULONG InBufferSize,
|
||||
__in_bcount(InBufferSize) PVOID InBuffer
|
||||
)
|
||||
{
|
||||
return m_SetInstance(GetDevice(),
|
||||
this,
|
||||
InBufferSize,
|
||||
InBuffer);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxWmiInstanceInternal::IsSetItemSupported(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
return m_SetItem != NULL ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_sameIRQL
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
FxWmiInstanceInternal::SetItem(
|
||||
__in ULONG DataItemId,
|
||||
__in ULONG InBufferSize,
|
||||
__in_bcount(InBufferSize) PVOID InBuffer
|
||||
)
|
||||
{
|
||||
return m_SetItem(GetDevice(),
|
||||
this,
|
||||
DataItemId,
|
||||
InBufferSize,
|
||||
InBuffer);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxWmiInstanceInternal::IsExecuteMethodSupported(
|
||||
VOID
|
||||
)
|
||||
|
||||
{
|
||||
return m_ExecuteMethod != NULL ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
__drv_sameIRQL
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
FxWmiInstanceInternal::ExecuteMethod(
|
||||
__in ULONG MethodId,
|
||||
__in ULONG InBufferSize,
|
||||
__inout ULONG OutBufferSize,
|
||||
__drv_when(InBufferSize >= OutBufferSize, __inout_bcount(InBufferSize))
|
||||
__drv_when(InBufferSize < OutBufferSize, __inout_bcount(OutBufferSize))
|
||||
PVOID Buffer,
|
||||
__out PULONG BufferUsed
|
||||
)
|
||||
{
|
||||
return m_ExecuteMethod(GetDevice(),
|
||||
this,
|
||||
MethodId,
|
||||
InBufferSize,
|
||||
OutBufferSize,
|
||||
Buffer,
|
||||
BufferUsed);
|
||||
}
|
1960
sdk/lib/drivers/wdf/kmdf/src/irphandlers/wmi/fxwmiirphandler.cpp
Normal file
1960
sdk/lib/drivers/wdf/kmdf/src/irphandlers/wmi/fxwmiirphandler.cpp
Normal file
File diff suppressed because it is too large
Load diff
32
sdk/lib/drivers/wdf/kmdf/src/irphandlers/wmi/fxwmipch.hpp
Normal file
32
sdk/lib/drivers/wdf/kmdf/src/irphandlers/wmi/fxwmipch.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
fxwmipch.hpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains header definitions and include files needed by all
|
||||
modules in this directory.
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef __FX_WMI_PCH_HPP__
|
||||
#define __FX_WMI_PCH_HPP__
|
||||
|
||||
extern "C" {
|
||||
#include <ntddk.h>
|
||||
}
|
||||
|
||||
#include <fx.hpp>
|
||||
|
||||
#endif // __FX_WMI_PCH_HPP__
|
563
sdk/lib/drivers/wdf/kmdf/src/irphandlers/wmi/fxwmiprovider.cpp
Normal file
563
sdk/lib/drivers/wdf/kmdf/src/irphandlers/wmi/fxwmiprovider.cpp
Normal file
|
@ -0,0 +1,563 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxWmiProvider.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the FxWmiProvider object
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "fxwmipch.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxWmiProvider.tmh"
|
||||
}
|
||||
|
||||
FxWmiProvider::FxWmiProvider(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PWDF_WMI_PROVIDER_CONFIG Config,
|
||||
__in FxDevice* Device
|
||||
) :
|
||||
FxNonPagedObject(FX_TYPE_WMI_PROVIDER,
|
||||
sizeof(FxWmiProvider),
|
||||
FxDriverGlobals),
|
||||
m_FunctionControl(FxDriverGlobals)
|
||||
{
|
||||
InitializeListHead(&m_ListEntry);
|
||||
InitializeListHead(&m_InstanceListHead);
|
||||
m_NumInstances = 0;
|
||||
|
||||
m_Parent = Device->m_PkgWmi;
|
||||
|
||||
m_EventControlEnabled = FALSE;
|
||||
m_DataBlockControlEnabled = FALSE;
|
||||
m_RemoveGuid = FALSE;
|
||||
|
||||
m_TracingHandle = 0;
|
||||
|
||||
m_Flags = Config->Flags;
|
||||
m_MinInstanceBufferSize = Config->MinInstanceBufferSize;
|
||||
RtlCopyMemory(&m_Guid, &Config->Guid, sizeof(GUID));
|
||||
|
||||
if (Config->EvtWmiProviderFunctionControl != NULL) {
|
||||
m_FunctionControl.m_Method = Config->EvtWmiProviderFunctionControl;
|
||||
}
|
||||
|
||||
//
|
||||
// Driver cannot call WdfObjectDelete on this handle
|
||||
//
|
||||
MarkNoDeleteDDI();
|
||||
|
||||
MarkDisposeOverride(ObjectDoNotLock);
|
||||
}
|
||||
|
||||
FxWmiProvider::~FxWmiProvider()
|
||||
{
|
||||
ASSERT(IsListEmpty(&m_ListEntry));
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxWmiProvider::Dispose(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
//
|
||||
// Object is being deleted, remove this object from the irp handler's list
|
||||
// of providers. If we don't do this, the irp handler will have a list
|
||||
// which contains entries which have been freed.
|
||||
//
|
||||
m_Parent->RemoveProvider(this);
|
||||
|
||||
return __super::Dispose();
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxWmiProvider::_Create(
|
||||
__in PFX_DRIVER_GLOBALS CallersGlobals,
|
||||
__in WDFDEVICE Device,
|
||||
__in_opt PWDF_OBJECT_ATTRIBUTES ProviderAttributes,
|
||||
__in PWDF_WMI_PROVIDER_CONFIG WmiProviderConfig,
|
||||
__out WDFWMIPROVIDER* WmiProvider,
|
||||
__out FxWmiProvider** Provider
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxDevice* pDevice;
|
||||
FxWmiProvider* pProvider;
|
||||
NTSTATUS status;
|
||||
WDFOBJECT hProvider;
|
||||
GUID zeroGuid;
|
||||
BOOLEAN update;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(CallersGlobals,
|
||||
Device,
|
||||
FX_TYPE_DEVICE,
|
||||
(PVOID*) &pDevice,
|
||||
&pFxDriverGlobals);
|
||||
|
||||
*Provider = NULL;
|
||||
update = FALSE;
|
||||
|
||||
*WmiProvider = NULL;
|
||||
|
||||
status = FxValidateObjectAttributes(pFxDriverGlobals,
|
||||
ProviderAttributes,
|
||||
FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (WmiProviderConfig->Size != sizeof(WDF_WMI_PROVIDER_CONFIG)) {
|
||||
status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"WmiProviderConfig Size 0x%x, expected size 0x%x, %!STATUS!",
|
||||
WmiProviderConfig->Size, sizeof(WDF_WMI_PROVIDER_CONFIG),
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((WmiProviderConfig->Flags & ~WdfWmiProviderValidFlags) != 0) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Invalid flag(s) set, Flags 0x%x, valid mask 0x%x, %!STATUS!",
|
||||
WmiProviderConfig->Flags, WdfWmiProviderValidFlags,
|
||||
status);
|
||||
return status;
|
||||
}
|
||||
|
||||
if ((WmiProviderConfig->Flags & WdfWmiProviderTracing) &&
|
||||
(WmiProviderConfig->Flags & ~WdfWmiProviderTracing)) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"WdfWmiProviderTracing must be the only flag set, %!STATUS!",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// Function control makes sense if it is expensive. Otherwise you will
|
||||
// not be called back on it.
|
||||
//
|
||||
// The opposite, marking yourself as expensive but providing no callback is
|
||||
// OK b/c the provider marks the enabled state and the driver can retrieve
|
||||
// it at runtime.
|
||||
//
|
||||
// Function control also applies to tracing GUIDs since the tracing subsystem
|
||||
// will call enable/disable events to start/stop tracing.
|
||||
//
|
||||
if (WmiProviderConfig->EvtWmiProviderFunctionControl != NULL &&
|
||||
((WmiProviderConfig->Flags & (WdfWmiProviderTracing | WdfWmiProviderExpensive)) == 0)) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"EvtWmiProviderFunctionControl can only be set if Flags 0x%x has "
|
||||
"WdfWmiProviderTracing (%d) or WdfWmiProviderExpensive (%d) bit "
|
||||
"values set, %!STATUS!",
|
||||
WmiProviderConfig->Flags, WdfWmiProviderTracing,
|
||||
WdfWmiProviderExpensive, status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
RtlZeroMemory(&zeroGuid, sizeof(zeroGuid));
|
||||
|
||||
if (RtlCompareMemory(&WmiProviderConfig->Guid,
|
||||
&zeroGuid,
|
||||
sizeof(GUID)) == sizeof(GUID)) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"WmiProvider Guid filed is all zeros, %!STATUS!",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
pProvider = NULL;
|
||||
|
||||
pProvider = new(pFxDriverGlobals, ProviderAttributes)
|
||||
FxWmiProvider(pFxDriverGlobals, WmiProviderConfig, pDevice);
|
||||
|
||||
if (pProvider == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
|
||||
"Could not allocate memory for a WDFWMIPROVIDER, %!STATUS!",
|
||||
status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
status = pDevice->m_PkgWmi->AddProvider(pProvider, &update);
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
status = pProvider->Commit(ProviderAttributes, &hProvider, pDevice);
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
pDevice->m_PkgWmi->RemoveProvider(pProvider);
|
||||
}
|
||||
else {
|
||||
//
|
||||
// NT_SUCCES(status) case
|
||||
//
|
||||
*WmiProvider = (WDFWMIPROVIDER) hProvider;
|
||||
}
|
||||
}
|
||||
|
||||
if (NT_SUCCESS(status)) {
|
||||
*Provider = pProvider;
|
||||
|
||||
if (update) {
|
||||
pDevice->m_PkgWmi->UpdateGuids();
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// AddProvider incremented update count on success however since we
|
||||
// are not going to update registration due to this failure, decrement
|
||||
// the count.
|
||||
//
|
||||
if (update) {
|
||||
pDevice->m_PkgWmi->DecrementUpdateCount();
|
||||
}
|
||||
|
||||
pProvider->DeleteFromFailedCreate();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxWmiProvider::AddInstanceLocked(
|
||||
__in FxWmiInstance* Instance,
|
||||
__in BOOLEAN NoErrorIfPresent,
|
||||
__out PBOOLEAN Update,
|
||||
__in AddInstanceAction Action
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
*Update = FALSE;
|
||||
|
||||
if (!IsListEmpty(&Instance->m_ListEntry)) {
|
||||
if (NoErrorIfPresent) {
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
else {
|
||||
//
|
||||
// Entry is already on a list, bad caller!
|
||||
//
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"WDFWMIINSTANCE %p already added, %!STATUS!",
|
||||
Instance->GetHandle(), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Check to see if we are in the process of
|
||||
//
|
||||
switch (m_Parent->m_RegisteredState) {
|
||||
case FxWmiIrpHandler::WmiUnregistered:
|
||||
//
|
||||
// The GUID will be reported when we do the initial registration
|
||||
//
|
||||
break;
|
||||
|
||||
case FxWmiIrpHandler::WmiDeregistered:
|
||||
//
|
||||
// Either the GUID will be reported when we do the re-registration or
|
||||
// we will clean it up when we goto the cleanup state.
|
||||
//
|
||||
break;
|
||||
|
||||
case FxWmiIrpHandler::WmiRegistered:
|
||||
//
|
||||
// Since we already registered we need to tell WMI the change in the
|
||||
// number of instances on this provider.
|
||||
//
|
||||
*Update = TRUE;
|
||||
break;
|
||||
|
||||
case FxWmiIrpHandler::WmiCleanedUp:
|
||||
//
|
||||
// Device is going away, registration is not allowed for the device
|
||||
// anymore.
|
||||
//
|
||||
status = STATUS_INVALID_DEVICE_STATE;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_INFORMATION, TRACINGDEVICE,
|
||||
"WMI is being cleanedup, WDFWMIINSTANCE %p add failing, %!STATUS!",
|
||||
Instance->GetHandle(), status);
|
||||
|
||||
return status;
|
||||
|
||||
default:
|
||||
ASSERT(FALSE);
|
||||
break;
|
||||
}
|
||||
|
||||
if (Action == AddInstanceToTail) {
|
||||
InsertTailList(&m_InstanceListHead, &Instance->m_ListEntry);
|
||||
}
|
||||
else {
|
||||
InsertHeadList(&m_InstanceListHead, &Instance->m_ListEntry);
|
||||
}
|
||||
|
||||
//
|
||||
// Since the count is increasing to at least one, we are not going to
|
||||
// need to report this GUID as missing. We could check the
|
||||
// m_Parent->m_RegisteredState and only set it when we are registered, but
|
||||
// it does us no harm to always clear this value regardless of state.
|
||||
//
|
||||
m_RemoveGuid = FALSE;
|
||||
|
||||
m_NumInstances++;
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxWmiProvider::AddInstance(
|
||||
__in FxWmiInstance* Instance,
|
||||
__in BOOLEAN NoErrorIfPresent
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
KIRQL irql;
|
||||
BOOLEAN update;
|
||||
|
||||
if (m_Flags & WdfWmiProviderTracing) {
|
||||
status = STATUS_INVALID_DEVICE_REQUEST;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGDEVICE,
|
||||
"WDFWMIINSTANCE %p cannot be added to tracing WDFWMIPROVIDER %p, "
|
||||
"%!STATUS!", Instance->GetHandle(), GetHandle(), status);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
m_Parent->Lock(&irql);
|
||||
status = AddInstanceLocked(Instance, NoErrorIfPresent, &update);
|
||||
|
||||
if (update) {
|
||||
update = m_Parent->DeferUpdateLocked(irql);
|
||||
}
|
||||
m_Parent->Unlock(irql);
|
||||
|
||||
if (update) {
|
||||
m_Parent->UpdateGuids();
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxWmiProvider::RemoveInstance(
|
||||
__in FxWmiInstance* Instance
|
||||
)
|
||||
{
|
||||
KIRQL irql;
|
||||
BOOLEAN update;
|
||||
|
||||
update = FALSE;
|
||||
|
||||
m_Parent->Lock(&irql);
|
||||
|
||||
if (!IsListEmpty(&Instance->m_ListEntry)) {
|
||||
//
|
||||
// Instance is in the list of instances on this provider. Remove it.
|
||||
//
|
||||
RemoveEntryList(&Instance->m_ListEntry);
|
||||
InitializeListHead(&Instance->m_ListEntry);
|
||||
m_NumInstances--;
|
||||
|
||||
if (m_Parent->m_RegisteredState == FxWmiIrpHandler::WmiRegistered) {
|
||||
update = TRUE;
|
||||
|
||||
//
|
||||
// When the count goes to zero, inform WMI that the GUID should be
|
||||
// removed when we get requeried. We only need to do this once we have
|
||||
// been registered. In all other states, we ignore this value.
|
||||
//
|
||||
if (m_NumInstances == 0 &&
|
||||
(m_Flags & WdfWmiProviderExpensive) == 0) {
|
||||
m_RemoveGuid = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
//
|
||||
// The instance was explicitly removed and now the instance is trying
|
||||
// to remove itself during dispose. Nothing to do.
|
||||
//
|
||||
DO_NOTHING();
|
||||
}
|
||||
|
||||
if (update) {
|
||||
update = m_Parent->DeferUpdateLocked(irql);
|
||||
}
|
||||
|
||||
m_Parent->Unlock(irql);
|
||||
|
||||
if (update) {
|
||||
m_Parent->UpdateGuids();
|
||||
}
|
||||
}
|
||||
|
||||
ULONG
|
||||
FxWmiProvider::GetInstanceIndex(
|
||||
__in FxWmiInstance* Instance
|
||||
)
|
||||
{
|
||||
PLIST_ENTRY ple;
|
||||
ULONG index;
|
||||
KIRQL irql;
|
||||
|
||||
m_Parent->Lock(&irql);
|
||||
for (index = 0, ple = m_InstanceListHead.Flink;
|
||||
index < m_NumInstances;
|
||||
index++, ple = ple->Flink) {
|
||||
if (CONTAINING_RECORD(ple, FxWmiInstance, m_ListEntry) == Instance) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_Parent->Unlock(irql);
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
FxWmiInstance*
|
||||
FxWmiProvider::GetInstanceReferenced(
|
||||
__in ULONG Index,
|
||||
__in PVOID Tag
|
||||
)
|
||||
{
|
||||
FxWmiInstance* pInstance;
|
||||
KIRQL irql;
|
||||
|
||||
m_Parent->Lock(&irql);
|
||||
pInstance = GetInstanceReferencedLocked(Index, Tag);
|
||||
m_Parent->Unlock(irql);
|
||||
|
||||
return pInstance;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
FxWmiInstance*
|
||||
FxWmiProvider::GetInstanceReferencedLocked(
|
||||
__in ULONG Index,
|
||||
__in PVOID Tag
|
||||
)
|
||||
{
|
||||
FxWmiInstance* pFound;
|
||||
PLIST_ENTRY ple;
|
||||
ULONG i;
|
||||
|
||||
pFound = NULL;
|
||||
|
||||
for (i = 0, ple = m_InstanceListHead.Flink;
|
||||
i < m_NumInstances;
|
||||
ple = ple->Flink, i++) {
|
||||
|
||||
if (i == Index) {
|
||||
pFound = CONTAINING_RECORD(ple, FxWmiInstance, m_ListEntry);
|
||||
pFound->ADDREF(Tag);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return pFound;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxWmiProvider::FunctionControl(
|
||||
__in WDF_WMI_PROVIDER_CONTROL Control,
|
||||
__in BOOLEAN Enable
|
||||
)
|
||||
{
|
||||
return m_FunctionControl.Invoke(m_Parent->GetDevice()->GetHandle(),
|
||||
GetHandle(),
|
||||
Control,
|
||||
Enable);
|
||||
}
|
||||
|
||||
ULONG
|
||||
FxWmiProvider::GetRegistrationFlagsLocked(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ULONG flags;
|
||||
|
||||
if (m_Flags & WdfWmiProviderTracing) {
|
||||
flags = WMIREG_FLAG_TRACED_GUID | WMIREG_FLAG_TRACE_CONTROL_GUID;
|
||||
|
||||
//
|
||||
// Once tracing GUID is registered, we do not allow it to be unregistered
|
||||
//
|
||||
ASSERT(m_RemoveGuid == FALSE);
|
||||
}
|
||||
else {
|
||||
flags = WMIREG_FLAG_INSTANCE_PDO;
|
||||
|
||||
if (m_Flags & WdfWmiProviderExpensive) {
|
||||
flags |= WMIREG_FLAG_EXPENSIVE;
|
||||
}
|
||||
|
||||
if (m_Flags & WdfWmiProviderEventOnly) {
|
||||
flags |= WMIREG_FLAG_EVENT_ONLY_GUID;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_RemoveGuid) {
|
||||
//
|
||||
// We have gone down to zero instances of this provider, report it as
|
||||
// gone to WMI.
|
||||
//
|
||||
ASSERT(m_NumInstances == 0);
|
||||
flags |= WMIREG_FLAG_REMOVE_GUID;
|
||||
|
||||
//
|
||||
// Once reported as removed, we do not have not have to report ourselves
|
||||
// as removed again.
|
||||
//
|
||||
m_RemoveGuid = FALSE;
|
||||
}
|
||||
|
||||
return flags;
|
||||
}
|
||||
|
717
sdk/lib/drivers/wdf/kmdf/src/librarycommon/fxlibrarycommon.cpp
Normal file
717
sdk/lib/drivers/wdf/kmdf/src/librarycommon/fxlibrarycommon.cpp
Normal file
|
@ -0,0 +1,717 @@
|
|||
//
|
||||
// Copyright (C) Microsoft. All rights reserved.
|
||||
//
|
||||
|
||||
extern "C" {
|
||||
#include <ntddk.h>
|
||||
}
|
||||
|
||||
//
|
||||
// This will cause inclusion of VfWdfFunctions table implementation from header
|
||||
//
|
||||
#define VF_FX_DYNAMICS_GENERATE_TABLE 1
|
||||
|
||||
//
|
||||
// Compute the length based on the max. service name length and the rest of the
|
||||
// error string as seen in ReportDdiFunctionCountMismatch
|
||||
//
|
||||
#define EVTLOG_DDI_COUNT_ERROR_MAX_LEN (53 + MAX_PATH)
|
||||
|
||||
#include "fx.hpp"
|
||||
#include "fxldr.h"
|
||||
#include "FxLibraryCommon.h"
|
||||
#include "FxTelemetry.hpp"
|
||||
#include "WdfVersionLog.h"
|
||||
#include "minwindef.h"
|
||||
|
||||
extern "C" {
|
||||
//
|
||||
// Global triage Info for dbgeng and 0x9F work
|
||||
//
|
||||
static WDFOBJECT_TRIAGE_INFO _WdfObjectTriageInfo = {0};
|
||||
static WDFCONTEXT_TRIAGE_INFO _WdfContextTriageInfo = {0};
|
||||
static WDFCONTEXTTYPE_TRIAGE_INFO _WdfContextTypeTriageInfo = {0};
|
||||
static WDFQUEUE_TRIAGE_INFO _WdfQueueTriageInfo = {0};
|
||||
static WDFIRPQUEUE_TRIAGE_INFO _WdfIrpQueueTriageInfo = {0};
|
||||
static WDFREQUEST_TRIAGE_INFO _WdfRequestTriageInfo = {0};
|
||||
static WDFDEVICE_TRIAGE_INFO _WdfDeviceTriageInfo = {0};
|
||||
static WDFIRP_TRIAGE_INFO _WdfIrpTriageInfo = {0};
|
||||
static WDFFWDPROGRESS_TRIAGE_INFO _WdfFwdProgressTriageInfo = {0};
|
||||
|
||||
WDF_TRIAGE_INFO g_WdfTriageInfo = {
|
||||
//
|
||||
// KMDF Version.
|
||||
//
|
||||
__WDF_MAJOR_VERSION,
|
||||
__WDF_MINOR_VERSION,
|
||||
|
||||
//
|
||||
// Table Version.
|
||||
//
|
||||
WDF_01_TRIAGE_INFO_MAJOR_VERSION,
|
||||
WDF_01_TRIAGE_INFO_MINOR_VERSION,
|
||||
|
||||
//
|
||||
// Reserved ptr (set to NULL).
|
||||
//
|
||||
NULL,
|
||||
|
||||
//
|
||||
// WDF objects triage info.
|
||||
//
|
||||
&_WdfObjectTriageInfo,
|
||||
&_WdfContextTriageInfo,
|
||||
&_WdfContextTypeTriageInfo,
|
||||
&_WdfQueueTriageInfo,
|
||||
&_WdfFwdProgressTriageInfo,
|
||||
&_WdfIrpQueueTriageInfo,
|
||||
&_WdfRequestTriageInfo,
|
||||
&_WdfDeviceTriageInfo,
|
||||
&_WdfIrpTriageInfo,
|
||||
};
|
||||
} // extern "C"
|
||||
|
||||
VOID
|
||||
GetTriageInfo(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
// Object
|
||||
_WdfObjectTriageInfo.RawObjectSize = sizeof(FxObject);
|
||||
_WdfObjectTriageInfo.ObjectType = FIELD_OFFSET(FxObject, m_Type);
|
||||
_WdfObjectTriageInfo.TotalObjectSize = FIELD_OFFSET(FxObject, m_ObjectSize);
|
||||
_WdfObjectTriageInfo.ChildListHead = FIELD_OFFSET(FxObject, m_ChildListHead);
|
||||
_WdfObjectTriageInfo.ChildEntry = FIELD_OFFSET(FxObject, m_ChildEntry);
|
||||
_WdfObjectTriageInfo.Globals = FIELD_OFFSET(FxObject, m_Globals);
|
||||
_WdfObjectTriageInfo.ParentObject = FIELD_OFFSET(FxObject, m_ParentObject);
|
||||
|
||||
// Context Triage Info
|
||||
_WdfContextTriageInfo.HeaderSize = sizeof(FxContextHeader);
|
||||
_WdfContextTriageInfo.NextHeader = FIELD_OFFSET(FxContextHeader, NextHeader);
|
||||
_WdfContextTriageInfo.Object = FIELD_OFFSET(FxContextHeader, Object);
|
||||
_WdfContextTriageInfo.TypeInfoPtr = FIELD_OFFSET(FxContextHeader, ContextTypeInfo);
|
||||
_WdfContextTriageInfo.Context = FIELD_OFFSET(FxContextHeader, Context);
|
||||
|
||||
// Context type Triage info
|
||||
_WdfContextTypeTriageInfo.TypeInfoSize = sizeof(WDF_OBJECT_CONTEXT_TYPE_INFO);
|
||||
_WdfContextTypeTriageInfo.ContextSize = FIELD_OFFSET(WDF_OBJECT_CONTEXT_TYPE_INFO, ContextSize);
|
||||
_WdfContextTypeTriageInfo.ContextName = FIELD_OFFSET(WDF_OBJECT_CONTEXT_TYPE_INFO, ContextName);
|
||||
|
||||
// WdfRequest Queue
|
||||
_WdfQueueTriageInfo.QueueSize = sizeof(FxIoQueue);
|
||||
_WdfQueueTriageInfo.IrpQueue1 = FIELD_OFFSET(FxIoQueue, m_Queue);
|
||||
_WdfQueueTriageInfo.IrpQueue2 = FIELD_OFFSET(FxIoQueue, m_DriverCancelable);
|
||||
_WdfQueueTriageInfo.RequestList1 = FIELD_OFFSET(FxIoQueue, m_Cancelled);
|
||||
_WdfQueueTriageInfo.RequestList2 = FIELD_OFFSET(FxIoQueue, m_CanceledOnQueueList);
|
||||
_WdfQueueTriageInfo.FwdProgressContext = FIELD_OFFSET(FxIoQueue, m_FwdProgContext);
|
||||
_WdfQueueTriageInfo.PkgIo = FIELD_OFFSET(FxIoQueue, m_PkgIo);
|
||||
|
||||
// Forward Progress
|
||||
_WdfFwdProgressTriageInfo.ReservedRequestList =
|
||||
FIELD_OFFSET(FXIO_FORWARD_PROGRESS_CONTEXT, m_ReservedRequestList);
|
||||
_WdfFwdProgressTriageInfo.ReservedRequestInUseList =
|
||||
FIELD_OFFSET(FXIO_FORWARD_PROGRESS_CONTEXT, m_ReservedRequestInUseList);
|
||||
_WdfFwdProgressTriageInfo.PendedIrpList =
|
||||
FIELD_OFFSET(FXIO_FORWARD_PROGRESS_CONTEXT, m_PendedIrpList);
|
||||
|
||||
// Irp Queue
|
||||
_WdfIrpQueueTriageInfo.IrpQueueSize = sizeof(FxIrpQueue);
|
||||
_WdfIrpQueueTriageInfo.IrpListHeader = FIELD_OFFSET(FxIrpQueue, m_Queue);
|
||||
_WdfIrpQueueTriageInfo.IrpListEntry = FIELD_OFFSET(IRP, Tail.Overlay.ListEntry);
|
||||
_WdfIrpQueueTriageInfo.IrpContext = FIELD_OFFSET(IRP,
|
||||
Tail.Overlay.DriverContext[FX_IRP_QUEUE_CSQ_CONTEXT_ENTRY]);
|
||||
|
||||
// WdfRequest
|
||||
_WdfRequestTriageInfo.RequestSize = sizeof(FxRequest);
|
||||
_WdfRequestTriageInfo.CsqContext = FIELD_OFFSET(FxRequest, m_CsqContext);
|
||||
_WdfRequestTriageInfo.FxIrp = FIELD_OFFSET(FxRequest, m_Irp);
|
||||
_WdfRequestTriageInfo.ListEntryQueueOwned =
|
||||
FIELD_OFFSET(FxRequest, m_OwnerListEntry);
|
||||
_WdfRequestTriageInfo.ListEntryQueueOwned2 =
|
||||
FIELD_OFFSET(FxRequest, m_OwnerListEntry2);
|
||||
_WdfRequestTriageInfo.RequestListEntry =
|
||||
FIELD_OFFSET(FxRequest, m_ListEntry);
|
||||
_WdfRequestTriageInfo.FwdProgressList =
|
||||
FIELD_OFFSET(FxRequest, m_ForwardProgressList);
|
||||
|
||||
// WdfDevice
|
||||
_WdfDeviceTriageInfo.DeviceInitSize = sizeof(WDFDEVICE_INIT);
|
||||
_WdfDeviceTriageInfo.DeviceDriver = FIELD_OFFSET(FxDevice, m_Driver);
|
||||
|
||||
// FxIrp
|
||||
_WdfIrpTriageInfo.FxIrpSize = sizeof(FxIrp);
|
||||
_WdfIrpTriageInfo.IrpPtr = FIELD_OFFSET(FxIrp, m_Irp);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
IsClientInfoValid(
|
||||
_In_ PCLIENT_INFO ClientInfo
|
||||
)
|
||||
{
|
||||
if (ClientInfo == NULL ||
|
||||
ClientInfo->Size != sizeof(CLIENT_INFO) ||
|
||||
ClientInfo->RegistryPath == NULL ||
|
||||
ClientInfo->RegistryPath->Length == 0 ||
|
||||
ClientInfo->RegistryPath->Buffer == NULL) {
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
VOID
|
||||
ReportDdiFunctionCountMismatch(
|
||||
_In_ PCUNICODE_STRING ServiceName,
|
||||
_In_ ULONG ActualFunctionCount,
|
||||
_In_ ULONG ExpectedFunctionCount
|
||||
)
|
||||
{
|
||||
WCHAR insertString[EVTLOG_DDI_COUNT_ERROR_MAX_LEN] = { 0 };
|
||||
NTSTATUS status;
|
||||
|
||||
//
|
||||
// NOTE: Any single call to DbgPrintEx will only transmit 512 bytes of
|
||||
// information.
|
||||
//
|
||||
DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL,
|
||||
"\n\n************************* \n"
|
||||
"* DDI function table mismatch detected in KMDF driver. The \n"
|
||||
"* driver will not load until it is re-compiled using a \n"
|
||||
"* newer version of the Windows Driver Kit (WDK). \n"
|
||||
);
|
||||
|
||||
DbgPrintEx(DPFLTR_DEFAULT_ID, DPFLTR_ERROR_LEVEL,
|
||||
"* Service name : %wZ\n"
|
||||
"* Actual function table count : %d \n"
|
||||
"* Expected function table count: %d \n"
|
||||
"*************************** \n\n",
|
||||
ServiceName,
|
||||
ActualFunctionCount,
|
||||
ExpectedFunctionCount
|
||||
);
|
||||
|
||||
//
|
||||
// Report a warning level ETW event to the system event log. "Wdf01000" is
|
||||
// the listed event provider.
|
||||
//
|
||||
status = RtlStringCchPrintfW(insertString,
|
||||
RTL_NUMBER_OF(insertString),
|
||||
L"Service:%wZ Count:Actual %d Expected %d",
|
||||
ServiceName,
|
||||
ActualFunctionCount,
|
||||
ExpectedFunctionCount);
|
||||
if (NT_SUCCESS(status)) {
|
||||
LibraryLogEvent(FxLibraryGlobals.DriverObject,
|
||||
WDFVER_CLIENT_INVALID_DDI_COUNT,
|
||||
STATUS_INVALID_PARAMETER,
|
||||
insertString,
|
||||
NULL,
|
||||
0);
|
||||
}
|
||||
|
||||
//
|
||||
// Report a telemetry event that can be used to proactively fix drivers
|
||||
//
|
||||
TraceLoggingWrite(g_TelemetryProvider,
|
||||
"KmdfClientFunctionCountMismatch",
|
||||
WDF_TELEMETRY_EVT_KEYWORDS,
|
||||
TraceLoggingUnicodeString(ServiceName, "ServiceName"),
|
||||
TraceLoggingUInt32(ActualFunctionCount, "FunctionCount"),
|
||||
TraceLoggingUInt32(ExpectedFunctionCount, "ExpectedCount"));
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxLibraryCommonCommission(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
DECLARE_CONST_UNICODE_STRING(usName, L"RtlGetVersion");
|
||||
PFN_RTL_GET_VERSION pRtlGetVersion = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
__Print((LITERAL(WDF_LIBRARY_COMMISSION) "\n"));
|
||||
|
||||
//
|
||||
// Commission this version's DLL globals.
|
||||
//
|
||||
status = FxLibraryGlobalsCommission();
|
||||
|
||||
if (!NT_SUCCESS(status)) {
|
||||
__Print(("FxLibraryGlobalsCommission failed %X\n", status));
|
||||
return status;
|
||||
}
|
||||
|
||||
//
|
||||
// register telemetry provider.
|
||||
//
|
||||
RegisterTelemetryProvider();
|
||||
|
||||
//
|
||||
// Initialize internal WPP tracing.
|
||||
//
|
||||
status = FxTraceInitialize();
|
||||
if (NT_SUCCESS(status)) {
|
||||
FxLibraryGlobals.InternalTracingInitialized = TRUE;
|
||||
}
|
||||
else {
|
||||
__Print(("Failed to initialize tracing for WDF\n"));
|
||||
|
||||
//
|
||||
// Failure to initialize is not critical enough to fail driver load.
|
||||
//
|
||||
status = STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Attempt to load RtlGetVersion (works for > w2k).
|
||||
//
|
||||
pRtlGetVersion = (PFN_RTL_GET_VERSION) MmGetSystemRoutineAddress(
|
||||
(PUNICODE_STRING) &usName
|
||||
);
|
||||
|
||||
//
|
||||
// Now attempt to get this OS's version.
|
||||
//
|
||||
if (pRtlGetVersion != NULL) {
|
||||
pRtlGetVersion(&gOsVersion);
|
||||
}
|
||||
|
||||
__Print(("OsVersion(%d.%d)\n",
|
||||
gOsVersion.dwMajorVersion,
|
||||
gOsVersion.dwMinorVersion ));
|
||||
|
||||
//
|
||||
// Init triage info for 9f bugcheck analysis.
|
||||
//
|
||||
GetTriageInfo();
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxLibraryCommonDecommission(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
__Print((LITERAL(WDF_LIBRARY_DECOMMISSION) ": enter\n"));
|
||||
|
||||
//
|
||||
// Uninitialize WPP tracing.
|
||||
//
|
||||
if (FxLibraryGlobals.InternalTracingInitialized) {
|
||||
TraceUninitialize();
|
||||
FxLibraryGlobals.InternalTracingInitialized = FALSE;
|
||||
}
|
||||
|
||||
//
|
||||
// Unregister telemetry provider.
|
||||
//
|
||||
UnregisterTelemetryProvider();
|
||||
|
||||
EventUnregisterMicrosoft_Windows_DriverFrameworks_KernelMode_Performance();
|
||||
|
||||
//
|
||||
// Decommission this version's DLL globals.
|
||||
//
|
||||
FxLibraryGlobalsDecommission();
|
||||
|
||||
//
|
||||
// Note: This is the absolute last action from WDF library (dynamic or static).
|
||||
// The image is likely to be deleted after returning.
|
||||
//
|
||||
__Print((LITERAL(WDF_LIBRARY_DECOMMISSION) ": exit\n"));
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxLibraryCommonRegisterClient(
|
||||
__inout PWDF_BIND_INFO Info,
|
||||
__deref_out PWDF_DRIVER_GLOBALS *WdfDriverGlobals,
|
||||
__in_opt PCLIENT_INFO ClientInfo
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
UNICODE_STRING serviceName = { 0 };
|
||||
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
__Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT) ": enter\n"));
|
||||
|
||||
if (Info == NULL || WdfDriverGlobals == NULL || Info->FuncTable == NULL) {
|
||||
__Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
|
||||
": NULL parameter -- %s\n",
|
||||
(Info == NULL) ? "PWDF_BIND_INFO" :
|
||||
(WdfDriverGlobals == NULL) ? "PWDF_DRIVER_GLOBALS *" :
|
||||
(Info->FuncTable == NULL) ? "PWDF_BIND_INFO->FuncTable" :
|
||||
"unknown" ));
|
||||
goto Done;
|
||||
}
|
||||
|
||||
ASSERT(Info->FuncCount);
|
||||
|
||||
|
||||
*WdfDriverGlobals = NULL;
|
||||
|
||||
//
|
||||
// WdfVersion.Count is initialized in FxDynamics.h and is never changed.
|
||||
// Prefast is unable to make that determination.
|
||||
//
|
||||
__assume(WdfVersion.FuncCount == sizeof(WDFFUNCTIONS)/sizeof(PVOID));
|
||||
|
||||
if (Info->FuncCount > WdfVersion.FuncCount) {
|
||||
__Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
|
||||
": version mismatch detected in function table count: client"
|
||||
"has 0x%x, library has 0x%x\n",
|
||||
Info->FuncCount, WdfVersion.FuncCount));
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (Info->FuncCount <= WdfFunctionTableNumEntries_V1_15) {
|
||||
//
|
||||
// Make sure table count matches exactly with previously
|
||||
// released framework version table sizes.
|
||||
//
|
||||
switch (Info->FuncCount) {
|
||||
|
||||
case WdfFunctionTableNumEntries_V1_15:
|
||||
case WdfFunctionTableNumEntries_V1_13:
|
||||
case WdfFunctionTableNumEntries_V1_11:
|
||||
case WdfFunctionTableNumEntries_V1_9:
|
||||
// case WdfFunctionTableNumEntries_V1_7: // both 1.7 and 1.5 have 387 functions
|
||||
case WdfFunctionTableNumEntries_V1_5:
|
||||
case WdfFunctionTableNumEntries_V1_1:
|
||||
case WdfFunctionTableNumEntries_V1_0:
|
||||
break;
|
||||
|
||||
default:
|
||||
__Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
|
||||
": Function table count 0x%x doesn't match any previously "
|
||||
"released framework version table size\n",
|
||||
Info->FuncCount));
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Client version is same as framework version. Make
|
||||
// sure table count is exact.
|
||||
if (Info->FuncCount != WdfFunctionTableNumEntries) {
|
||||
RtlZeroMemory(&serviceName, sizeof(UNICODE_STRING));
|
||||
|
||||
if (IsClientInfoValid(ClientInfo)) {
|
||||
GetNameFromPath(ClientInfo->RegistryPath, &serviceName);
|
||||
}
|
||||
else {
|
||||
RtlInitUnicodeString(&serviceName, L"Unknown");
|
||||
}
|
||||
|
||||
//
|
||||
// Report a DbgPrint message, telemetry event and an ETW event that
|
||||
// will serve as diagnostic aid.
|
||||
//
|
||||
ReportDdiFunctionCountMismatch((PCUNICODE_STRING)&serviceName,
|
||||
Info->FuncCount,
|
||||
WdfFunctionTableNumEntries);
|
||||
|
||||
//
|
||||
// If loader diagnostics are enabled and KD is connected, break-in
|
||||
//
|
||||
if (WdfLdrDbgPrintOn && KD_DEBUGGER_ENABLED &&
|
||||
!KD_DEBUGGER_NOT_PRESENT) {
|
||||
DbgBreakPoint();
|
||||
}
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate an new FxDriverGlobals area for this driver.
|
||||
//
|
||||
*WdfDriverGlobals = FxAllocateDriverGlobals();
|
||||
|
||||
if (*WdfDriverGlobals) {
|
||||
BOOLEAN isFunctinTableHookingOn = FALSE;
|
||||
BOOLEAN isPerformanceAnalysisOn = FALSE;
|
||||
PFX_DRIVER_GLOBALS fxDriverGlobals = NULL;
|
||||
|
||||
//
|
||||
// Check the registry to see if Enhanced verifier is on for this driver.
|
||||
// if registry read fails, options value remains unchanged.
|
||||
// store enhanced verifier options in driver globals
|
||||
//
|
||||
fxDriverGlobals = GetFxDriverGlobals(*WdfDriverGlobals);
|
||||
GetEnhancedVerifierOptions(ClientInfo, &fxDriverGlobals->FxEnhancedVerifierOptions);
|
||||
isFunctinTableHookingOn = IsFxVerifierFunctionTableHooking(fxDriverGlobals);
|
||||
isPerformanceAnalysisOn = IsFxPerformanceAnalysis(fxDriverGlobals);
|
||||
|
||||
//
|
||||
// Set-up the function table. Enhanced verifier and Performance analysis is off by default.
|
||||
//
|
||||
if (isFunctinTableHookingOn == FALSE && isPerformanceAnalysisOn == FALSE) {
|
||||
|
||||
//
|
||||
// Starting in 1.15 we reference a copy of the DDI table in WDF01000,
|
||||
// prior to that we copy the entire table to local memory.
|
||||
//
|
||||
if (Info->FuncCount <= WdfFunctionTableNumEntries_V1_13) {
|
||||
RtlCopyMemory( Info->FuncTable,
|
||||
&WdfVersion.Functions,
|
||||
Info->FuncCount * sizeof(PVOID) );
|
||||
}
|
||||
else {
|
||||
//
|
||||
// FuncTable arrives with a ptr to &WdfFunctions, so we update
|
||||
// what WdfFunctions points to.
|
||||
//
|
||||
*((WDFFUNC**) Info->FuncTable) = (WDFFUNC*) &WdfVersion.Functions;
|
||||
}
|
||||
}
|
||||
else {
|
||||
__Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
|
||||
": Enhanced Verification is ON \n"));
|
||||
|
||||
LockVerifierSection(fxDriverGlobals, ClientInfo->RegistryPath);
|
||||
|
||||
if (Microsoft_Windows_DriverFrameworks_KernelMode_PerformanceHandle == NULL) {
|
||||
EventRegisterMicrosoft_Windows_DriverFrameworks_KernelMode_Performance();
|
||||
}
|
||||
|
||||
//
|
||||
// Enhanced verification is on. Return verifier function table
|
||||
//
|
||||
// Starting in 1.15 we reference a copy of the DDI table in WDF01000,
|
||||
// prior to that we copy the entire table to local memory.
|
||||
//
|
||||
if (Info->FuncCount <= WdfFunctionTableNumEntries_V1_13) {
|
||||
RtlCopyMemory( Info->FuncTable,
|
||||
&VfWdfVersion.Functions,
|
||||
Info->FuncCount * sizeof(PVOID) );
|
||||
}
|
||||
else {
|
||||
//
|
||||
// FuncTable arrives with a ptr to &WdfFunctions, so we update
|
||||
// what WdfFunctions points to.
|
||||
//
|
||||
*((WDFFUNC**) Info->FuncTable) = (WDFFUNC*) &VfWdfVersion.Functions;
|
||||
}
|
||||
}
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
__Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
|
||||
": WdfFunctions %p\n", Info->FuncTable));
|
||||
}
|
||||
|
||||
Done:
|
||||
__Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
|
||||
": exit: status %X\n", status));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxLibraryCommonUnregisterClient(
|
||||
__in PWDF_BIND_INFO Info,
|
||||
__in PWDF_DRIVER_GLOBALS WdfDriverGlobals
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
|
||||
__Print((LITERAL(WDF_LIBRARY_UNREGISTER_CLIENT) ": enter\n"));
|
||||
|
||||
ASSERT(Info);
|
||||
ASSERT(WdfDriverGlobals);
|
||||
|
||||
if (Info != NULL && WdfDriverGlobals != NULL) {
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
pFxDriverGlobals = GetFxDriverGlobals(WdfDriverGlobals);
|
||||
|
||||
//
|
||||
// Destroy this FxDriver instance, if its still indicated.
|
||||
//
|
||||
if (pFxDriverGlobals->Driver != NULL) {
|
||||
//
|
||||
// Association support, we are a root with no parent
|
||||
//
|
||||
pFxDriverGlobals->Driver->DeleteObject();
|
||||
|
||||
FxDestroy(pFxDriverGlobals);
|
||||
}
|
||||
|
||||
//
|
||||
// Stop IFR logging
|
||||
//
|
||||
FxIFRStop(pFxDriverGlobals);
|
||||
|
||||
//
|
||||
// unlock enhanced-verifier image sections
|
||||
//
|
||||
if (IsFxVerifierFunctionTableHooking(pFxDriverGlobals)) {
|
||||
UnlockVerifierSection(pFxDriverGlobals);
|
||||
}
|
||||
|
||||
//
|
||||
// This will free the client's FxDriverGlobals area
|
||||
//
|
||||
FxFreeDriverGlobals(WdfDriverGlobals);
|
||||
}
|
||||
else {
|
||||
status = STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
|
||||
__Print((LITERAL(WDF_LIBRARY_UNREGISTER_CLIENT)
|
||||
": exit: status %X\n", status));
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID
|
||||
GetEnhancedVerifierOptions(
|
||||
__in PCLIENT_INFO ClientInfo,
|
||||
__out PULONG Options
|
||||
)
|
||||
{
|
||||
NTSTATUS status;
|
||||
ULONG value;
|
||||
FxAutoRegKey hKey, hWdf;
|
||||
DECLARE_CONST_UNICODE_STRING(parametersPath, L"Parameters\\Wdf");
|
||||
DECLARE_CONST_UNICODE_STRING(valueName, WDF_ENHANCED_VERIFIER_OPTIONS_VALUE_NAME);
|
||||
|
||||
*Options = 0;
|
||||
if (!IsClientInfoValid(ClientInfo) ||
|
||||
Options == NULL) {
|
||||
|
||||
__Print((LITERAL(WDF_LIBRARY_REGISTER_CLIENT)
|
||||
": Invalid ClientInfo received from wdfldr \n"));
|
||||
return;
|
||||
}
|
||||
|
||||
status = FxRegKey::_OpenKey(NULL,
|
||||
ClientInfo->RegistryPath,
|
||||
&hWdf.m_Key,
|
||||
KEY_READ);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
status = FxRegKey::_OpenKey(hWdf.m_Key,
|
||||
¶metersPath,
|
||||
&hKey.m_Key,
|
||||
KEY_READ);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return;
|
||||
}
|
||||
|
||||
status = FxRegKey::_QueryULong(
|
||||
hKey.m_Key, &valueName, &value);
|
||||
|
||||
//
|
||||
// Examine key values and set Options only on success.
|
||||
//
|
||||
if (NT_SUCCESS(status)) {
|
||||
if (value) {
|
||||
*Options = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
LibraryLogEvent(
|
||||
__in PDRIVER_OBJECT DriverObject,
|
||||
__in NTSTATUS ErrorCode,
|
||||
__in NTSTATUS FinalStatus,
|
||||
__in PWSTR ErrorInsertionString,
|
||||
__in_bcount(RawDataLen) PVOID RawDataBuf,
|
||||
__in USHORT RawDataLen
|
||||
)
|
||||
/*++
|
||||
|
||||
|
||||
Routine Description:
|
||||
|
||||
Logs an error to the system event log.
|
||||
|
||||
Arguments:
|
||||
|
||||
DriverObject - Pointer to driver object reporting the error.
|
||||
|
||||
ErrorCode - Indicates the type of error, system or driver-defined.
|
||||
|
||||
ErrorInsertionString - Null-terminated Unicode string inserted into error
|
||||
description, as defined by error code.
|
||||
|
||||
Return Value:
|
||||
|
||||
None.
|
||||
|
||||
--*/
|
||||
{
|
||||
PIO_ERROR_LOG_PACKET errorLogEntry;
|
||||
size_t errorLogEntrySize; // [including null]
|
||||
size_t errorInsertionStringByteSize = 0;
|
||||
|
||||
if (ErrorInsertionString) {
|
||||
errorInsertionStringByteSize = wcslen(ErrorInsertionString) * sizeof(WCHAR);
|
||||
errorInsertionStringByteSize += sizeof(UNICODE_NULL);
|
||||
}
|
||||
|
||||
errorLogEntrySize = sizeof(IO_ERROR_LOG_PACKET) + RawDataLen + errorInsertionStringByteSize;
|
||||
|
||||
//
|
||||
// Log an error.
|
||||
//
|
||||
//
|
||||
// prefast complains about comparison of constant with constant here
|
||||
//
|
||||
#pragma prefast(suppress:__WARNING_CONST_CONST_COMP, "If ErrorInsertionString is not null then this is not a constant")
|
||||
if (errorLogEntrySize <= ERROR_LOG_MAXIMUM_SIZE) {
|
||||
|
||||
errorLogEntry = (PIO_ERROR_LOG_PACKET)IoAllocateErrorLogEntry(DriverObject,
|
||||
(UCHAR)errorLogEntrySize);
|
||||
|
||||
if (errorLogEntry != NULL) {
|
||||
|
||||
RtlZeroMemory(errorLogEntry, errorLogEntrySize);
|
||||
|
||||
errorLogEntry->ErrorCode = ErrorCode;
|
||||
errorLogEntry->FinalStatus = FinalStatus;
|
||||
errorLogEntry->NumberOfStrings = (ErrorInsertionString) ? 1 : 0;
|
||||
errorLogEntry->DumpDataSize = RawDataLen;
|
||||
errorLogEntry->StringOffset = (FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData)) + errorLogEntry->DumpDataSize;
|
||||
|
||||
//
|
||||
// Insertion strings follow dumpdata and since there is no dumpdata we place the
|
||||
// insertion string at the start offset of the dumpdata.
|
||||
//
|
||||
if (RawDataBuf) {
|
||||
RtlCopyMemory(errorLogEntry->DumpData,
|
||||
RawDataBuf,
|
||||
RawDataLen);
|
||||
}
|
||||
|
||||
if (ErrorInsertionString) {
|
||||
RtlCopyMemory(((PCHAR)errorLogEntry->DumpData) + RawDataLen,
|
||||
ErrorInsertionString,
|
||||
errorInsertionStringByteSize);
|
||||
}
|
||||
|
||||
IoWriteErrorLogEntry(errorLogEntry);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
182
sdk/lib/drivers/wdf/kmdf/src/support/fxqueryinterface.cpp
Normal file
182
sdk/lib/drivers/wdf/kmdf/src/support/fxqueryinterface.cpp
Normal file
|
@ -0,0 +1,182 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxQueryInterface.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the device interface object.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "FxSupportPch.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxQueryInterface.tmh"
|
||||
}
|
||||
|
||||
FxQueryInterface::FxQueryInterface(
|
||||
__in FxDevice* Device,
|
||||
__in PWDF_QUERY_INTERFACE_CONFIG Config
|
||||
) :
|
||||
m_Device(Device),
|
||||
m_Interface(NULL)
|
||||
{
|
||||
m_Entry.Next = NULL;
|
||||
|
||||
m_EmbeddedInterface = FALSE;
|
||||
|
||||
if (Config != NULL) {
|
||||
m_SendQueryToParentStack = Config->SendQueryToParentStack;
|
||||
m_ImportInterface = Config->ImportInterface;
|
||||
m_ProcessRequest.m_Method = Config->EvtDeviceProcessQueryInterfaceRequest;
|
||||
RtlCopyMemory(&m_InterfaceType, Config->InterfaceType, sizeof(GUID));
|
||||
}
|
||||
}
|
||||
|
||||
FxQueryInterface::~FxQueryInterface()
|
||||
{
|
||||
//
|
||||
// Should not in any list
|
||||
//
|
||||
ASSERT(m_Entry.Next == NULL);
|
||||
|
||||
if (m_Interface != NULL && m_EmbeddedInterface == FALSE) {
|
||||
FxPoolFree(m_Interface);
|
||||
}
|
||||
}
|
||||
|
||||
VOID
|
||||
FxQueryInterface::_FormatIrp(
|
||||
__in PIRP Irp,
|
||||
__in const GUID* InterfaceGuid,
|
||||
__out PINTERFACE Interface,
|
||||
__in USHORT InterfaceSize,
|
||||
__in USHORT InterfaceVersion,
|
||||
__in_opt PVOID InterfaceSpecificData
|
||||
)
|
||||
{
|
||||
PIO_STACK_LOCATION stack;
|
||||
|
||||
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
|
||||
|
||||
stack = IoGetNextIrpStackLocation(Irp);
|
||||
|
||||
stack->MajorFunction = IRP_MJ_PNP;
|
||||
stack->MinorFunction = IRP_MN_QUERY_INTERFACE;
|
||||
|
||||
stack->Parameters.QueryInterface.Interface = Interface;
|
||||
stack->Parameters.QueryInterface.InterfaceSpecificData = InterfaceSpecificData;
|
||||
stack->Parameters.QueryInterface.Size = InterfaceSize;
|
||||
stack->Parameters.QueryInterface.Version = InterfaceVersion;
|
||||
stack->Parameters.QueryInterface.InterfaceType = InterfaceGuid;
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxQueryInterface::_QueryForInterface(
|
||||
__in PDEVICE_OBJECT TopOfStack,
|
||||
__in const GUID* InterfaceType,
|
||||
__out PINTERFACE Interface,
|
||||
__in USHORT Size,
|
||||
__in USHORT Version,
|
||||
__in_opt PVOID InterfaceSpecificData
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Send an IRP_MJPNP/IRP_MN_QUERY_INTERFACE irp to a device object and its
|
||||
attached stack.
|
||||
|
||||
Arguments:
|
||||
TargetDevice - device to send the query to.
|
||||
|
||||
InterfaceType - The type of interface to query for
|
||||
|
||||
Interface - The interface to fill out
|
||||
|
||||
Size - Size of Interface in bytes
|
||||
|
||||
Version - Version of the interface to be queried
|
||||
|
||||
InterfaceSpecificData - Addtional interface data to be queried
|
||||
|
||||
|
||||
Return Value:
|
||||
NTSTATUS as indicated by the handler of the QI with in the device stack,
|
||||
STATUS_NOT_SUPPORTED if the QI is not handled.
|
||||
|
||||
--*/
|
||||
{
|
||||
PIRP pIrp;
|
||||
NTSTATUS status;
|
||||
|
||||
pIrp = IoAllocateIrp(TopOfStack->StackSize, FALSE);
|
||||
|
||||
if (pIrp != NULL) {
|
||||
FxAutoIrp irp(pIrp);
|
||||
|
||||
_FormatIrp(
|
||||
pIrp,
|
||||
InterfaceType,
|
||||
Interface,
|
||||
Size,
|
||||
Version,
|
||||
InterfaceSpecificData
|
||||
);
|
||||
|
||||
status = irp.SendIrpSynchronously(TopOfStack);
|
||||
}
|
||||
else {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxQueryInterface::SetEmbedded(
|
||||
__in PWDF_QUERY_INTERFACE_CONFIG Config,
|
||||
__in PINTERFACE Interface
|
||||
)
|
||||
/*++
|
||||
|
||||
Routine Description:
|
||||
Marks the structure as embedded and sets the configuration. This is used
|
||||
for FxQueryInterface structs which are embedded in other structures because
|
||||
at contruction time the Config is not available yet.
|
||||
|
||||
By marking as embedded, FxPkgPnp will not free the structure when it deletes
|
||||
the query interface chain.
|
||||
|
||||
Arguments:
|
||||
Config - how the interface behaves
|
||||
|
||||
Interface - the interface that is exported
|
||||
|
||||
Return Value:
|
||||
None
|
||||
|
||||
--*/
|
||||
{
|
||||
m_EmbeddedInterface = TRUE;
|
||||
m_Interface = Interface;
|
||||
|
||||
m_SendQueryToParentStack = Config->SendQueryToParentStack;
|
||||
m_ImportInterface = Config->ImportInterface;
|
||||
m_ProcessRequest.m_Method = Config->EvtDeviceProcessQueryInterfaceRequest;
|
||||
RtlCopyMemory(&m_InterfaceType, Config->InterfaceType, sizeof(GUID));
|
||||
}
|
222
sdk/lib/drivers/wdf/kmdf/src/support/fxqueryinterfaceapi.cpp
Normal file
222
sdk/lib/drivers/wdf/kmdf/src/support/fxqueryinterfaceapi.cpp
Normal file
|
@ -0,0 +1,222 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
FxQueryInterfaceAPI.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the device interface object.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "FxSupportPch.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "FxQueryInterfaceAPI.tmh"
|
||||
}
|
||||
|
||||
//
|
||||
// Extern "C" the entire file
|
||||
//
|
||||
extern "C" {
|
||||
_Must_inspect_result_
|
||||
__drv_maxIRQL(PASSIVE_LEVEL)
|
||||
NTSTATUS
|
||||
WDFEXPORT(WdfDeviceAddQueryInterface)(
|
||||
__in
|
||||
PWDF_DRIVER_GLOBALS DriverGlobals,
|
||||
__in
|
||||
WDFDEVICE Device,
|
||||
__in
|
||||
PWDF_QUERY_INTERFACE_CONFIG InterfaceConfig
|
||||
)
|
||||
{
|
||||
PFX_DRIVER_GLOBALS pFxDriverGlobals;
|
||||
FxQueryInterface *pQueryInterface;
|
||||
FxDevice *pDevice;
|
||||
PINTERFACE pInterface;
|
||||
NTSTATUS status;
|
||||
|
||||
FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
|
||||
Device,
|
||||
FX_TYPE_DEVICE,
|
||||
(PVOID*) &pDevice,
|
||||
&pFxDriverGlobals );
|
||||
|
||||
pQueryInterface = NULL;
|
||||
|
||||
FxPointerNotNull(pFxDriverGlobals, Device);
|
||||
FxPointerNotNull(pFxDriverGlobals, InterfaceConfig);
|
||||
FxPointerNotNull(pFxDriverGlobals, InterfaceConfig->InterfaceType);
|
||||
|
||||
status = FxVerifierCheckIrqlLevel(pFxDriverGlobals, PASSIVE_LEVEL);
|
||||
if (!NT_SUCCESS(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
pInterface = InterfaceConfig->Interface;
|
||||
|
||||
if (InterfaceConfig->Size != sizeof(WDF_QUERY_INTERFACE_CONFIG)) {
|
||||
status = STATUS_INFO_LENGTH_MISMATCH;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
|
||||
"WDFDEVICE %p, WDF_QUERY_INTERFACE_CONFIG Size %d, expected %d, "
|
||||
"%!STATUS!", Device, InterfaceConfig->Size,
|
||||
sizeof(WDF_QUERY_INTERFACE_CONFIG), status);
|
||||
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// A pass through interface is only associated with PDOs
|
||||
//
|
||||
if (InterfaceConfig->SendQueryToParentStack && pDevice->IsPdo() == FALSE) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
|
||||
"SendQueryToParentStack TRUE, but WDFDEVICE %p not a PDO, %!STATUS!",
|
||||
Device, status);
|
||||
|
||||
goto Done;
|
||||
}
|
||||
|
||||
//
|
||||
// The only time we can have a NULL Interface is if the interface is
|
||||
// passthrough or it is an import interface (since on import interfaces
|
||||
// the callback must do the copying).
|
||||
//
|
||||
if (pInterface == NULL) {
|
||||
if (InterfaceConfig->SendQueryToParentStack || InterfaceConfig->ImportInterface) {
|
||||
//
|
||||
// A NULL interface is valid for this config
|
||||
//
|
||||
DO_NOTHING();
|
||||
}
|
||||
else {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
|
||||
"WDFDEVICE %p, SendQueryToParentStack is FALSE and "
|
||||
"InterfaceConfig->ImportInterface is FALSE, %!STATUS!",
|
||||
Device, status);
|
||||
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If it is an import interface, we need a callback so that the driver can
|
||||
// modify the interface being returned.
|
||||
//
|
||||
if (InterfaceConfig->ImportInterface &&
|
||||
InterfaceConfig->EvtDeviceProcessQueryInterfaceRequest == NULL) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
|
||||
"WDFDEVICE %p, ImportInterface is TRUE and "
|
||||
"EvtDeviceProcessQueryInterfaceRequest is NULL, %!STATUS!",
|
||||
Device, status);
|
||||
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (pInterface != NULL) {
|
||||
//
|
||||
// Make sure we are exposing the minimum size
|
||||
//
|
||||
if (pInterface->Size < sizeof(INTERFACE)) {
|
||||
status = STATUS_INVALID_PARAMETER;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
|
||||
"WDFDEVICE %p, Interface size %d < sizeof(INTERFACE) (%d), "
|
||||
"%!STATUS!", Device, pInterface->Size, sizeof(INTERFACE), status);
|
||||
|
||||
goto Done;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Since the QI irp is only allowed to be sent at passive level and
|
||||
// the list of FxQueryInterface's is locked by a lock which does not
|
||||
// raise IRQL, we can allocate the structure out paged pool.
|
||||
//
|
||||
pQueryInterface = new (pFxDriverGlobals, PagedPool)
|
||||
FxQueryInterface(pDevice, InterfaceConfig);
|
||||
|
||||
if (pQueryInterface == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
|
||||
"WDFDEVICE %p, object creation failed, %!STATUS!", Device, status);
|
||||
|
||||
goto Done;
|
||||
}
|
||||
|
||||
if (pInterface != NULL) {
|
||||
//
|
||||
// Try to allocate memory for the interface.
|
||||
//
|
||||
pQueryInterface->m_Interface = (PINTERFACE)
|
||||
FxPoolAllocate(pFxDriverGlobals, PagedPool, pInterface->Size);
|
||||
|
||||
if (pQueryInterface->m_Interface == NULL) {
|
||||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||||
|
||||
DoTraceLevelMessage(
|
||||
pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGERROR,
|
||||
"WDFDEVICE %p, interface allocation failed, %!STATUS!",
|
||||
Device, status);
|
||||
|
||||
goto Done;
|
||||
}
|
||||
|
||||
RtlCopyMemory(pQueryInterface->m_Interface,
|
||||
pInterface,
|
||||
pInterface->Size);
|
||||
|
||||
if (pInterface->InterfaceReference == NULL) {
|
||||
pQueryInterface->m_Interface->InterfaceReference =
|
||||
FxDevice::_InterfaceReferenceNoOp;
|
||||
}
|
||||
if (pInterface->InterfaceDereference == NULL) {
|
||||
pQueryInterface->m_Interface->InterfaceDereference =
|
||||
FxDevice::_InterfaceDereferenceNoOp;
|
||||
}
|
||||
}
|
||||
|
||||
status = STATUS_SUCCESS;
|
||||
|
||||
pDevice->m_PkgPnp->AddQueryInterface(pQueryInterface, TRUE);
|
||||
|
||||
Done:
|
||||
//
|
||||
// Delete the query interface structure if there is an error.
|
||||
//
|
||||
if (!NT_SUCCESS(status) && pQueryInterface != NULL) {
|
||||
delete pQueryInterface;
|
||||
pQueryInterface = NULL;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
} // extern "C"
|
44
sdk/lib/drivers/wdf/kmdf/src/support/fxrelateddevice.cpp
Normal file
44
sdk/lib/drivers/wdf/kmdf/src/support/fxrelateddevice.cpp
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
FxRelatedDevice.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
This module implements the FxRelatedDevice class which is used in usage
|
||||
notification propagation
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "FxSupportPch.hpp"
|
||||
|
||||
FxRelatedDevice::FxRelatedDevice(
|
||||
__in PDEVICE_OBJECT DeviceObject,
|
||||
__in PFX_DRIVER_GLOBALS Globals
|
||||
) : FxObject(FX_TYPE_RELATED_DEVICE, 0, Globals),
|
||||
m_DeviceObject(DeviceObject),
|
||||
m_State(RelatedDeviceStateNeedsReportPresent)
|
||||
{
|
||||
m_TransactionedEntry.SetTransactionedObject(this);
|
||||
ObReferenceObject(m_DeviceObject);
|
||||
}
|
||||
|
||||
FxRelatedDevice::~FxRelatedDevice(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
ObDereferenceObject(m_DeviceObject);
|
||||
}
|
150
sdk/lib/drivers/wdf/kmdf/src/support/fxrelateddevicelist.cpp
Normal file
150
sdk/lib/drivers/wdf/kmdf/src/support/fxrelateddevicelist.cpp
Normal file
|
@ -0,0 +1,150 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
FxDependentList.cpp
|
||||
|
||||
Abstract:
|
||||
This object derives from the transactioned list and provides a unique
|
||||
object check during the addition of an item.
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include "FxSupportPch.hpp"
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxRelatedDeviceList::Add(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__inout FxRelatedDevice* Entry
|
||||
)
|
||||
{
|
||||
return FxSpinLockTransactionedList::Add(FxDriverGlobals,
|
||||
&Entry->m_TransactionedEntry);
|
||||
}
|
||||
|
||||
VOID
|
||||
FxRelatedDeviceList::Remove(
|
||||
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
|
||||
__in PDEVICE_OBJECT Device
|
||||
)
|
||||
{
|
||||
SearchForAndRemove(FxDriverGlobals, (PVOID) Device);
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
FxRelatedDevice*
|
||||
FxRelatedDeviceList::GetNextEntry(
|
||||
__in_opt FxRelatedDevice* Entry
|
||||
)
|
||||
{
|
||||
FxTransactionedEntry *pReturn, *pEntry;
|
||||
|
||||
if (Entry == NULL) {
|
||||
pEntry = NULL;
|
||||
}
|
||||
else {
|
||||
pEntry = &Entry->m_TransactionedEntry;
|
||||
}
|
||||
|
||||
pReturn = FxSpinLockTransactionedList::GetNextEntry(pEntry);
|
||||
|
||||
if (pReturn != NULL) {
|
||||
return CONTAINING_RECORD(pReturn, FxRelatedDevice, m_TransactionedEntry);
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
_Must_inspect_result_
|
||||
NTSTATUS
|
||||
FxRelatedDeviceList::ProcessAdd(
|
||||
__in FxTransactionedEntry *NewEntry
|
||||
)
|
||||
{
|
||||
FxRelatedDevice* pNew, *pInList;
|
||||
FxTransactionedEntry *pEntry;
|
||||
PLIST_ENTRY ple;
|
||||
|
||||
pNew = CONTAINING_RECORD(NewEntry, FxRelatedDevice, m_TransactionedEntry);
|
||||
|
||||
pEntry = NULL;
|
||||
|
||||
//
|
||||
// Go over the transactions first because the device could be in the real
|
||||
// list with a transaction to remove it, so we catch first here instead
|
||||
// of adding complexity to the iteration of the already inserted list.
|
||||
//
|
||||
for (ple = m_TransactionHead.Flink;
|
||||
ple != &m_TransactionHead;
|
||||
ple = ple->Flink) {
|
||||
pEntry = FxTransactionedEntry::_FromEntry(ple);
|
||||
pInList = CONTAINING_RECORD(pEntry, FxRelatedDevice, m_TransactionedEntry);
|
||||
|
||||
if (pInList->m_DeviceObject == pNew->m_DeviceObject) {
|
||||
if (pEntry->GetTransactionAction() == FxTransactionActionAdd) {
|
||||
//
|
||||
// An additional add, failure
|
||||
//
|
||||
return STATUS_DUPLICATE_OBJECTID;
|
||||
}
|
||||
|
||||
|
||||
// Removal is OK b/c our add will be right behind it
|
||||
//
|
||||
ASSERT(pEntry->GetTransactionAction() == FxTransactionActionRemove);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
pEntry = NULL;
|
||||
while ((pEntry = __super::GetNextEntryLocked(pEntry)) != NULL) {
|
||||
pInList = CONTAINING_RECORD(pEntry, FxRelatedDevice, m_TransactionedEntry);
|
||||
|
||||
if (pInList->m_DeviceObject == pNew->m_DeviceObject) {
|
||||
return STATUS_DUPLICATE_OBJECTID;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
FxRelatedDeviceList::Compare(
|
||||
__in FxTransactionedEntry* Entry,
|
||||
__in PVOID Data
|
||||
)
|
||||
{
|
||||
FxRelatedDevice *pRelated;
|
||||
|
||||
pRelated = CONTAINING_RECORD(Entry, FxRelatedDevice, m_TransactionedEntry);
|
||||
|
||||
return pRelated->GetDevice() == (PDEVICE_OBJECT) Data ? TRUE : FALSE;
|
||||
}
|
||||
|
||||
VOID
|
||||
FxRelatedDeviceList::EntryRemoved(
|
||||
__in FxTransactionedEntry* Entry
|
||||
)
|
||||
{
|
||||
FxRelatedDevice *pRelated;
|
||||
|
||||
pRelated = CONTAINING_RECORD(Entry, FxRelatedDevice, m_TransactionedEntry);
|
||||
|
||||
if (pRelated->m_State == RelatedDeviceStateReportedPresent) {
|
||||
m_NeedReportMissing++;
|
||||
}
|
||||
}
|
32
sdk/lib/drivers/wdf/kmdf/src/support/fxsupportpch.hpp
Normal file
32
sdk/lib/drivers/wdf/kmdf/src/support/fxsupportpch.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
Module Name:
|
||||
|
||||
fxsupportpch.h
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains header definitions and include files needed by all
|
||||
modules in fx\support
|
||||
|
||||
Author:
|
||||
|
||||
Environment:
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef __FX_SUPPORT_PCH_HPP__
|
||||
#define __FX_SUPPORT_PCH_HPP__
|
||||
|
||||
extern "C" {
|
||||
#include <ntddk.h>
|
||||
}
|
||||
|
||||
#include <fx.hpp>
|
||||
|
||||
#endif // __FX_SUPPORT_PCH_HPP__
|
79
sdk/lib/drivers/wdf/kmdf/src/support/probeandlock.c
Normal file
79
sdk/lib/drivers/wdf/kmdf/src/support/probeandlock.c
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*++
|
||||
|
||||
Copyright (c) Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
ProbeAndLock.c
|
||||
|
||||
Abstract:
|
||||
|
||||
This module contains C routines for probing and locking
|
||||
down memory buffers.
|
||||
|
||||
|
||||
Author:
|
||||
|
||||
|
||||
|
||||
Environment:
|
||||
|
||||
Kernel mode only
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
//
|
||||
// These routines must be implemented in a C file to avoid problems
|
||||
// with C++ exception handling errors.
|
||||
//
|
||||
|
||||
#include <ntddk.h>
|
||||
|
||||
NTSTATUS
|
||||
FxProbeAndLockForRead(
|
||||
__in PMDL Mdl,
|
||||
__in KPROCESSOR_MODE AccessMode
|
||||
)
|
||||
{
|
||||
try {
|
||||
MmProbeAndLockPages(Mdl, AccessMode, IoReadAccess);
|
||||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
return GetExceptionCode();
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxProbeAndLockForWrite(
|
||||
__in PMDL Mdl,
|
||||
__in KPROCESSOR_MODE AccessMode
|
||||
)
|
||||
{
|
||||
try {
|
||||
MmProbeAndLockPages(Mdl, AccessMode, IoWriteAccess);
|
||||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
return GetExceptionCode();
|
||||
}
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS
|
||||
FxProbeAndLockWithAccess(
|
||||
__in PMDL Mdl,
|
||||
__in KPROCESSOR_MODE AccessMode,
|
||||
__in LOCK_OPERATION Operation
|
||||
)
|
||||
{
|
||||
try {
|
||||
MmProbeAndLockPages(Mdl, AccessMode, Operation);
|
||||
} except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
return GetExceptionCode();
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue