reactos/sdk/lib/drivers/wdf/shared/support/fxcollection.cpp
Victor Perevertkin 1f377076d7
[WDF] Fix KMDF so it can compile with ReactOS SDK
Not all files are included, but these are necessary to compile cdrom driver.
So far it can only be statically linked with drivers, a proper
implementation requires wdfldr helper driver
2020-11-03 00:06:27 +03:00

285 lines
4.9 KiB
C++

/*++
Copyright (c) Microsoft Corporation
Module Name:
FxCollection.cpp
Abstract:
This module implements a simple collection class to operate on
objects derived from FxObject.
Author:
Environment:
Both kernel and user mode
Revision History:
--*/
#include "fxsupportpch.hpp"
FxCollectionInternal::FxCollectionInternal(
VOID
)
{
m_Count = 0;
InitializeListHead(&m_ListHead);
}
FxCollectionInternal::~FxCollectionInternal(
VOID
)
{
Clear();
}
VOID
FxCollectionInternal::Clear(
VOID
)
{
while (!IsListEmpty(&m_ListHead)) {
Remove(0);
}
}
ULONG
FxCollectionInternal::Count(
VOID
)
{
return m_Count;
}
BOOLEAN
FxCollectionInternal::Add(
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
__in FxObject *Item
)
{
FxCollectionEntry *pNode;
pNode = AllocateEntry(FxDriverGlobals);
if (pNode != NULL) {
InsertTailList(&m_ListHead, &pNode->m_ListEntry);
AddEntry(pNode, Item);
}
return pNode != NULL;
}
_Must_inspect_result_
FxCollectionEntry*
FxCollectionInternal::FindEntry(
__in ULONG Index
)
{
PLIST_ENTRY ple;
ULONG i;
if (Index >= m_Count) {
return NULL;
}
for (i = 0, ple = m_ListHead.Flink;
ple != &m_ListHead;
ple = ple->Flink, i++) {
if (i != Index) {
continue;
}
return CONTAINING_RECORD(ple, FxCollectionEntry, m_ListEntry);
}
return NULL;
}
_Must_inspect_result_
FxCollectionEntry*
FxCollectionInternal::FindEntryByObject(
__in FxObject* Object
)
{
PLIST_ENTRY ple;
for (ple = m_ListHead.Flink; ple != &m_ListHead; ple = ple->Flink) {
FxCollectionEntry* pNode;
pNode = CONTAINING_RECORD(ple, FxCollectionEntry, m_ListEntry);
if (pNode->m_Object == Object) {
return pNode;
}
}
return NULL;
}
NTSTATUS
FxCollectionInternal::Remove(
__in ULONG Index
)
{
FxCollectionEntry *pNode;
pNode = FindEntry(Index);
if (pNode != NULL) {
return RemoveEntry(pNode);
}
else {
return STATUS_NOT_FOUND;
}
}
_Must_inspect_result_
NTSTATUS
FxCollectionInternal::RemoveItem(
__in FxObject* Item
)
{
FxCollectionEntry* pNode;
pNode = FindEntryByObject(Item);
if (pNode != NULL) {
return RemoveEntry(pNode);
}
return STATUS_NOT_FOUND;
}
VOID
FxCollectionInternal::CleanupEntry(
__in FxCollectionEntry* Entry
)
{
RemoveEntryList(&Entry->m_ListEntry);
delete Entry;
m_Count--;
}
NTSTATUS
FxCollectionInternal::RemoveEntry(
__in FxCollectionEntry* Entry
)
{
CleanupEntryObject(Entry->m_Object);
CleanupEntry(Entry);
return STATUS_SUCCESS;
}
_Must_inspect_result_
FxObject*
FxCollectionInternal::GetItem(
__in ULONG Index
)
{
FxCollectionEntry* pNode;
pNode = FindEntry(Index);
if (pNode != NULL) {
return pNode->m_Object;
}
else {
return NULL;
}
}
_Must_inspect_result_
FxObject*
FxCollectionInternal::GetFirstItem(
VOID
)
{
if (IsListEmpty(&m_ListHead)) {
return NULL;
}
else {
return CONTAINING_RECORD(m_ListHead.Flink,
FxCollectionEntry,
m_ListEntry)->m_Object;
}
}
_Must_inspect_result_
FxObject*
FxCollectionInternal::GetLastItem(
VOID
)
{
if (IsListEmpty(&m_ListHead)) {
return NULL;
}
else {
return CONTAINING_RECORD(m_ListHead.Blink,
FxCollectionEntry,
m_ListEntry)->m_Object;
}
}
FxCollection::FxCollection(
__in PFX_DRIVER_GLOBALS FxDriverGlobals
) :
FxNonPagedObject(FX_TYPE_COLLECTION, sizeof(FxCollection), FxDriverGlobals)
{
}
FxCollection::FxCollection(
__in PFX_DRIVER_GLOBALS FxDriverGlobals,
__in WDFTYPE Type,
__in USHORT Size
) : FxNonPagedObject(Type, Size, FxDriverGlobals)
{
}
FxCollection::~FxCollection(
VOID
)
{
Clear();
}
VOID
FxCollection::StealCollection(
__in FxCollection* Collection
)
{
PLIST_ENTRY ple;
m_Count = Collection->m_Count;
Collection->m_Count = 0;
while (!IsListEmpty(&Collection->m_ListHead)) {
FxCollectionEntry* pEntry;
ple = RemoveHeadList(&Collection->m_ListHead);
pEntry = CONTAINING_RECORD(ple, FxCollectionEntry, m_ListEntry);
//
// When we are tracking reference tags, the tag associated with the
// reference matters. When we added the object to Collection, we used
// that pointer as the tag. We must remove that tag and readd the
// reference using the this value as a tag.
//
// Obviously, order is important here. Add the reference first so that
// we know the relese will make the object go away.
//
pEntry->m_Object->ADDREF(this);
pEntry->m_Object->RELEASE(Collection);
InsertTailList(&m_ListHead, ple);
}
}