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.
362 lines
6.2 KiB
362 lines
6.2 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1997 - 1999
|
|
|
|
Module Name:
|
|
|
|
linklist.cxx
|
|
|
|
Abstract:
|
|
|
|
Implements a linked list for Destination Reachability.
|
|
|
|
Author:
|
|
|
|
Gopal Parupudi <GopalP>
|
|
|
|
[Notes:]
|
|
|
|
optional-notes
|
|
|
|
Revision History:
|
|
|
|
GopalP 10/30/1997 Start.
|
|
|
|
--*/
|
|
|
|
#include <precomp.hxx>
|
|
|
|
#define WCHAR_Y ((WCHAR) 'Y')
|
|
#define WCHAR_N ((WCHAR) 'N')
|
|
#define WCHAR_X ((WCHAR) '-')
|
|
|
|
|
|
NODE::NODE()
|
|
{
|
|
Next = NULL;
|
|
Prev = NULL;
|
|
Destination = NULL;
|
|
SubId = ~0;
|
|
cRef = 1;
|
|
State = UNTRIED;
|
|
}
|
|
|
|
NODE::NODE(DWORD Id, PWCHAR Dest, PDWORD pdwStatus)
|
|
{
|
|
*pdwStatus = ERROR_SUCCESS;
|
|
Next = NULL;
|
|
Prev = NULL;
|
|
|
|
// Make a copy of the Destination name
|
|
size_t size = wcslen(Dest) + 1;
|
|
Destination = (PWCHAR) new WCHAR[size];
|
|
if (Destination != NULL)
|
|
{
|
|
StringCchCopyW(Destination, size, Dest);
|
|
}
|
|
else
|
|
{
|
|
*pdwStatus = ERROR_OUTOFMEMORY;
|
|
}
|
|
|
|
SubId = Id;
|
|
cRef = 1;
|
|
State = UNTRIED;
|
|
}
|
|
|
|
NODE::~NODE()
|
|
{
|
|
if (Destination != NULL)
|
|
{
|
|
delete Destination;
|
|
}
|
|
}
|
|
|
|
LIST::LIST()
|
|
{
|
|
pHead = NULL;
|
|
|
|
cElements = 0;
|
|
|
|
InitializeCriticalSection(&ListLock);
|
|
}
|
|
|
|
|
|
LIST::~LIST()
|
|
{
|
|
DeleteAll();
|
|
|
|
DeleteCriticalSection(&ListLock);
|
|
}
|
|
|
|
DWORD
|
|
LIST::Insert(
|
|
PNODE pNew
|
|
)
|
|
{
|
|
ASSERT(pNew != NULL);
|
|
ASSERT(pNew->Destination != NULL);
|
|
|
|
RequestLock();
|
|
|
|
//
|
|
// See if it is already present. Find() will add a reference to the
|
|
// destination if it is already present in the list.
|
|
//
|
|
if (NULL != Find(pNew->Destination, TRUE))
|
|
{
|
|
ReleaseLock();
|
|
Print();
|
|
return ERROR_ALREADY_EXISTS;
|
|
}
|
|
|
|
pNew->Next = pHead;
|
|
if (pHead != NULL)
|
|
{
|
|
pHead->Prev = pNew;
|
|
}
|
|
pHead = pNew;
|
|
|
|
cElements++;
|
|
|
|
ReleaseLock();
|
|
|
|
Print();
|
|
|
|
return ERROR_SUCCESS;
|
|
}
|
|
|
|
DWORD
|
|
LIST::InsertByDest(
|
|
PWCHAR lpszDest
|
|
)
|
|
{
|
|
DWORD dwStatus = ERROR_SUCCESS;
|
|
PNODE pNode = NULL;
|
|
|
|
// Insert into the global list
|
|
pNode = new NODE(99, lpszDest, &dwStatus);
|
|
if ( (dwStatus != ERROR_SUCCESS)
|
|
|| (pNode == NULL))
|
|
{
|
|
if (pNode)
|
|
{
|
|
delete pNode;
|
|
}
|
|
return ERROR_OUTOFMEMORY;
|
|
}
|
|
|
|
dwStatus = Insert(pNode);
|
|
|
|
if (ERROR_ALREADY_EXISTS == dwStatus)
|
|
{
|
|
delete pNode;
|
|
}
|
|
|
|
return dwStatus;
|
|
}
|
|
|
|
inline void
|
|
LIST::Delete(
|
|
PNODE pDelete
|
|
)
|
|
{
|
|
// Should be always called with the ListLock held.
|
|
|
|
if (0 != pDelete->Release())
|
|
{
|
|
Print();
|
|
return;
|
|
}
|
|
|
|
if (pDelete->Next != NULL)
|
|
{
|
|
pDelete->Next->Prev = pDelete->Prev;
|
|
}
|
|
|
|
if (pDelete->Prev != NULL)
|
|
{
|
|
pDelete->Prev->Next = pDelete->Next;
|
|
}
|
|
|
|
if (pDelete == pHead)
|
|
{
|
|
pHead = pDelete->Next;
|
|
}
|
|
|
|
delete pDelete;
|
|
|
|
cElements--;
|
|
|
|
Print();
|
|
}
|
|
|
|
BOOL
|
|
LIST::DeleteByDest(
|
|
PWCHAR lpszDest
|
|
)
|
|
{
|
|
PNODE pTemp = NULL;
|
|
|
|
RequestLock();
|
|
|
|
pTemp = pHead;
|
|
while (pTemp != NULL)
|
|
{
|
|
if (wcscmp(pTemp->Destination, lpszDest) == 0)
|
|
{
|
|
Delete(pTemp);
|
|
ReleaseLock();
|
|
return TRUE;
|
|
}
|
|
|
|
pTemp = pTemp->Next;
|
|
}
|
|
|
|
ReleaseLock();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
LIST::DeleteById(
|
|
DWORD Id
|
|
)
|
|
{
|
|
PNODE pTemp = NULL;
|
|
|
|
RequestLock();
|
|
|
|
pTemp = pHead;
|
|
while (pTemp != NULL)
|
|
{
|
|
if (pTemp->SubId == Id)
|
|
{
|
|
Delete(pTemp);
|
|
ReleaseLock();
|
|
return TRUE;
|
|
}
|
|
|
|
pTemp = pTemp->Next;
|
|
}
|
|
|
|
ReleaseLock();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
LIST::DeleteAll(
|
|
void
|
|
)
|
|
{
|
|
PNODE pTemp, pDelete;
|
|
|
|
RequestLock();
|
|
|
|
pTemp = pHead;
|
|
while (pTemp != NULL)
|
|
{
|
|
pDelete = pTemp;
|
|
pTemp = pTemp->Next;
|
|
delete pDelete;
|
|
cElements--;
|
|
}
|
|
|
|
ASSERT(cElements == 0);
|
|
|
|
ReleaseLock();
|
|
}
|
|
|
|
PNODE
|
|
LIST::Find(
|
|
PWCHAR lpszDest,
|
|
BOOL bAddReference
|
|
)
|
|
{
|
|
PNODE pTemp = NULL;
|
|
|
|
RequestLock();
|
|
|
|
pTemp = pHead;
|
|
while (pTemp != NULL)
|
|
{
|
|
if (wcscmp(pTemp->Destination, lpszDest) == 0)
|
|
{
|
|
if (TRUE == bAddReference)
|
|
{
|
|
pTemp->AddRef();
|
|
}
|
|
ReleaseLock();
|
|
return pTemp;
|
|
}
|
|
|
|
pTemp = pTemp->Next;
|
|
}
|
|
|
|
ReleaseLock();
|
|
|
|
return NULL;
|
|
}
|
|
|
|
BOOL
|
|
LIST::IsEmpty(
|
|
void
|
|
)
|
|
{
|
|
RequestLock();
|
|
|
|
if (pHead == NULL)
|
|
{
|
|
ASSERT(cElements == 0);
|
|
|
|
ReleaseLock();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
ReleaseLock();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void
|
|
LIST::Print(
|
|
void
|
|
)
|
|
{
|
|
#ifdef DBG
|
|
|
|
PNODE pTemp;
|
|
|
|
|
|
SensPrintA(SENS_INFO, ("\n\t|----------------------------------------------------------|\n"));
|
|
SensPrintA(SENS_INFO, ("\t| R E A C H A B I L I T Y L I S T |\n"));
|
|
SensPrintA(SENS_INFO, ("\t|----------------------------------------------------------|\n"));
|
|
SensPrintA(SENS_INFO, ("\t|----------------------------------------------------------|\n"));
|
|
SensPrintA(SENS_INFO, ("\t| cRef | Reachable | Destination |\n"));
|
|
SensPrintA(SENS_INFO, ("\t|----------------------------------------------------------|\n"));
|
|
|
|
RequestLock();
|
|
|
|
pTemp = pHead;
|
|
while (pTemp != NULL)
|
|
{
|
|
SensPrintW(SENS_INFO, (L"\t| %3d | %c | %s\n",
|
|
pTemp->cRef,
|
|
(pTemp->State == REACHABLE) ? WCHAR_Y : ((pTemp->State == UNTRIED) ? WCHAR_X : WCHAR_N),
|
|
pTemp->Destination ? pTemp->Destination : L"<NULL>")
|
|
);
|
|
pTemp = pTemp->Next;
|
|
}
|
|
|
|
ReleaseLock();
|
|
|
|
SensPrintA(SENS_INFO, ("\t|----------------------------------------------------------|\n\n"));
|
|
|
|
#else
|
|
|
|
// Nothing
|
|
|
|
#endif // DBG
|
|
}
|