--- /dev/null
+/*++
+
+Copyright (c) Microsoft Corporation
+
+Module Name:
+
+ FxResourceAPI.cpp
+
+Abstract:
+
+ This module implements the resource class.
+
+Author:
+
+
+
+
+Environment:
+
+ Both kernel and user mode
+
+Revision History:
+
+--*/
+#include "FxSupportPch.hpp"
+
+extern "C" {
+#include "FxResourceAPI.tmh"
+}
+
+//
+// Extern "C" the entire file
+//
+extern "C" {
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfIoResourceRequirementsListSetSlotNumber)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESREQLIST RequirementsList,
+ __in
+ ULONG SlotNumber
+ )
+/*++
+
+Routine Description:
+ Sets the slot number for a given resource requirements list
+
+Arguments:
+ RequirementsList - list to be modified
+
+ SlotNumber - slot value to assign
+
+Return Value:
+ None
+
+ --*/
+{
+ FxIoResReqList* pIoResReqList;
+
+ FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
+ RequirementsList,
+ FX_TYPE_IO_RES_REQ_LIST,
+ (PVOID*) &pIoResReqList);
+
+ if (pIoResReqList->m_SlotNumber != SlotNumber) {
+ pIoResReqList->MarkChanged();
+ }
+ pIoResReqList->m_SlotNumber = SlotNumber;
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfIoResourceRequirementsListSetInterfaceType)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESREQLIST RequirementsList,
+ __in
+ __drv_strictTypeMatch(__drv_typeCond)
+ INTERFACE_TYPE InterfaceType
+ )
+/*++
+
+Routine Description:
+ Sets the InterfaceType for a given resource requirements list
+
+Arguments:
+ RequirementsList - list to be modified
+
+ InterfaceType - interface type to assign
+
+Return Value:
+ None
+
+ --*/
+{
+ FxIoResReqList* pIoResReqList;
+
+ FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
+ RequirementsList,
+ FX_TYPE_IO_RES_REQ_LIST,
+ (PVOID*) &pIoResReqList);
+
+ if (pIoResReqList->m_InterfaceType != InterfaceType) {
+ pIoResReqList->MarkChanged();
+ }
+
+ pIoResReqList->m_InterfaceType = InterfaceType;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(DISPATCH_LEVEL)
+NTSTATUS
+FxIoResourceRequirementsListInsertIoResList(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESREQLIST RequirementsList,
+ __in
+ WDFIORESLIST IoResList,
+ ULONG Index
+ )
+/*++
+
+Routine Description:
+ Inserts a resource list into a requirements list at a particular index.
+
+Arguments:
+ RequirementsList - list to be modified
+
+ IoResList - resource list to add
+
+ Index - zero based index to insert at
+
+Return Value:
+ NTSTATUS
+
+ --*/
+{
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxIoResReqList* pIoResReqList;
+ FxIoResList* pIoResList;
+ NTSTATUS status;
+
+ FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
+ RequirementsList,
+ FX_TYPE_IO_RES_REQ_LIST,
+ (PVOID*) &pIoResReqList,
+ &pFxDriverGlobals);
+
+ FxObjectHandleGetPtr(pFxDriverGlobals,
+ IoResList,
+ FX_TYPE_IO_RES_LIST,
+ (PVOID*) &pIoResList);
+
+ if (pIoResList->m_OwningList != pIoResReqList) {
+ return STATUS_INVALID_DEVICE_REQUEST;
+ }
+
+ status = pIoResReqList->AddAt(Index, pIoResList);
+
+ if (NT_SUCCESS(status)) {
+ //
+ // Mirror the access flags as well.
+ //
+ pIoResList->m_AccessFlags = pIoResReqList->m_AccessFlags;
+ pIoResList->m_OwningList = pIoResReqList;
+ }
+
+ return status;
+}
+
+
+_Must_inspect_result_
+__drv_maxIRQL(DISPATCH_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfIoResourceRequirementsListInsertIoResList)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESREQLIST RequirementsList,
+ __in
+ WDFIORESLIST IoResList,
+ __in
+ ULONG Index
+ )
+/*++
+
+Routine Description:
+ Inserts a resource list into a requirements list at a particular index.
+
+Arguments:
+ RequirementsList - list to be modified
+
+ IoResList - resource list to add
+
+ Index - zero based index to insert at
+
+Return Value:
+ NTSTATUS
+
+ --*/
+{
+ return FxIoResourceRequirementsListInsertIoResList(DriverGlobals,
+ RequirementsList,
+ IoResList,
+ Index);
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(DISPATCH_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfIoResourceRequirementsListAppendIoResList)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESREQLIST RequirementsList,
+ __in
+ WDFIORESLIST IoResList
+ )
+/*++
+
+Routine Description:
+ Appends a resource list to a resource requirements list
+
+Arguments:
+ RequirementsList - list to be modified
+
+ IoResList - resource list to append
+
+Return Value:
+ NTSTATUS
+
+ --*/
+
+{
+ return FxIoResourceRequirementsListInsertIoResList(DriverGlobals,
+ RequirementsList,
+ IoResList,
+ WDF_INSERT_AT_END);
+}
+
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+ULONG
+WDFEXPORT(WdfIoResourceRequirementsListGetCount)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESREQLIST RequirementsList
+ )
+/*++
+
+Routine Description:
+ Returns the number of resource lists in the requirements list
+
+
+Arguments:
+ RequirementsList - requirements list whose count will be returned
+
+Return Value:
+ number of elements in the list
+
+ --*/
+
+{
+ FxIoResReqList* pList;
+ ULONG count;
+ KIRQL irql;
+
+ FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
+ RequirementsList,
+ FX_TYPE_IO_RES_REQ_LIST,
+ (PVOID*) &pList);
+
+ pList->Lock(&irql);
+ count = pList->Count();
+ pList->Unlock(irql);
+
+ return count;
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+WDFIORESLIST
+WDFEXPORT(WdfIoResourceRequirementsListGetIoResList)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESREQLIST RequirementsList,
+ __in
+ ULONG Index
+ )
+/*++
+
+Routine Description:
+ Retrieves a resource list from the requirements list at a given index.
+
+Arguments:
+ RequirementsList - list to retrieve the resource list from
+
+ Index - zero based index from which to retrieve the list
+
+Return Value:
+ resource list handle or NULL
+
+ --*/
+{
+ FxIoResReqList* pIoResReqList;
+ FxObject* pObject;
+ KIRQL irql;
+
+ FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
+ RequirementsList,
+ FX_TYPE_IO_RES_REQ_LIST,
+ (PVOID*) &pIoResReqList);
+
+ pIoResReqList->Lock(&irql);
+ pObject = pIoResReqList->GetItem(Index);
+ pIoResReqList->Unlock(irql);
+
+ if (pObject == NULL) {
+ return NULL;
+ }
+ else {
+ return (WDFIORESLIST) pObject->GetObjectHandle();
+ }
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfIoResourceRequirementsListRemove)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESREQLIST RequirementsList,
+ __in
+ ULONG Index
+ )
+/*++
+
+Routine Description:
+ Removes a resource list from the requirements list at a given index
+
+Arguments:
+ RequirementsList - list of resource requirements which will be modified
+
+ Index - zero based index which indictes location in the list to find the
+ resource list
+
+Return Value:
+ None
+
+ --*/
+{
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxIoResReqList* pList;
+
+ FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
+ RequirementsList,
+ FX_TYPE_IO_RES_REQ_LIST,
+ (PVOID*) &pList,
+ &pFxDriverGlobals);
+
+ if (pList->RemoveAndDelete(Index) == FALSE) {
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
+ "WDFIORESLIST %p, could not remove list at index %d (not found), "
+ "list item count is %d", RequirementsList, Index, pList->Count());
+
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ }
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfIoResourceRequirementsListRemoveByIoResList)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESREQLIST RequirementsList,
+ __in
+ WDFIORESLIST IoResList
+ )
+/*++
+
+Routine Description:
+ Removes a resource list from the requirements list based on the resource list's
+ handle
+
+Arguments:
+ RequirementsList - resource requirements list being modified
+
+ IoResList - resource list to be removed
+
+Return Value:
+ None
+
+ --*/
+{
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxCollectionEntry* cur, *end;
+ FxIoResReqList* pList;
+ FxIoResList* pResList;
+ KIRQL irql;
+ BOOLEAN listFound;
+
+ FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
+ RequirementsList,
+ FX_TYPE_IO_RES_REQ_LIST,
+ (PVOID*) &pList,
+ &pFxDriverGlobals);
+
+ if (pList->IsRemoveAllowed() == FALSE) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
+ "WDFIORESREQLIST %p: Removes not allowed",
+ RequirementsList);
+
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ FxObjectHandleGetPtr(pFxDriverGlobals,
+ IoResList,
+ FX_TYPE_IO_RES_LIST,
+ (PVOID*) &pResList);
+
+ pList->Lock(&irql);
+
+ cur = pList->Start();
+ end = pList->End();
+ listFound = FALSE;
+
+ while (cur != end) {
+ if (cur->m_Object == pResList) {
+ pList->MarkChanged();
+
+ pList->RemoveEntry(cur);
+ listFound = TRUE;
+ break;
+ }
+
+ cur = cur->Next();
+ }
+
+ pList->Unlock(irql);
+
+ if (listFound) {
+ pResList->DeleteObject();
+ pResList = NULL;
+ }
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(DISPATCH_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfIoResourceListCreate)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESREQLIST RequirementsList,
+ __in_opt
+ PWDF_OBJECT_ATTRIBUTES Attributes,
+ __out
+ WDFIORESLIST* ResourceList
+ )
+/*++
+
+Routine Description:
+ Creates a resource list.
+
+Arguments:
+ RequirementsList - the resource requirements list that the resource list will
+ be associated with
+
+ Attributes - generic object attributes for the new resource list
+
+ ResourceList - pointer which will receive the new object handle
+
+Return Value:
+ NTSTATUS
+
+ --*/
+{
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxIoResReqList* pIoResReqList;
+ FxIoResList* pIoResList;
+ NTSTATUS status;
+
+ FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
+ RequirementsList,
+ FX_TYPE_IO_RES_REQ_LIST,
+ (PVOID*) &pIoResReqList,
+ &pFxDriverGlobals);
+
+ FxPointerNotNull(pFxDriverGlobals, ResourceList);
+ *ResourceList = NULL;
+
+ status = FxValidateObjectAttributes(pFxDriverGlobals,
+ Attributes,
+ FX_VALIDATE_OPTION_PARENT_NOT_ALLOWED);
+
+ if (!NT_SUCCESS(status)) {
+ return status;
+ }
+
+ pIoResList = new (pFxDriverGlobals, Attributes) FxIoResList(
+ pFxDriverGlobals, pIoResReqList);
+
+ if (pIoResList == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ status = pIoResList->Commit(Attributes,
+ (WDFOBJECT*) ResourceList,
+ pIoResReqList);
+
+ if (!NT_SUCCESS(status)) {
+ pIoResList->DeleteFromFailedCreate();
+ }
+
+ return status;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(DISPATCH_LEVEL)
+NTSTATUS
+FxIoResourceListInsertDescriptor(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESLIST ResourceList,
+ __in
+ PIO_RESOURCE_DESCRIPTOR Descriptor,
+ ULONG Index
+ )
+/*++
+
+Routine Description:
+ Inserts a descriptor into a resource list at a particular index.
+
+Arguments:
+ ResourceList - list to be modified
+
+ Descriptor - descriptor to insert
+
+ Index - zero based index to insert at
+
+Return Value:
+ NTSTATUS
+
+ --*/
+{
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxIoResList* pList;
+ FxResourceIo* pObject;
+ NTSTATUS status;
+
+ FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
+ ResourceList,
+ FX_TYPE_IO_RES_LIST,
+ (PVOID*) &pList,
+ &pFxDriverGlobals);
+
+ FxPointerNotNull(pFxDriverGlobals, Descriptor);
+
+ if (pList->m_OwningList->IsAddAllowed() == FALSE) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
+ "Removes not allowed on WDFIORESLIST %p",
+ ResourceList);
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return STATUS_ACCESS_DENIED;
+ }
+
+ pObject = new(pFxDriverGlobals)
+ FxResourceIo(pFxDriverGlobals, Descriptor);
+
+ if (pObject == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ status = pObject->AssignParentObject(pList);
+ if (!NT_SUCCESS(status)) {
+ pObject->DeleteObject();
+ return status;
+ }
+
+ status = pList->AddAt(Index, pObject);
+
+ //
+ // Mark both this list and its owning list as changed so when it comes
+ // time to evaluate the entire requirements list for changes, we do not
+ // have to iterate over all the resource lists.
+ //
+ if (NT_SUCCESS(status)) {
+ pList->m_OwningList->MarkChanged();
+ }
+
+ return status;
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(DISPATCH_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfIoResourceListInsertDescriptor)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESLIST ResourceList,
+ __in
+ PIO_RESOURCE_DESCRIPTOR Descriptor,
+ __in
+ ULONG Index
+ )
+/*++
+
+Routine Description:
+ Inserts a descriptor into a resource list at a particular index.
+
+Arguments:
+ ResourceList - list to be modified
+
+ Descriptor - descriptor to insert
+
+ Index - zero based index to insert at
+
+Return Value:
+ NTSTATUS
+
+ --*/
+{
+ return FxIoResourceListInsertDescriptor(DriverGlobals,
+ ResourceList,
+ Descriptor,
+ Index);
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(DISPATCH_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfIoResourceListAppendDescriptor)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESLIST ResourceList,
+ __in
+ PIO_RESOURCE_DESCRIPTOR Descriptor
+ )
+/*++
+
+Routine Description:
+ Appends a descriptor to a resource list
+
+Arguments:
+ ResourceList - list to be modified
+
+ Descriptor - item to be appended
+
+Return Value:
+ NTSTATUS
+
+ --*/
+{
+ return FxIoResourceListInsertDescriptor(DriverGlobals,
+ ResourceList,
+ Descriptor,
+ WDF_INSERT_AT_END);
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfIoResourceListUpdateDescriptor)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESLIST ResourceList,
+ __in
+ PIO_RESOURCE_DESCRIPTOR Descriptor,
+ __in
+ ULONG Index
+ )
+/*++
+
+Routine Description:
+ Updates resource requirement in place in the list.
+
+Arguments:
+ ResourceList - list to be modified
+
+ Descriptor - Pointer to descriptor whic contains the updated value
+
+ Index - zero based location in the list to update
+
+Return Value:
+ None
+
+ --*/
+{
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxIoResList* pList;
+ FxResourceIo* pObject;
+ KIRQL irql;
+
+ FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
+ ResourceList,
+ FX_TYPE_IO_RES_LIST,
+ (PVOID*) &pList,
+ &pFxDriverGlobals);
+
+ FxPointerNotNull(pFxDriverGlobals, Descriptor);
+
+ pList->Lock(&irql);
+ pObject = (FxResourceIo*) pList->GetItem(Index);
+ pList->Unlock(irql);
+
+ if (pObject != NULL) {
+ //
+ // We don't check for add or remove access because we don't know what
+ // the update is actually doing (ie widening a range, shortening it, etc).
+ // For this operation we have to trust the driver that it is doing the
+ // right thing at the right time.
+ //
+ RtlCopyMemory(&pObject->m_Descriptor,
+ Descriptor,
+ sizeof(pObject->m_Descriptor));
+
+ //
+ // Mark both this list and its owning list as changed so when it comes
+ // time to evaluate the entire requirements list for changes, we do not
+ // have to iterate over all the resource lists.
+ //
+ pList->MarkChanged();
+ pList->m_OwningList->MarkChanged();
+ }
+ else {
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
+ "WDFIORESREQLIST %p, cannot update item at index %d, item not found,"
+ " list item count is %d", ResourceList, Index, pList->Count());
+
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ }
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+ULONG
+WDFEXPORT(WdfIoResourceListGetCount)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESLIST ResourceList
+ )
+/*++
+
+Routine Description:
+ Returns the number of descriptors in the resource list
+
+Arguments:
+ ResourceList - resource list whose count will be returned
+
+Return Value:
+ number of elements in the list
+
+ --*/
+{
+ FxIoResList* pList;
+ ULONG count;
+ KIRQL irql;
+
+ FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
+ ResourceList,
+ FX_TYPE_IO_RES_LIST,
+ (PVOID*) &pList);
+
+ pList->Lock(&irql);
+ count = pList->Count();
+ pList->Unlock(irql);
+
+ return count;
+}
+
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+PIO_RESOURCE_DESCRIPTOR
+WDFEXPORT(WdfIoResourceListGetDescriptor)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESLIST ResourceList,
+ __in
+ ULONG Index
+ )
+/*++
+
+Routine Description:
+ Retrieves an io resource desciptor for a given index in the resource list
+
+Arguments:
+ ResourceList - list being looked up
+
+ Index - zero based index into the list to find the value of
+
+Return Value:
+ pointer to an io resource descriptor upon success, NULL upon error
+
+ --*/
+
+{
+ FxIoResList* pList;
+ FxResourceIo* pObject;
+ KIRQL irql;
+
+ FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
+ ResourceList,
+ FX_TYPE_IO_RES_LIST,
+ (PVOID*) &pList);
+
+ pList->Lock(&irql);
+ pObject = (FxResourceIo*) pList->GetItem(Index);
+ pList->Unlock(irql);
+
+ if (pObject == NULL) {
+ return NULL;
+ }
+ else {
+ //
+ // Copy the current descriptor to the clone and return it
+ //
+ RtlCopyMemory(&pObject->m_DescriptorClone,
+ &pObject->m_Descriptor,
+ sizeof(pObject->m_Descriptor));
+
+ return &pObject->m_DescriptorClone;
+ }
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfIoResourceListRemove)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESLIST ResourceList,
+ __in
+ ULONG Index
+ )
+/*++
+
+Routine Description:
+ Removes a descriptor in an io resource list
+
+Arguments:
+ ResourceList - resource list to modify
+
+ Index - zero based index into the list in which to remove the descriptor
+
+Return Value:
+ None
+
+ --*/
+{
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxIoResList* pList;
+
+ FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
+ ResourceList,
+ FX_TYPE_IO_RES_LIST,
+ (PVOID*) &pList,
+ &pFxDriverGlobals);
+
+ if (pList->RemoveAndDelete(Index)) {
+ //
+ // Mark this list's owning list as changed so when it comes
+ // time to evaluate the entire requirements list for changes, we do not
+ // have to iterate over all the resource lists.
+ //
+ // RemoveAndDelete marked pList as changed already
+ //
+ pList->m_OwningList->MarkChanged();
+ }
+ else {
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
+ "WDFIORESLIST %p, could not remove item at index %d (not found), "
+ "list item count is %d", ResourceList, Index, pList->Count());
+
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ }
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfIoResourceListRemoveByDescriptor)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFIORESLIST ResourceList,
+ __in
+ PIO_RESOURCE_DESCRIPTOR Descriptor
+ )
+/*++
+
+Routine Description:
+ Removes a descriptor by value in a given io resource list. Equality is
+ determined by RtlCompareMemory.
+
+Arguments:
+ ResourceList - the io resource list to modify
+
+ Descriptor - pointer to a descriptor to remove.
+
+Return Value:
+ None
+
+ --*/
+{
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxCollectionEntry* cur, *end;
+ FxIoResList* pList;
+ FxResourceIo* pObject;
+ KIRQL irql;
+
+ FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
+ ResourceList,
+ FX_TYPE_IO_RES_LIST,
+ (PVOID*) &pList,
+ &pFxDriverGlobals);
+
+ FxPointerNotNull(pFxDriverGlobals, Descriptor);
+
+ if (pList->IsRemoveAllowed() == FALSE) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
+ "Removes not allowed on WDFIORESLIST %p",
+ ResourceList);
+
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ pList->Lock(&irql);
+
+ cur = pList->Start();
+ end = pList->End();
+ pObject = NULL;
+
+ while (cur != end) {
+ pObject = (FxResourceIo*) cur->m_Object;
+
+ if (RtlCompareMemory(&pObject->m_Descriptor,
+ Descriptor,
+ sizeof(*Descriptor)) == sizeof(*Descriptor)) {
+ //
+ // Mark both this list and its owning list as changed so when it
+ // comes time to evaluate the entire requirements list for
+ // changes, we do not have to iterate over all the resource lists.
+ //
+ pList->MarkChanged();
+ pList->m_OwningList->MarkChanged();
+
+ pList->RemoveEntry(cur);
+ break;
+ }
+
+ //
+ // Set to NULL so that we do not delete it if this is the last item in
+ // the list.
+ //
+ pObject = NULL;
+
+ cur = cur->Next();
+ }
+
+ pList->Unlock(irql);
+
+ if (pObject != NULL) {
+ pObject->DeleteObject();
+ }
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(DISPATCH_LEVEL)
+NTSTATUS
+FxCmResourceListInsertDescriptor(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFCMRESLIST List,
+ __in
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
+ __in
+ ULONG Index
+ )
+/*++
+
+Routine Description:
+ Inserts a descriptor into a cm resource list at a particular index.
+
+Arguments:
+ ResourceList - list to be modified
+
+ Descriptor - descriptor to insert
+
+ Index - zero based index to insert at
+
+Return Value:
+ NTSTATUS
+
+ --*/
+{
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxCmResList* pList;
+ FxResourceCm* pObject;
+ NTSTATUS status;
+
+ pFxDriverGlobals = GetFxDriverGlobals(DriverGlobals);
+
+ FxPointerNotNull(pFxDriverGlobals, Descriptor);
+
+ FxObjectHandleGetPtr(pFxDriverGlobals,
+ List,
+ FX_TYPE_CM_RES_LIST,
+ (PVOID*) &pList);
+
+ pObject = new(pFxDriverGlobals) FxResourceCm(pFxDriverGlobals, Descriptor);
+
+ if (pObject == NULL) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ status = pObject->AssignParentObject(pList);
+ if (!NT_SUCCESS(status)) {
+ pObject->DeleteObject();
+ return status;
+ }
+
+ return pList->AddAt(Index, pObject);
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(DISPATCH_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfCmResourceListInsertDescriptor)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFCMRESLIST List,
+ __in
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor,
+ __in
+ ULONG Index
+ )
+/*++
+
+Routine Description:
+ Inserts a descriptor into a cm resource list at a particular index.
+
+Arguments:
+ ResourceList - list to be modified
+
+ Descriptor - descriptor to insert
+
+ Index - zero based index to insert at
+
+Return Value:
+ NTSTATUS
+
+ --*/
+{
+ DDI_ENTRY();
+
+ return FxCmResourceListInsertDescriptor(DriverGlobals,
+ List,
+ Descriptor,
+ Index);
+}
+
+_Must_inspect_result_
+__drv_maxIRQL(DISPATCH_LEVEL)
+NTSTATUS
+WDFEXPORT(WdfCmResourceListAppendDescriptor)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFCMRESLIST List,
+ __in
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
+ )
+/*++
+
+Routine Description:
+ Appends a descriptor to a cm resource list
+
+Arguments:
+ ResourceList - list to be modified
+
+ Descriptor - item to be appended
+
+Return Value:
+ NTSTATUS
+
+ --*/
+{
+ DDI_ENTRY();
+
+ return FxCmResourceListInsertDescriptor(DriverGlobals,
+ List,
+ Descriptor,
+ WDF_INSERT_AT_END);
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+ULONG
+WDFEXPORT(WdfCmResourceListGetCount)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFCMRESLIST List
+ )
+/*++
+
+Routine Description:
+ Returns the number of cm descriptors in the resource list
+
+Arguments:
+ ResourceList - resource list whose count will be returned
+
+Return Value:
+ number of elements in the list
+
+ --*/
+{
+ FxCmResList* pList;
+
+ FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
+ List,
+ FX_TYPE_CM_RES_LIST,
+ (PVOID*) &pList);
+
+ return pList->GetCount();
+}
+
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+PCM_PARTIAL_RESOURCE_DESCRIPTOR
+WDFEXPORT(WdfCmResourceListGetDescriptor)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFCMRESLIST List,
+ __in
+ ULONG Index
+ )
+/*++
+
+Routine Description:
+ Retrieves a cm resource desciptor for a given index in the resource list
+
+Arguments:
+ ResourceList - list being looked up
+
+ Index - zero based index into the list to find the value of
+
+Return Value:
+ pointer to a cm resource descriptor upon success, NULL upon error
+
+ --*/
+{
+ DDI_ENTRY();
+
+ FxCmResList* pList;
+
+ FxObjectHandleGetPtr(GetFxDriverGlobals(DriverGlobals),
+ List,
+ FX_TYPE_CM_RES_LIST,
+ (PVOID*) &pList);
+
+ return pList->GetDescriptor(Index);
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfCmResourceListRemove)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFCMRESLIST List,
+ __in
+ ULONG Index
+ )
+/*++
+
+Routine Description:
+ Removes a descriptor in an cm resource list
+
+Arguments:
+ ResourceList - resource list to modify
+
+ Index - zero based index into the list in which to remove the descriptor
+
+Return Value:
+ None
+
+ --*/
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxCmResList* pList;
+
+ FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
+ List,
+ FX_TYPE_CM_RES_LIST,
+ (PVOID*) &pList,
+ &pFxDriverGlobals);
+
+ if (pList->RemoveAndDelete(Index) == FALSE) {
+ DoTraceLevelMessage(
+ pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
+ "WDFCMRESLIST %p, could not remove list at index %d (not found), "
+ "list item count is %d", List, Index, pList->Count());
+
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ }
+}
+
+__drv_maxIRQL(DISPATCH_LEVEL)
+VOID
+WDFEXPORT(WdfCmResourceListRemoveByDescriptor)(
+ __in
+ PWDF_DRIVER_GLOBALS DriverGlobals,
+ __in
+ WDFCMRESLIST List,
+ __in
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor
+ )
+/*++
+
+Routine Description:
+ Removes a descriptor by value in a given cm resource list. Equality is
+ determined by RtlCompareMemory.
+
+Arguments:
+ ResourceList - the io resource list to modify
+
+ Descriptor - pointer to a descriptor to remove.
+
+Return Value:
+ None
+
+ --*/
+{
+ DDI_ENTRY();
+
+ PFX_DRIVER_GLOBALS pFxDriverGlobals;
+ FxCollectionEntry* cur;
+ FxCollectionEntry* end;
+ FxCmResList* pList;
+ FxResourceCm* pObject;
+ KIRQL irql;
+
+ FxObjectHandleGetPtrAndGlobals(GetFxDriverGlobals(DriverGlobals),
+ List,
+ FX_TYPE_CM_RES_LIST,
+ (PVOID*) &pList,
+ &pFxDriverGlobals);
+
+ FxPointerNotNull(pFxDriverGlobals, Descriptor);
+
+ if (pList->IsRemoveAllowed() == FALSE) {
+ DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP,
+ "Removes not allowed on WDFCMRESLIST %p", List);
+
+ FxVerifierDbgBreakPoint(pFxDriverGlobals);
+ return;
+ }
+
+ pList->Lock(&irql);
+
+ cur = pList->Start();
+ end = pList->End();
+ pObject = NULL;
+
+ while (cur != end) {
+ pObject = (FxResourceCm*) cur->m_Object;
+
+ if (RtlCompareMemory(&pObject->m_Descriptor,
+ Descriptor,
+ sizeof(*Descriptor)) == sizeof(*Descriptor)) {
+ pList->MarkChanged();
+
+ pList->RemoveEntry(cur);
+ break;
+ }
+
+ //
+ // Set to NULL so that we do not delete it if this is the last item in
+ // the list.
+ //
+ pObject = NULL;
+
+ cur = cur->Next();
+ }
+
+ pList->Unlock(irql);
+
+ if (pObject != NULL) {
+ pObject->DeleteObject();
+ pObject = NULL;
+ }
+}
+
+} // extern "C"