Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740/*++
Copyright (c) Microsoft Corporation
Module Name:
FxResourceCollection.cpp
Abstract:
This module implements a base object for derived collection classes and the derived collection classes.
Author:
Environment:
Both kernel and user mode
Revision History:
--*/
#include "fxsupportpch.hpp"
extern "C" {#if defined(EVENT_TRACING)#include "FxResourceCollection.tmh"#endif}
BOOLEANFxResourceCollection::RemoveAndDelete( __in ULONG Index )/*++
Routine Description: Removes an entry from the collection and then deletes it if found. The caller must have removal permissions to perform this action.
Arguments: Index - zero based index into the collection at which to perform the removal
Return Value: TRUE if the item was found and deleted, FALSE otherwise
--*/{ FxObject* pObject; FxCollectionEntry* pEntry; KIRQL irql;
if (IsRemoveAllowed() == FALSE) { DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP, "Removes not allowed on handle %p, remove at index %d" "failed", GetObjectHandle(), Index);
FxVerifierDbgBreakPoint(GetDriverGlobals()); return FALSE; }
pObject = NULL;
Lock(&irql);
pEntry = FindEntry(Index); if (pEntry != NULL) {
// // Mark the list as changed so when we go to create a WDM resource list we // know if a new list is needed. // MarkChanged();
pObject = pEntry->m_Object;
// // Remove the entry // RemoveEntry(pEntry); } Unlock(irql);
if (pObject != NULL) { // // Delete the object since we created it // pObject->DeleteObject(); pObject = NULL;
return TRUE; } else { return FALSE; }}
_Must_inspect_result_NTSTATUSFxResourceCollection::AddAt( __in ULONG Index, __in FxObject* Object )/*++
Routine Description: Adds an object into the collection at the specified index.
Arguments: Index - zero baesd index in which to insert into the list. WDF_INSERT_AT_END is a special value which indicates that the insertion is an append.
Object - object to add
Return Value: NTSTATUS
--*/{ FxCollectionEntry *pNew; PLIST_ENTRY ple; NTSTATUS status; KIRQL irql;
if (IsAddAllowed() == FALSE) { DoTraceLevelMessage(GetDriverGlobals(), TRACE_LEVEL_ERROR, TRACINGPNP, "Adds not allowed on handle %p, add at index %d" "failed", GetObjectHandle(), Index);
FxVerifierDbgBreakPoint(GetDriverGlobals());
return STATUS_ACCESS_DENIED; }
Lock(&irql);
ple = NULL; status = STATUS_SUCCESS;
pNew = AllocateEntry(GetDriverGlobals());
if (pNew != NULL) { // // Inserting at the current count (i.e. one past the end) is the same // as append. // if (Index == WDF_INSERT_AT_END || Index == Count()) { ple = &m_ListHead; } else { FxCollectionEntry* cur, *end; ULONG i;
for (cur = Start(), end = End(), i = 0; cur != end; cur = cur->Next(), i++) { if (i == Index) { ple = &cur->m_ListEntry; break; } }
if (ple == NULL) { delete pNew; status = STATUS_ARRAY_BOUNDS_EXCEEDED; } } } else { status = STATUS_INSUFFICIENT_RESOURCES; }
if (NT_SUCCESS(status)) { PLIST_ENTRY blink;
// ple now points to the list entry which we will insert our node // *before*
blink = ple->Blink;
// Link the previous with the new entry blink->Flink = &pNew->m_ListEntry; pNew->m_ListEntry.Blink = blink;
// Link the current with the new entry pNew->m_ListEntry.Flink = ple; ple->Blink = &pNew->m_ListEntry;
AddEntry(pNew, Object);
// // Mark the list as changed so when we go to create a WDM resource list // we know if a new list is needed. // MarkChanged(); }
Unlock(irql);
if (!NT_SUCCESS(status)) { Object->DeleteFromFailedCreate(); }
return status;}
_Must_inspect_result_NTSTATUSFxIoResList::BuildFromWdmList( __deref_in PIO_RESOURCE_LIST* WdmResourceList )/*++
Routine Description: Builds up the collection with FxResourceIo objects based on the passed in WDM io resource list
Arguments: WdmResourceList - list which specifies the io resource objects to create
Return Value: NTSTATUS
--*/{ PIO_RESOURCE_DESCRIPTOR pWdmDescriptor; ULONG i, count; NTSTATUS status;
pWdmDescriptor = &(*WdmResourceList)->Descriptors[0]; count = (*WdmResourceList)->Count; status = STATUS_SUCCESS;
for (i = 0; i < count; i++) { // // Now create a new resource object for each resource // in our list. // FxResourceIo *pResource;
pResource = new(GetDriverGlobals()) FxResourceIo(GetDriverGlobals(), pWdmDescriptor);
if (pResource == NULL) { // // We failed, clean up, and exit. Since we are only // keeping references on the master collection, if // we free this, everything else will go away too. // status = STATUS_INSUFFICIENT_RESOURCES; }
if (NT_SUCCESS(status)) { status = pResource->AssignParentObject(this);
// // See notes in previous AssignParentObject as to why // we are asserting. // ASSERT(NT_SUCCESS(status)); UNREFERENCED_PARAMETER(status);
status = Add(pResource) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; }
if (!NT_SUCCESS(status)) { break; }
pWdmDescriptor++; }
if (NT_SUCCESS(status)) { status = m_OwningList->Add(this) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; }
if (NT_SUCCESS(status)) { *WdmResourceList = (PIO_RESOURCE_LIST) pWdmDescriptor; }
return status;}
_Must_inspect_result_NTSTATUSFxCmResList::BuildFromWdmList( __in PCM_RESOURCE_LIST WdmResourceList, __in UCHAR AccessFlags )/*++
Routine Description: Builds up the collection with FxResourceCm objects based on the passed in WDM io resource list.
Arguments: WdmResourceList - list which specifies the io resource objects to create
AccessFlags - permissions to be associated with the list
Return Value: NTSTATUS
--*/{ NTSTATUS status;
// // Predispose to success // status = STATUS_SUCCESS;
Clear();
m_AccessFlags = AccessFlags;
if (WdmResourceList != NULL) { PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor; ULONG count, i;
// // We only expect to see one full resource descriptor. // ASSERT(WdmResourceList->Count == 1);
count = WdmResourceList->List[0].PartialResourceList.Count; pDescriptor = WdmResourceList->List[0].PartialResourceList.PartialDescriptors;
for(i = 0; i < count; i++, pDescriptor++) { FxResourceCm *pResource;
pResource = new(GetDriverGlobals()) FxResourceCm(GetDriverGlobals(), pDescriptor);
if (pResource == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; }
if (NT_SUCCESS(status)) { status = pResource->AssignParentObject(this);
// // Since we control our own lifetime here, the assign should // always work. // ASSERT(NT_SUCCESS(status));
status = Add(pResource) ? STATUS_SUCCESS : STATUS_INSUFFICIENT_RESOURCES; }
if (!NT_SUCCESS(status)) { Clear(); break; } } }
return status;}
_Must_inspect_result_PCM_RESOURCE_LISTFxCmResList::CreateWdmList( __in __drv_strictTypeMatch(__drv_typeExpr) POOL_TYPE PoolType )/*++
Routine Description: Allocates and initializes a WDM CM resource list based off of the current contents of this collection.
Arguments: PoolType - the pool type from which to allocate the resource list
Return Value: a new resource list upon success, NULL upon failure
--*/{ PCM_RESOURCE_LIST pWdmResourceList; ULONG size; PFX_DRIVER_GLOBALS pFxDriverGlobals;
pWdmResourceList = NULL; pFxDriverGlobals = GetDriverGlobals();
if (Count()) { // // NOTE: This function assumes all resources are on the same bus // and therefore there is only one FULL_RESOURCE_DESCRIPTOR. // size = sizeof(CM_RESOURCE_LIST) + (sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) * (Count() - 1));
pWdmResourceList = (PCM_RESOURCE_LIST) MxMemory::MxAllocatePoolWithTag(PoolType, size, pFxDriverGlobals->Tag);
if (pWdmResourceList != NULL) { PCM_PARTIAL_RESOURCE_DESCRIPTOR pDescriptor; FxCollectionEntry *cur, *end;
RtlZeroMemory(pWdmResourceList, size);
pWdmResourceList->Count = 1; // We only return one full descriptor
pWdmResourceList->List[0].PartialResourceList.Version = 1; pWdmResourceList->List[0].PartialResourceList.Revision = 1; pWdmResourceList->List[0].PartialResourceList.Count = Count();
pDescriptor = pWdmResourceList->List[0].PartialResourceList.PartialDescriptors;
end = End(); for (cur = Start(); cur != end; cur = cur->Next()) { FxResourceCm *pResource;
pResource = (FxResourceCm*) cur->m_Object;
RtlCopyMemory(pDescriptor, &pResource->m_Descriptor, sizeof(pResource->m_Descriptor)); pDescriptor++; } } }
return pWdmResourceList;}
ULONGFxCmResList::GetCount( VOID ){ ULONG count; KIRQL irql;
Lock(&irql); count = Count(); Unlock(irql);
return count;}
PCM_PARTIAL_RESOURCE_DESCRIPTORFxCmResList::GetDescriptor( __in ULONG Index ){ FxResourceCm* pObject; KIRQL irql;
Lock(&irql); pObject = (FxResourceCm*) GetItem(Index); 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; }}
_Must_inspect_result_FxIoResReqList*FxIoResReqList::_CreateFromWdmList( __in PFX_DRIVER_GLOBALS FxDriverGlobals, __in PIO_RESOURCE_REQUIREMENTS_LIST WdmRequirementsList, __in UCHAR AccessFlags )/*++
Routine Description: Allocates and populates an FxIoResReqList based on the WDM resource requirements list.
Arguments: WdmRequirementsList - a list of IO_RESOURCE_LISTs which will indicate how to fill in the returned collection object
AccessFlags - permissions to associate with the newly created object
Return Value: a new object upon success, NULL upon failure
--*/
{ FxIoResReqList* pIoResReqList; ULONG i;
pIoResReqList = new(FxDriverGlobals, WDF_NO_OBJECT_ATTRIBUTES) FxIoResReqList(FxDriverGlobals, AccessFlags);
if (pIoResReqList != NULL) { PIO_RESOURCE_LIST pWdmResourceList; NTSTATUS status;
if (WdmRequirementsList == NULL) { return pIoResReqList; }
status = STATUS_SUCCESS; pWdmResourceList = &WdmRequirementsList->List[0];
pIoResReqList->m_InterfaceType = WdmRequirementsList->InterfaceType; pIoResReqList->m_SlotNumber = WdmRequirementsList->SlotNumber;
for (i = 0; i < WdmRequirementsList->AlternativeLists; i++) { FxIoResList *pResList;
pResList = new(FxDriverGlobals, WDF_NO_OBJECT_ATTRIBUTES) FxIoResList(FxDriverGlobals, pIoResReqList);
if (pResList != NULL) { status = pResList->AssignParentObject(pIoResReqList);
// // Since we control our own lifetime, assigning the parent should // never fail. // ASSERT(NT_SUCCESS(status));
status = pResList->BuildFromWdmList(&pWdmResourceList); } else { // // We failed to allocate a child collection. Clean up // and break out of the loop. // status = STATUS_INSUFFICIENT_RESOURCES; }
if (!NT_SUCCESS(status)) { break; } }
if (!NT_SUCCESS(status)) { // // Cleanup and return a NULL object // pIoResReqList->DeleteObject(); pIoResReqList = NULL; } }
return pIoResReqList;}
_Must_inspect_result_PIO_RESOURCE_REQUIREMENTS_LISTFxIoResReqList::CreateWdmList( VOID )/*++
Routine Description: Creates a WDM io resource requirements list based off of the current contents of the collection
Arguments: None
Return Value: new WDM io resource requirements list allocated out of paged pool upon success, NULL upon failure or an empty list
--*/{ PIO_RESOURCE_REQUIREMENTS_LIST pRequirementsList; FxCollectionEntry *cur, *end; NTSTATUS status; ULONG totalDescriptors; ULONG size; ULONG count; ULONG tmp; PFX_DRIVER_GLOBALS pFxDriverGlobals;
totalDescriptors = 0; pRequirementsList = NULL;
count = Count(); pFxDriverGlobals = GetDriverGlobals();
if (count > 0) { // // The collection object should contain a set of child collections // with each of the various requirement lists. Use the number of // these collections to determine the size of our requirements // list. // end = End(); for (cur = Start(); cur != end; cur = cur->Next()) { status = RtlULongAdd(totalDescriptors, ((FxIoResList *) cur->m_Object)->Count(), &totalDescriptors);
if (!NT_SUCCESS(status)) { goto Overflow; } }
// // We now have enough information to determine how much memory we // need to allocate for our requirements list. // // size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + // (sizeof(IO_RESOURCE_LIST) * (count - 1)) + // (sizeof(IO_RESOURCE_DESCRIPTOR) * totalDescriptors) - // (sizeof(IO_RESOURCE_DESCRIPTOR) * count); // // sizeof(IO_RESOURCE_DESCRIPTOR) * count is subtracted off because // each IO_RESOURCE_LIST has an embedded IO_RESOURCE_DESCRIPTOR in it // and we don't want to overallocated. //
// // To handle overflow each mathematical operation is split out into an // overflow safe call. // size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST);
// sizeof(IO_RESOURCE_LIST) * (count - 1) status = RtlULongMult(sizeof(IO_RESOURCE_LIST), count - 1, &tmp); if (!NT_SUCCESS(status)) { goto Overflow; }
status = RtlULongAdd(size, tmp, &size); if (!NT_SUCCESS(status)) { goto Overflow; }
// (sizeof(IO_RESOURCE_DESCRIPTOR) * totalDescriptors) status = RtlULongMult(sizeof(IO_RESOURCE_DESCRIPTOR), totalDescriptors, &tmp); if (!NT_SUCCESS(status)) { goto Overflow; }
status = RtlULongAdd(size, tmp, &size); if (!NT_SUCCESS(status)) { goto Overflow; }
// - sizeof(IO_RESOURCE_DESCRIPTOR) * Count() (note the subtraction!) status = RtlULongMult(sizeof(IO_RESOURCE_DESCRIPTOR), count, &tmp); if (!NT_SUCCESS(status)) { goto Overflow; }
// Sub, not Add! status = RtlULongSub(size, tmp, &size); if (!NT_SUCCESS(status)) { goto Overflow; }
pRequirementsList = (PIO_RESOURCE_REQUIREMENTS_LIST) MxMemory::MxAllocatePoolWithTag(PagedPool, size, pFxDriverGlobals->Tag);
if (pRequirementsList != NULL) { PIO_RESOURCE_LIST pList; FxResourceIo *pResource;
pList = pRequirementsList->List;
// // Start by zero initializing our structure // RtlZeroMemory(pRequirementsList, size);
// // InterfaceType and BusNumber are unused for WDM, but InterfaceType // is used by the arbiters. // pRequirementsList->InterfaceType = m_InterfaceType;
pRequirementsList->SlotNumber = m_SlotNumber;
// // Now populate the requirements list with the resources from // our collections. // pRequirementsList->ListSize = size; pRequirementsList->AlternativeLists = Count();
end = End(); for (cur = Start(); cur != end; cur = cur->Next()) { FxIoResList* pIoResList; PIO_RESOURCE_DESCRIPTOR pDescriptor; FxCollectionEntry *pIoResCur, *pIoResEnd;
pIoResList = (FxIoResList*) cur->m_Object;
pList->Version = 1; pList->Revision = 1; pList->Count = pIoResList->Count();
pDescriptor = pList->Descriptors;
pIoResEnd = pIoResList->End(); for (pIoResCur = pIoResList->Start(); pIoResCur != pIoResEnd; pIoResCur = pIoResCur->Next()) {
pResource = (FxResourceIo *) pIoResCur->m_Object; RtlCopyMemory(pDescriptor, &pResource->m_Descriptor, sizeof(pResource->m_Descriptor)); pDescriptor++; }
pList = (PIO_RESOURCE_LIST) pDescriptor; } } }
return pRequirementsList;
Overflow: DoTraceLevelMessage(pFxDriverGlobals, TRACE_LEVEL_ERROR, TRACINGPNP, "Integer overflow occured when computing size of " "IO_RESOURCE_REQUIREMENTS_LIST");
return NULL;}