mirror of
https://github.com/reactos/reactos.git
synced 2024-11-20 06:15:26 +00:00
1f377076d7
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
285 lines
4.9 KiB
C++
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);
|
|
}
|
|
}
|
|
|