mirror of
https://github.com/reactos/reactos.git
synced 2025-03-10 10:14:44 +00:00
749 lines
16 KiB
C++
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_
|