/*++ Copyright (C) Microsoft Corporation, 1997 - 1999 Module Name: linklist.cxx Abstract: Implements a linked list for Destination Reachability. Author: Gopal Parupudi [Notes:] optional-notes Revision History: GopalP 10/30/1997 Start. --*/ #include #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"") ); pTemp = pTemp->Next; } ReleaseLock(); SensPrintA(SENS_INFO, ("\t|----------------------------------------------------------|\n\n")); #else // Nothing #endif // DBG }