reactos/sdk/lib/drivers/wdf/shared/inc/private/common/fxresource.hpp
Victor Perevertkin 8a978a179f
[WDF] Add Windows Driver Framework files
Takern from Microsoft GitHub repo:
d9c6040fe9

Licensed under MIT
2020-11-03 00:06:26 +03:00

749 lines
16 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Module Name:
FxResource.hpp
Abstract:
This module implements the resource object.
Author:
Environment:
Both kernel and user mode
Revision History:
--*/
#ifndef _FXRESOURCE_H_
#define _FXRESOURCE_H_
extern "C" {
#if defined(EVENT_TRACING)
#include "FxResource.hpp.tmh"
#endif
}
#if (FX_CORE_MODE==FX_CORE_USER_MODE)
struct FxRegisterResourceInfo : FxStump {
//
// start physical address of resource range assigned by pnp
//
PHYSICAL_ADDRESS m_StartPa;
//
// start of mapped system base address
//
PVOID m_StartSystemVa;
//
// end of mapped system base address
//
PVOID m_EndSystemVa;
//
// user-mode mapped address
//
PVOID m_StartUsermodeVa;
//
// Length of resource range assigned by pnp
//
SIZE_T m_Length;
//
// Length of mapped resource range
//
SIZE_T m_MappedLength;
static
NTSTATUS
_CreateAndInit(
_In_ PFX_DRIVER_GLOBALS DriverGlobals,
_In_ ULONG Count,
_Out_ FxRegisterResourceInfo** RegisterTable
)
{
NTSTATUS status;
FxRegisterResourceInfo* table;
ASSERT(RegisterTable != NULL);
*RegisterTable = NULL;
table = new (DriverGlobals) FxRegisterResourceInfo[Count];
if (table == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
DoTraceLevelMessage(
DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
"Failed to allocate Resource table %!STATUS!", status);
return status;
}
*RegisterTable = table;
status = STATUS_SUCCESS;
return status;
}
FxRegisterResourceInfo(
VOID
):
m_StartSystemVa(NULL),
m_EndSystemVa(NULL),
m_StartUsermodeVa(NULL),
m_Length(0),
m_MappedLength(0)
{
m_StartPa.QuadPart = 0;
};
~FxRegisterResourceInfo(){;};
VOID
SetPhysicalAddress(
__in PHYSICAL_ADDRESS StartPa,
__in SIZE_T Length
)
{
m_StartPa = StartPa;
m_Length = Length;
}
VOID
SetMappedAddress(
__in PVOID SystemBaseAddress,
__in SIZE_T MappedLength,
__in PVOID UsermodeBaseAddress
)
{
m_StartSystemVa = SystemBaseAddress;
m_MappedLength = MappedLength;
m_EndSystemVa = ((PUCHAR) m_StartSystemVa) + MappedLength - 1;
m_StartUsermodeVa = UsermodeBaseAddress;
};
VOID
ClearMappedAddress(
VOID
)
{
m_StartSystemVa = NULL;
m_EndSystemVa = NULL;
m_StartUsermodeVa = NULL;
m_MappedLength = 0;
};
};
struct FxPortResourceInfo : FxStump {
//
// start physical address
//
PHYSICAL_ADDRESS m_StartPa;
//
// end physical address
//
PHYSICAL_ADDRESS m_EndPa;
//
// Length of resource
//
SIZE_T m_Length;
static
NTSTATUS
_CreateAndInit(
_In_ PFX_DRIVER_GLOBALS DriverGlobals,
_In_ ULONG Count,
_Out_ FxPortResourceInfo** PortTable
)
{
NTSTATUS status;
FxPortResourceInfo* table;
ASSERT(PortTable != NULL);
*PortTable = NULL;
table = new (DriverGlobals) FxPortResourceInfo[Count];
if (table == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
DoTraceLevelMessage(
DriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
"Failed to allocate Resource table %!STATUS!", status);
return status;
}
*PortTable = table;
status = STATUS_SUCCESS;
return status;
}
FxPortResourceInfo(
VOID
):
m_Length(0)
{
m_StartPa.QuadPart = 0;
m_EndPa.QuadPart = 0;
};
~FxPortResourceInfo(){;};
VOID
SetPhysicalAddress(
__in PHYSICAL_ADDRESS StartPa,
__in SIZE_T Length
)
{
m_StartPa = StartPa;
m_EndPa.QuadPart = StartPa.QuadPart + Length - 1;
m_Length = Length;
}
};
#endif
//
// Used in FilterResourceRequirements, and QueryResourceRequirements
//
class FxResourceIo : public FxObject {
public:
IO_RESOURCE_DESCRIPTOR m_Descriptor;
//
// Clone of m_Descriptor which is returned to the driver writer when it
// requests a descriptor pointer. We clone the descriptor so that if the
// driver writer attempts to modify the pointer in place, they modify the
// clone and not the real descriptor.
//
IO_RESOURCE_DESCRIPTOR m_DescriptorClone;
public:
FxResourceIo(
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
__in PIO_RESOURCE_DESCRIPTOR Resource
) : FxObject(FX_TYPE_RESOURCE_IO, 0, FxDriverGlobals)
{
RtlCopyMemory(&m_Descriptor, Resource, sizeof(m_Descriptor));
}
DECLARE_INTERNAL_NEW_OPERATOR();
};
//
// Used in StartDevice
//
class FxResourceCm : public FxObject {
public:
CM_PARTIAL_RESOURCE_DESCRIPTOR m_Descriptor;
//
// Clone of m_Descriptor which is returned to the driver writer when it
// requests a descriptor pointer. We clone the descriptor so that if the
// driver writer attempts to modify the pointer in place, they modify the
// clone and not the real descriptor.
//
CM_PARTIAL_RESOURCE_DESCRIPTOR m_DescriptorClone;
public:
FxResourceCm(
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
__in PCM_PARTIAL_RESOURCE_DESCRIPTOR Resource
) : FxObject(FX_TYPE_RESOURCE_CM, 0, FxDriverGlobals)
{
RtlCopyMemory(&m_Descriptor, Resource, sizeof(m_Descriptor));
}
DECLARE_INTERNAL_NEW_OPERATOR();
};
enum FxResourceAccessFlags {
FxResourceNoAccess = 0x0000,
FxResourceAddAllowed = 0x0001,
FxResourceRemoveAllowed = 0x0002,
FxResourceAllAccessAllowed = FxResourceAddAllowed | FxResourceRemoveAllowed,
};
class FxResourceCollection : public FxCollection {
protected:
FxResourceCollection(
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
__in WDFTYPE Type,
__in USHORT Size,
__in UCHAR AccessFlags = FxResourceNoAccess
) : FxCollection(FxDriverGlobals, Type, Size),
m_AccessFlags(AccessFlags), m_Changed(FALSE)
{
//
// Driver cannot delete this or any of its derivations
//
MarkNoDeleteDDI();
}
public:
BOOLEAN
RemoveAndDelete(
__in ULONG Index
);
_Must_inspect_result_
NTSTATUS
AddAt(
__in ULONG Index,
__in FxObject* Object
);
BOOLEAN
IsRemoveAllowed(
VOID
)
{
return FLAG_TO_BOOL(m_AccessFlags, FxResourceRemoveAllowed);
}
BOOLEAN
IsAddAllowed(
VOID
)
{
return FLAG_TO_BOOL(m_AccessFlags, FxResourceAddAllowed);
}
VOID
MarkChanged(
VOID
)
{
m_Changed = TRUE;
}
BOOLEAN
IsChanged(
VOID
)
{
return m_Changed;
}
public:
UCHAR m_AccessFlags;
BOOLEAN m_Changed;
};
class FxCmResList : public FxResourceCollection {
#if (FX_CORE_MODE==FX_CORE_USER_MODE)
protected:
//
// Table of mapped register resources
//
FxRegisterResourceInfo* m_RegisterResourceTable;
ULONG m_RegisterResourceTableSizeCe;
//
// Table of port resources
//
FxPortResourceInfo* m_PortResourceTable;
ULONG m_PortResourceTableSizeCe;
//
// TRUE if we have at least one CmResourceTypeConnection resource.
//
BOOLEAN m_HasConnectionResources;
//
// Lock to serialize access to port/register resource table
//
MxLock m_ResourceTableLock;
#endif // FX_CORE_USER_MODE
protected:
FxCmResList(
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
__in UCHAR AccessFlags
) : FxResourceCollection(FxDriverGlobals,
FX_TYPE_CM_RES_LIST,
sizeof(FxCmResList),
AccessFlags)
{
#if (FX_CORE_MODE==FX_CORE_USER_MODE)
m_RegisterResourceTable = NULL;
m_PortResourceTable = NULL;
m_RegisterResourceTableSizeCe = 0;
m_PortResourceTableSizeCe = 0;
m_HasConnectionResources = FALSE;
#endif // FX_CORE_USER_MODE
}
~FxCmResList();
public:
static
_Must_inspect_result_
NTSTATUS
_CreateAndInit(
__in FxCmResList** ResourceList,
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
__in CfxDevice * Device,
__in_opt PWDF_OBJECT_ATTRIBUTES ListAttributes,
__in UCHAR AccessFlags
)
{
NTSTATUS ntStatus;
FxCmResList *resList = NULL;
UNREFERENCED_PARAMETER(Device);
//
// Initialize
//
*ResourceList = NULL;
//
// Allocate a new resource list object
//
resList = new(FxDriverGlobals, ListAttributes)
FxCmResList(FxDriverGlobals, AccessFlags);
if (resList == NULL) {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR,
TRACINGDEVICE,
"Failed to allocate FxCmResList, "
"returning %!STATUS!",
ntStatus);
goto exit;
}
*ResourceList = resList;
ntStatus = STATUS_SUCCESS;
exit:
if (!NT_SUCCESS(ntStatus)) {
if (NULL != resList) {
resList->DeleteFromFailedCreate();
}
}
return ntStatus;
}
WDFCMRESLIST
GetHandle(
VOID
)
{
return (WDFCMRESLIST) GetObjectHandle();
}
_Must_inspect_result_
NTSTATUS
BuildFromWdmList(
__in PCM_RESOURCE_LIST ResourceList,
__in UCHAR AccessFlags
);
_Must_inspect_result_
PCM_RESOURCE_LIST
CreateWdmList(
__in __drv_strictTypeMatch(__drv_typeExpr) POOL_TYPE PoolType = PagedPool
);
ULONG
GetCount(
VOID
);
PCM_PARTIAL_RESOURCE_DESCRIPTOR
GetDescriptor(
__in ULONG Index
);
#if (FX_CORE_MODE == FX_CORE_USER_MODE)
//
// Lock functions used internally
//
__inline
void
#pragma prefast(suppress:__WARNING_UNEXPECTED_IRQL_CHANGE, "UM has no IRQL")
LockResourceTable(
)
{
KIRQL oldIrql;
m_ResourceTableLock.Acquire(&oldIrql);
UNREFERENCED_PARAMETER(oldIrql);
}
__inline
void
#pragma prefast(suppress:__WARNING_UNEXPECTED_IRQL_CHANGE, "UM has no IRQL")
UnlockResourceTable(
)
{
m_ResourceTableLock.Release(PASSIVE_LEVEL);
}
NTSTATUS
BuildRegisterResourceTable(
VOID
);
NTSTATUS
BuildPortResourceTable(
VOID
);
VOID
UpdateRegisterResourceEntryLocked(
__in FxRegisterResourceInfo* Entry,
__in PVOID SystemMappedAddress,
__in SIZE_T NumberOfBytes,
__in PVOID UsermodeMappedAddress
);
VOID
ClearRegisterResourceEntryLocked(
__in FxRegisterResourceInfo* Entry
);
HRESULT
ValidateRegisterPhysicalAddressRange (
__in PHYSICAL_ADDRESS PhysicalAddress,
__in SIZE_T Size,
__out FxRegisterResourceInfo** TableEntry
);
HRESULT
ValidateRegisterSystemBaseAddress (
__in PVOID Address,
__out PVOID* UsermodeBaseAddress
);
HRESULT
ValidateRegisterSystemAddressRange (
__in PVOID SystemAddress,
__in SIZE_T Length,
__out_opt PVOID* UsermodeAddress
);
HRESULT
ValidateAndClearMapping(
__in PVOID Address,
__in SIZE_T Length
);
HRESULT
ValidatePortAddressRange(
__in PVOID Address,
__in SIZE_T Length
);
SIZE_T
GetResourceLength(
__in PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
__out_opt PHYSICAL_ADDRESS* Start
);
HRESULT
MapIoSpaceWorker(
__in PHYSICAL_ADDRESS PhysicalAddress,
__in SIZE_T NumberOfBytes,
__in MEMORY_CACHING_TYPE CacheType,
__deref_out VOID** PseudoBaseAddress
);
VOID
ValidateResourceUnmap(
VOID
);
VOID
DeleteRegisterResourceTable(
VOID
)
{
LockResourceTable();
if (m_RegisterResourceTable != NULL) {
delete [] m_RegisterResourceTable;
m_RegisterResourceTable = NULL;
m_RegisterResourceTableSizeCe = 0;
}
UnlockResourceTable();
}
VOID
DeletePortResourceTable(
VOID
)
{
LockResourceTable();
if (m_PortResourceTable != NULL) {
delete [] m_PortResourceTable;
m_PortResourceTable = NULL;
m_PortResourceTableSizeCe = 0;
}
UnlockResourceTable();
}
_Must_inspect_result_
NTSTATUS
CheckForConnectionResources(
VOID
);
BOOLEAN
HasConnectionResources(
VOID
)
{
return m_HasConnectionResources;
}
#endif // FX_CORE_USER_MODE
};
class FxIoResReqList : public FxResourceCollection {
protected:
FxIoResReqList(
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
__in UCHAR AccessFlags = FxResourceNoAccess
) :
FxResourceCollection(FxDriverGlobals,
FX_TYPE_IO_RES_REQ_LIST,
sizeof(FxIoResReqList),
AccessFlags),
m_SlotNumber(0), m_InterfaceType(Internal)
{
m_AccessFlags = AccessFlags;
}
public:
static
_Must_inspect_result_
NTSTATUS
_CreateAndInit(
__in FxIoResReqList** ResourceReqList,
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
__in_opt PWDF_OBJECT_ATTRIBUTES ListAttributes,
__in UCHAR AccessFlags
)
{
NTSTATUS ntStatus;
FxIoResReqList *resReqList = NULL;
//
// Initialize
//
*ResourceReqList = NULL;
//
// Allocate a new resource list object
//
resReqList = new(FxDriverGlobals, ListAttributes)
FxIoResReqList(FxDriverGlobals, AccessFlags);
if (resReqList == NULL) {
ntStatus = STATUS_INSUFFICIENT_RESOURCES;
DoTraceLevelMessage(FxDriverGlobals, TRACE_LEVEL_ERROR,
TRACINGDEVICE,
"Failed to allocate FxIoResReqList, "
"returning %!STATUS!",
ntStatus);
goto exit;
}
*ResourceReqList = resReqList;
ntStatus = STATUS_SUCCESS;
exit:
if (!NT_SUCCESS(ntStatus)) {
if (NULL != resReqList) {
resReqList->DeleteFromFailedCreate();
}
}
return ntStatus;
}
WDFIORESREQLIST
GetHandle(
VOID
)
{
return (WDFIORESREQLIST) GetObjectHandle();
}
static
_Must_inspect_result_
FxIoResReqList*
_CreateFromWdmList(
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
__in PIO_RESOURCE_REQUIREMENTS_LIST WdmRequirementsList,
__in UCHAR AccessFlags
);
_Must_inspect_result_
PIO_RESOURCE_REQUIREMENTS_LIST
CreateWdmList(
VOID
);
public:
ULONG m_SlotNumber;
INTERFACE_TYPE m_InterfaceType;
};
class FxIoResList : public FxResourceCollection {
public:
FxIoResList(
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
__in FxIoResReqList* RequirementsList
) :
FxResourceCollection(FxDriverGlobals, FX_TYPE_IO_RES_LIST, sizeof(FxIoResList)),
m_OwningList(RequirementsList)
{
m_AccessFlags = RequirementsList->m_AccessFlags;
}
WDFIORESLIST
GetHandle(
VOID
)
{
return (WDFIORESLIST) GetObjectHandle();
}
_Must_inspect_result_
NTSTATUS
BuildFromWdmList(
__deref_in PIO_RESOURCE_LIST* WdmResourceList
);
public:
FxIoResReqList* m_OwningList;
};
#endif // _FXRESOURCE_H_