[WDF] Add Windows Driver Framework files
[reactos.git] / sdk / lib / drivers / wdf / shared / inc / private / common / fxresource.hpp
diff --git a/sdk/lib/drivers/wdf/shared/inc/private/common/fxresource.hpp b/sdk/lib/drivers/wdf/shared/inc/private/common/fxresource.hpp
new file mode 100644 (file)
index 0000000..05d8155
--- /dev/null
@@ -0,0 +1,749 @@
+/*++
+
+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_