Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

637 lines
13 KiB

//---------------------------------------------------------------------------
//
// Module: clist.cpp
//
// Description:
//
//
//@@BEGIN_MSINTERNAL
// Development Team:
// Mike McLaughlin
//
// History: Date Author Comment
//
// To Do: Date Author Comment
//
//@@END_MSINTERNAL
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
// PURPOSE.
//
// Copyright (c) 1996-1999 Microsoft Corporation. All Rights Reserved.
//
//---------------------------------------------------------------------------
#include "common.h"
//---------------------------------------------------------------------------
// CListSingle Class
//---------------------------------------------------------------------------
ENUMFUNC
CListSingle::EnumerateList(
IN ENUMFUNC (CListSingleItem::*pfn)(
)
)
{
NTSTATUS Status = STATUS_CONTINUE;
PCLIST_SINGLE_ITEM plsi;
Assert(this);
FOR_EACH_CLIST_ITEM_DELETE(this, plsi, CLIST_SINGLE_ITEM) {
Status = (plsi->*pfn)();
if(Status != STATUS_CONTINUE) {
goto exit;
}
} END_EACH_CLIST_ITEM
exit:
return(Status);
}
ENUMFUNC
CListSingle::EnumerateList(
IN ENUMFUNC (CListSingleItem::*pfn)(
PVOID pReference
),
PVOID pReference
)
{
NTSTATUS Status = STATUS_CONTINUE;
PCLIST_SINGLE_ITEM plsi;
Assert(this);
FOR_EACH_CLIST_ITEM_DELETE(this, plsi, CLIST_SINGLE_ITEM) {
Status = (plsi->*pfn)(pReference);
if(Status != STATUS_CONTINUE) {
goto exit;
}
} END_EACH_CLIST_ITEM
exit:
return(Status);
}
PCLIST_SINGLE_ITEM *
CListSingle::GetListEnd(
)
{
PCLIST_SINGLE_ITEM *pplsi;
for(pplsi = &m_plsiHead;
!IsListEnd(*pplsi);
pplsi = &(*pplsi)->m_plsiNext) {
Assert(*pplsi);
}
return(pplsi);
}
void
CListSingle::ReverseList(
)
{
PCLIST_SINGLE_ITEM plsi = m_plsiHead;
PCLIST_SINGLE_ITEM plsiNext;
PCLIST_SINGLE_ITEM plsiTemp;
if (NULL != plsi) {
plsiNext = plsi->m_plsiNext;
plsi->m_plsiNext = NULL;
while (NULL != plsiNext) {
plsiTemp = plsiNext->m_plsiNext;
plsiNext->m_plsiNext = plsi;
plsi = plsiNext;
plsiNext = plsiTemp;
}
m_plsiHead = plsi;
}
}
//---------------------------------------------------------------------------
// CListSingleItem Class
//---------------------------------------------------------------------------
VOID
CListSingleItem::RemoveList(
IN PCLIST_SINGLE pls
)
{
PCLIST_SINGLE_ITEM *pplsi;
Assert(pls);
Assert(this);
for(pplsi = &pls->m_plsiHead;
!pls->IsListEnd(*pplsi);
pplsi = &(*pplsi)->m_plsiNext) {
Assert(*pplsi);
if(*pplsi == this) {
break;
}
}
*pplsi = m_plsiNext;
}
//---------------------------------------------------------------------------
// CListDouble Class
//---------------------------------------------------------------------------
ULONG
CListDouble::CountList(
)
{
PCLIST_DOUBLE_ITEM pldi;
ULONG c = 0;
Assert(this);
FOR_EACH_CLIST_ITEM(this, pldi) {
Assert(pldi);
c++;
} END_EACH_CLIST_ITEM
return(c);
}
ENUMFUNC
CListDouble::EnumerateList(
IN ENUMFUNC (CListDoubleItem::*pfn)(
)
)
{
NTSTATUS Status = STATUS_CONTINUE;
PCLIST_DOUBLE_ITEM plbi;
Assert(this);
FOR_EACH_CLIST_ITEM_DELETE(this, plbi, CLIST_DOUBLE_ITEM) {
Status = (plbi->*pfn)();
if(Status != STATUS_CONTINUE) {
goto exit;
}
} END_EACH_CLIST_ITEM
exit:
return(Status);
}
ENUMFUNC
CListDouble::EnumerateList(
IN ENUMFUNC (CListDoubleItem::*pfn)(
PVOID pReference
),
PVOID pReference
)
{
NTSTATUS Status = STATUS_CONTINUE;
PCLIST_DOUBLE_ITEM plbi;
Assert(this);
FOR_EACH_CLIST_ITEM_DELETE(this, plbi, CLIST_DOUBLE_ITEM) {
Status = (plbi->*pfn)(pReference);
if(Status != STATUS_CONTINUE) {
goto exit;
}
} END_EACH_CLIST_ITEM
exit:
return(Status);
}
//---------------------------------------------------------------------------
// CListData Class
//---------------------------------------------------------------------------
VOID
CListData::DestroyList()
{
PCLIST_DATA_DATA pldd;
Assert(this);
FOR_EACH_CLIST_ITEM_DELETE(this, pldd, CLIST_DATA_DATA) {
delete pldd;
} END_EACH_CLIST_ITEM
CListSingle::DestroyList();
}
ULONG
CListData::CountList(
)
{
PCLIST_DATA_DATA pldd;
ULONG c = 0;
Assert(this);
FOR_EACH_CLIST_ITEM(this, pldd) {
Assert(pldd);
c++;
} END_EACH_CLIST_ITEM
return(c);
}
ENUMFUNC
CListData::EnumerateList(
IN ENUMFUNC (CListDataItem::*pfn)(
)
)
{
NTSTATUS Status = STATUS_CONTINUE;
PCLIST_DATA_DATA pldd;
Assert(this);
FOR_EACH_CLIST_ITEM_DELETE(this, pldd, CLIST_DATA_DATA) {
Status = (GetListData(pldd)->*pfn)();
if(Status != STATUS_CONTINUE) {
goto exit;
}
} END_EACH_CLIST_ITEM
exit:
return(Status);
}
ENUMFUNC
CListData::EnumerateList(
IN ENUMFUNC (CListDataItem::*pfn)(
PVOID pReference
),
PVOID pReference
)
{
NTSTATUS Status = STATUS_CONTINUE;
PCLIST_DATA_DATA pldd;
Assert(this);
FOR_EACH_CLIST_ITEM_DELETE(this, pldd, CLIST_DATA_DATA) {
Status = (GetListData(pldd)->*pfn)(pReference);
if(Status != STATUS_CONTINUE) {
goto exit;
}
} END_EACH_CLIST_ITEM
exit:
return(Status);
}
NTSTATUS
CListData::CreateUniqueList(
OUT PCLIST_DATA pldOut,
IN PVOID (*GetFunction)(
IN PVOID pData
),
IN BOOL (*CompareFunction)(
IN PVOID pIn,
IN PVOID pOut
)
)
{
NTSTATUS Status = STATUS_SUCCESS;
PCLIST_DATA_DATA plddIn, plddOut;
PVOID pIn, pOut;
BOOL fFoundMatch;
FOR_EACH_CLIST_ITEM(this, plddIn) {
pIn = (*GetFunction)((PVOID)GetListData(plddIn));
if(pIn == NULL) {
continue;
}
AssertAligned(pIn);
fFoundMatch = FALSE;
FOR_EACH_CLIST_ITEM(pldOut, plddOut) {
pOut = (PVOID)pldOut->GetListData(plddOut);
if((*CompareFunction)(pIn, pOut)) {
fFoundMatch = TRUE;
break;
}
} END_EACH_CLIST_ITEM
if(!fFoundMatch) {
Status = pldOut->AddListEnd(pIn);
if(!NT_SUCCESS(Status)) {
Trap();
goto exit;
}
}
} END_EACH_CLIST_ITEM
exit:
if(!NT_SUCCESS(Status)) {
pldOut->DestroyList();
}
return(Status);
}
BOOL
CListData::CheckDupList(
PVOID p
)
{
PCLIST_DATA_DATA pldd;
Assert(this);
FOR_EACH_CLIST_ITEM(this, pldd) {
if(GetListData(pldd) == p) {
return(TRUE);
}
} END_EACH_CLIST_ITEM
return(FALSE);
}
NTSTATUS
CListData::AddList(
PVOID p
)
{
Assert(this);
if(CheckDupList(p)) {
return(STATUS_SUCCESS);
}
return(AddListDup(p));
}
NTSTATUS
CListData::AddListDup(
PVOID p
)
{
Assert(this);
PCLIST_DATA_DATA pldd = new CLIST_DATA_DATA(p);
if(pldd == NULL) {
return(STATUS_INSUFFICIENT_RESOURCES);
}
pldd->AddList(this);
return(STATUS_SUCCESS);
}
NTSTATUS
CListData::AddListEnd(
PVOID p
)
{
ASSERT(!CheckDupList(p));
PCLIST_DATA_DATA pldd = new CLIST_DATA_DATA(p);
if(pldd == NULL) {
return(STATUS_INSUFFICIENT_RESOURCES);
}
*(GetListEnd()) = pldd;
return(STATUS_SUCCESS);
}
NTSTATUS
CListData::AddListOrdered(
PVOID p,
LONG lFieldOffset
)
{
PCLIST_DATA_DATA pldd, *ppldd;
ULONG ulOrder;
ASSERT(!CheckDupList(p));
ulOrder = *((PULONG)(((PCHAR)p) + lFieldOffset));
pldd = new CLIST_DATA_DATA(p);
if(pldd == NULL) {
return(STATUS_INSUFFICIENT_RESOURCES);
}
for(ppldd = (PCLIST_DATA_DATA *)&m_plsiHead;
!IsListEnd(*ppldd);
ppldd = (PCLIST_DATA_DATA *)&(*ppldd)->m_plsiNext) {
Assert(*ppldd);
if(ulOrder < *((PULONG)(((PCHAR)GetListData(*ppldd)) + lFieldOffset))) {
break;
}
}
pldd->m_plsiNext = *ppldd;
*ppldd = pldd;
return(STATUS_SUCCESS);
}
VOID
CListData::RemoveList(
PVOID p
)
{
PCLIST_DATA_DATA pldd;
Assert(this);
FOR_EACH_CLIST_ITEM_DELETE(this, pldd, CLIST_DATA_DATA) {
if(GetListData(pldd) == p) {
pldd->RemoveList(this);
delete pldd;
}
} END_EACH_CLIST_ITEM
}
VOID
CListData::JoinList(
PCLIST_DATA pld
)
{
*GetListEnd() = pld->GetListFirst();
pld->CListSingle::DestroyList();
}
//---------------------------------------------------------------------------
// CListMulti Class
//---------------------------------------------------------------------------
VOID
CListMulti::DestroyList(
)
{
PCLIST_MULTI_DATA plmd;
Assert(this);
FOR_EACH_CLIST_ITEM_DELETE(this, plmd, CLIST_MULTI_DATA) {
delete plmd;
} END_EACH_CLIST_ITEM
CListDouble::DestroyList();
}
ENUMFUNC
CListMulti::EnumerateList(
ENUMFUNC (CListMultiItem::*pfn)(
)
)
{
NTSTATUS Status = STATUS_CONTINUE;
PCLIST_MULTI_DATA plmd;
Assert(this);
FOR_EACH_CLIST_ITEM_DELETE(this, plmd, CLIST_MULTI_DATA) {
Status = (GetListData(plmd)->*pfn)();
if(Status != STATUS_CONTINUE) {
goto exit;
}
} END_EACH_CLIST_ITEM
exit:
return(Status);
}
ENUMFUNC
CListMulti::EnumerateList(
ENUMFUNC (CListMultiItem::*pfn)(
PVOID pReference
),
PVOID pReference
)
{
NTSTATUS Status = STATUS_CONTINUE;
PCLIST_MULTI_DATA plmd;
Assert(this);
FOR_EACH_CLIST_ITEM_DELETE(this, plmd, CLIST_MULTI_DATA) {
Status = (GetListData(plmd)->*pfn)(pReference);
if(Status != STATUS_CONTINUE) {
goto exit;
}
} END_EACH_CLIST_ITEM
exit:
return(Status);
}
BOOL
CListMulti::CheckDupList(
PVOID p
)
{
PCLIST_MULTI_DATA plmd;
FOR_EACH_CLIST_ITEM(this, plmd) {
if(GetListData(plmd) == p) {
return(TRUE);
}
} END_EACH_CLIST_ITEM
return(FALSE);
}
NTSTATUS
CListMulti::AddList(
PVOID p,
CListMultiItem *plmi
)
{
Assert(this);
Assert(plmi);
if(CheckDupList(p)) {
return(STATUS_SUCCESS);
}
PCLIST_MULTI_DATA plmd = new CLIST_MULTI_DATA(p);
if(plmd == NULL) {
return(STATUS_INSUFFICIENT_RESOURCES);
}
plmd->AddList(this);
plmd->m_ldiItem.AddList(plmi);
return(STATUS_SUCCESS);
}
NTSTATUS
CListMulti::AddListEnd(
PVOID p,
CListMultiItem *plmi
)
{
Assert(this);
Assert(plmi);
if(CheckDupList(p)) {
return(STATUS_SUCCESS);
}
PCLIST_MULTI_DATA plmd = new CLIST_MULTI_DATA(p);
if(plmd == NULL) {
return(STATUS_INSUFFICIENT_RESOURCES);
}
plmd->AddListEnd(this);
plmd->m_ldiItem.AddListEnd(plmi);
return(STATUS_SUCCESS);
}
NTSTATUS
CListMulti::AddListOrdered(
PVOID p,
CListMultiItem *plmi,
LONG lFieldOffset
)
{
PCLIST_MULTI_DATA plmd, plmdNew;
ULONG ulOrder;
ASSERT(!CheckDupList(p));
ulOrder = *((PULONG)(((PCHAR)p) + lFieldOffset));
plmdNew = new CLIST_MULTI_DATA(p);
if(plmdNew == NULL) {
return(STATUS_INSUFFICIENT_RESOURCES);
}
plmdNew->m_ldiItem.AddList(plmi);
FOR_EACH_CLIST_ITEM(this, plmd) {
if(ulOrder < *((PULONG)(((PCHAR)GetListData(plmd)) + lFieldOffset))) {
break;
}
} END_EACH_CLIST_ITEM
InsertTailList(&plmd->m_le, &plmdNew->m_le);
return(STATUS_SUCCESS);
}
VOID
CListMulti::RemoveList(
PVOID p
)
{
PCLIST_MULTI_DATA plmd;
Assert(this);
FOR_EACH_CLIST_ITEM_DELETE(this, plmd, CLIST_MULTI_DATA) {
if(GetListData(plmd) == p) {
delete plmd;
}
} END_EACH_CLIST_ITEM
}
VOID
CListMulti::JoinList(
PCLIST_MULTI plm
)
{
Assert(this);
Assert(plm);
ASSERT(this->m_leHead.Blink->Flink == &this->m_leHead);
ASSERT(plm->m_leHead.Blink->Flink == &plm->m_leHead);
ASSERT(this->m_leHead.Flink->Blink == &this->m_leHead);
ASSERT(plm->m_leHead.Flink->Blink == &plm->m_leHead);
if(!plm->IsLstEmpty()) {
this->m_leHead.Blink->Flink = plm->m_leHead.Flink;
plm->m_leHead.Flink->Blink = this->m_leHead.Blink;
plm->m_leHead.Blink->Flink = &this->m_leHead;
this->m_leHead.Blink = plm->m_leHead.Blink;
InitializeListHead(&plm->m_leHead);
}
}
//---------------------------------------------------------------------------
// CListMultiItem Class
//---------------------------------------------------------------------------
CListMultiItem::~CListMultiItem()
{
PCLIST_MULTI_DATA plmd, plmdNext;
for(plmd = CONTAINING_RECORD(GetListFirst(), CLIST_MULTI_DATA, m_ldiItem);
!IsListEnd(&plmd->m_ldiItem);
plmd = plmdNext) {
Assert(plmd);
plmdNext = CONTAINING_RECORD(
GetListNext(&plmd->m_ldiItem),
CLIST_MULTI_DATA,
m_ldiItem);
delete plmd;
}
}
//---------------------------------------------------------------------------
// end of clist.cpp
//---------------------------------------------------------------------------