/**********************************************************************/ /** Microsoft Windows/NT **/ /** Copyright(c) Microsoft Corporation, 1997 - 1999 **/ /**********************************************************************/ /* hArray.cpp Index manager for wins db FILE HISTORY: Oct 13 1997 EricDav Created */ #include "stdafx.h" #include "wins.h" #include "memmngr.h" #include "harray.h" #include "mbstring.h" #include "vrfysrv.h" // the lstrcmpA fucntion converts the dbcs string to Unicode using the ACP // and then does a string compare. So, we need to do the OEMCP conversion // and then call the string compare ourselves. int lstrcmpOEM( LPCSTR lpString1, LPCSTR lpString2 ) { CString str1, str2; MBCSToWide((LPSTR) lpString1, str1, WINS_NAME_CODE_PAGE); MBCSToWide((LPSTR) lpString2, str2, WINS_NAME_CODE_PAGE); return lstrcmp(str1, str2); } /*!-------------------------------------------------------------------------- Class CHRowIndex ---------------------------------------------------------------------------*/ CHRowIndex::CHRowIndex(INDEX_TYPE IndexType) : m_dbType(IndexType), m_bAscending(TRUE) { } CHRowIndex::~CHRowIndex() { } /*!-------------------------------------------------------------------------- CHRowIndex::GetType - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CHRowIndex::GetType(INDEX_TYPE * pIndexType) { if (pIndexType) *pIndexType = m_dbType; return hrOK; } /*!-------------------------------------------------------------------------- CHRowIndex::SetArray - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CHRowIndex::SetArray(HRowArray & hrowArray) { m_hrowArray.Copy(hrowArray); return hrOK; } /*!-------------------------------------------------------------------------- CHRowIndex::GetHRow - Author: EricDav ---------------------------------------------------------------------------*/ HROW CHRowIndex::GetHRow(int nIndex) { Assert(nIndex >= 0); Assert(nIndex <= m_hrowArray.GetSize()); if (nIndex < 0 || nIndex >= m_hrowArray.GetSize()) { return NULL; } return m_hrowArray.GetAt(nIndex); } /*!-------------------------------------------------------------------------- CHRowIndex::GetIndex - Author: EricDav ---------------------------------------------------------------------------*/ int CHRowIndex::GetIndex(HROW hrow) { Assert(hrow != 0); LPHROW phrow = (LPHROW) BSearch((const void *)&hrow, (const void *)m_hrowArray.GetData(), (size_t) m_hrowArray.GetSize(), (size_t) sizeof(HROW)); int nIndex = (int) (phrow - (LPHROW) m_hrowArray.GetData()); Assert(nIndex >= 0); Assert(nIndex <= m_hrowArray.GetSize()); int nComp, nIndexTemp; nComp = BCompare(&hrow, phrow); if (nComp == 0) { // found the right one, check the previous one to return the first // record in a list of duplicates nIndexTemp = nIndex; while (nIndexTemp && nComp == 0) { *phrow = (HROW) m_hrowArray.GetAt(--nIndexTemp); nComp = BCompare(&hrow, phrow); } if (nIndexTemp == nIndex) return nIndex; // nIndex should be zero here as well else if (nComp == 0) return nIndexTemp; // nIndexTemp should be 0 in this case else return nIndexTemp++; } return -1; } /*!-------------------------------------------------------------------------- CHRowIndex::Add - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CHRowIndex::Add(HROW hrow, BOOL bEnd) { // if we are loading the array then just stick this on the end if (bEnd) { m_hrowArray.Add(hrow); } else { if (m_hrowArray.GetSize() == 0) { m_hrowArray.Add(hrow); } else { LPHROW phrow = (LPHROW) BSearch((const void *)&hrow, (const void *)m_hrowArray.GetData(), (size_t) m_hrowArray.GetSize(), (size_t) sizeof(HROW)); int nIndex = (int) (phrow - (LPHROW) m_hrowArray.GetData()); Assert(nIndex >= 0); Assert(nIndex <= m_hrowArray.GetSize()); int nComp; if (m_bAscending) nComp = BCompare(&hrow, phrow); else nComp = BCompareD(&hrow, phrow); if (nComp < 0) { // Insert before phrow m_hrowArray.InsertAt(nIndex, hrow); } else { // insert after phrow m_hrowArray.InsertAt(nIndex + 1, hrow); } } } return hrOK; } /*!-------------------------------------------------------------------------- CHRowIndex::Remove - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CHRowIndex::Remove(HROW hrow) { // do a bsearch for the record and then remove LPHROW phrow = (LPHROW) BSearch((const void*)&hrow, (const void*)m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), (size_t)sizeof(HROW)); // make sure the record is in the database, may not be if we aren't // filtering if (phrow) { int nComp = BCompare(&hrow, phrow); Assert(nComp == 0); if (nComp != 0) return E_FAIL; // calculate the index int nIndex = (int) (phrow - (LPHROW) m_hrowArray.GetData()); Assert(nIndex >= 0); Assert(nIndex <= m_hrowArray.GetSize()); m_hrowArray.RemoveAt((int) nIndex); } return hrOK; } /*!-------------------------------------------------------------------------- CHRowIndex::BSearch Modified bsearch which returns the closest or equal element in an array Author: EricDav ---------------------------------------------------------------------------*/ void * CHRowIndex::BSearch (const void *key, const void *base, size_t num, size_t width) { char *lo = (char *)base; char *hi = (char *)base + (num - 1) * width; char *mid = NULL; unsigned int half = 0; int result = 0; while (lo <= hi) if (half = num / 2) { mid = lo + (num & 1 ? half : (half - 1)) * width; if (m_bAscending) { if (!(result = BCompare(key,mid))) return(mid); else if (result < 0) { hi = mid - width; num = num & 1 ? half : half-1; } else { lo = mid + width; num = half; } } else { if (!(result = BCompareD(key,mid))) return(mid); else if (result < 0) { hi = mid - width; num = num & 1 ? half : half-1; } else { lo = mid + width; num = half; } } } else if (num) return(lo); else break; return(mid); } /*!-------------------------------------------------------------------------- Class CIndexMgr ---------------------------------------------------------------------------*/ CIndexMgr::CIndexMgr() { m_posCurrentIndex = NULL; m_posFilteredIndex = NULL; m_posLastIndex = NULL; m_posUpdatedIndex = NULL; m_bFiltered = FALSE; } CIndexMgr::~CIndexMgr() { Reset(); } /*!-------------------------------------------------------------------------- CIndexMgr::Initialize - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexMgr::Initialize() { HRESULT hr = hrOK; CSingleLock cl(&m_cs); cl.Lock(); COM_PROTECT_TRY { // cleanup Reset(); // Create one index, the named index CIndexName * pName = new CIndexName(); m_posCurrentIndex = m_listIndicies.AddTail((CHRowIndex *) pName); m_posUpdatedIndex = m_posCurrentIndex; // this will be the current index, we need the Named Index also // for the total count CFilteredIndexName *pFilteredName = new CFilteredIndexName() ; m_posFilteredIndex = m_listFilteredIndices.AddTail((CHRowIndex *) pFilteredName); } COM_PROTECT_CATCH return hr; } /*!-------------------------------------------------------------------------- CIndexMgr::Reset - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexMgr::Reset() { CSingleLock cl(&m_cs); cl.Lock(); while (m_listIndicies.GetCount() > 0) { delete m_listIndicies.RemoveHead(); } while(m_listFilteredIndices.GetCount() > 0 ) { delete m_listFilteredIndices.RemoveHead(); } return hrOK; } /*!-------------------------------------------------------------------------- CIndexMgr::GetTotalCount The index sorted by name contains the total database and should always be available. Use this for the total count. Author: EricDav ---------------------------------------------------------------------------*/ UINT CIndexMgr::GetTotalCount() { CSingleLock cl(&m_cs); cl.Lock(); CHRowIndex * pIndex = GetNameIndex(); if (pIndex == NULL) return 0; return (UINT)pIndex->GetArray().GetSize(); } /*!-------------------------------------------------------------------------- CIndexMgr::GetCurrentCount The current count may differ depending upon if the current Index is a filtered index. Author: EricDav ---------------------------------------------------------------------------*/ UINT CIndexMgr::GetCurrentCount() { CSingleLock cl(&m_cs); cl.Lock(); CHRowIndex * pIndex ; if (!m_bFiltered) pIndex = m_listIndicies.GetAt(m_posUpdatedIndex); else pIndex = m_listFilteredIndices.GetAt(m_posUpdatedIndex); if (pIndex == NULL) return 0; return (UINT)pIndex->GetArray().GetSize(); } /*!-------------------------------------------------------------------------- CIndexMgr::AddHRow - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexMgr::AddHRow(HROW hrow, BOOL bEnd, BOOL bFilterChecked) { CSingleLock cl(&m_cs); cl.Lock(); INDEX_TYPE indexType; HRESULT hr = hrOK; POSITION pos = m_listIndicies.GetHeadPosition(); COM_PROTECT_TRY { while (pos) { CHRowIndex * pIndex = m_listIndicies.GetNext(pos); // check the INDEX type of the HRowIndex, // if filtered, need to add, depending on // whether the filter holds good pIndex->GetType(&indexType); if (indexType != INDEX_TYPE_FILTER) pIndex->Add(hrow, bEnd); } pos = m_listFilteredIndices.GetHeadPosition(); while(pos) { CHRowIndex * pIndex = m_listFilteredIndices.GetNext(pos); pIndex->GetType(&indexType); if (indexType != INDEX_TYPE_FILTER) break; BOOL bCheck = bFilterChecked ? TRUE : ((CFilteredIndexName*)pIndex)->CheckForFilter(&hrow); if (bCheck) pIndex->Add(hrow, bEnd); } } COM_PROTECT_CATCH return hr; } /*!-------------------------------------------------------------------------- CIndexMgr::AcceptHRow - Author: FlorinT ---------------------------------------------------------------------------*/ BOOL CIndexMgr::AcceptWinsRecord(WinsRecord *pWinsRecord) { CSingleLock cl(&m_cs); cl.Lock(); POSITION pos = m_listFilteredIndices.GetHeadPosition(); while(pos) { CHRowIndex *pIndex = m_listFilteredIndices.GetNext(pos); INDEX_TYPE indexType; pIndex->GetType(&indexType); if (indexType != INDEX_TYPE_FILTER) break; if (((CFilteredIndexName*)pIndex)->CheckWinsRecordForFilter(pWinsRecord)) return TRUE; } return FALSE; } /*!-------------------------------------------------------------------------- CIndexMgr::RemoveHRow - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexMgr::RemoveHRow(HROW hrow) { CSingleLock cl(&m_cs); cl.Lock(); HRESULT hr = hrOK; POSITION pos = m_listIndicies.GetHeadPosition(); COM_PROTECT_TRY { // remove from the normal list while (pos) { CHRowIndex * pIndex = m_listIndicies.GetNext(pos); pIndex->Remove(hrow); } // now remove from the filtered list pos = m_listFilteredIndices.GetHeadPosition(); while (pos) { CHRowIndex * pIndex = m_listFilteredIndices.GetNext(pos); pIndex->Remove(hrow); } } COM_PROTECT_CATCH return hr; } /*!-------------------------------------------------------------------------- CIndexMgr::Sort - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexMgr::Sort(WINSDB_SORT_TYPE SortType, DWORD dwSortOptions) { CSingleLock cl(&m_cs); cl.Lock(); HRESULT hr = hrOK; CHRowIndex * pNameIndex; CHRowIndex * pNewIndex; POSITION pos; INDEX_TYPE indexType; BOOL bAscending = (dwSortOptions & WINSDB_SORT_ASCENDING) ? TRUE : FALSE; if (!m_bFiltered) { // check to see if we have an index for this. pos = m_listIndicies.GetHeadPosition(); while (pos) { POSITION posTemp = pos; CHRowIndex * pIndex = m_listIndicies.GetNext(pos); pIndex->GetType(&indexType); if (indexType == SortType) { if (pIndex->IsAscending() != bAscending) { pIndex->SetAscending(bAscending); pIndex->Sort(); } m_posCurrentIndex = posTemp; m_posUpdatedIndex = m_posCurrentIndex; // m_posLastIndex = m_posCurrentIndex; return hrOK; } } } // to save memory, remove all old indicies, except the name index CleanupIndicies(); COM_PROTECT_TRY { // if not, create one switch (SortType) { case INDEX_TYPE_NAME: pNewIndex = new CIndexName(); break; case INDEX_TYPE_IP: pNewIndex = new CIndexIpAddr(); break; case INDEX_TYPE_VERSION: pNewIndex = new CIndexVersion(); break; case INDEX_TYPE_TYPE: pNewIndex = new CIndexType(); break; case INDEX_TYPE_EXPIRATION: pNewIndex = new CIndexExpiration(); break; case INDEX_TYPE_STATE: pNewIndex = new CIndexState(); break; case INDEX_TYPE_STATIC: pNewIndex = new CIndexStatic(); break; case INDEX_TYPE_OWNER: pNewIndex = new CIndexOwner(); break; case INDEX_TYPE_FILTER: //pNewIndex = new CIndexFilter(); break; default: Panic1("Invalid sort type passed to IndexMgr::Sort %d\n", SortType); break; } } COM_PROTECT_CATCH if (FHrSucceeded(hr)) { Assert(pNewIndex); if (!m_bFiltered) pNameIndex = GetNameIndex(); else pNameIndex = GetFilteredNameIndex(); Assert(pNameIndex); COM_PROTECT_TRY { // copy the array from the named index pNewIndex->SetArray(pNameIndex->GetArray()); } COM_PROTECT_CATCH } if (FHrSucceeded(hr)) { pNewIndex->SetAscending(bAscending); pNewIndex->Sort(); if (!m_bFiltered) { m_posCurrentIndex = m_listIndicies.AddTail(pNewIndex); m_posUpdatedIndex = m_posCurrentIndex; } else { POSITION posTemp = m_posFilteredIndex = m_listFilteredIndices.AddTail(pNewIndex); m_posUpdatedIndex = posTemp;// m_posFilteredIndex; } Assert(m_posCurrentIndex); } if (!FHrSucceeded(hr)) { if (pNewIndex != NULL) delete pNewIndex; } return hr; } /*!-------------------------------------------------------------------------- CIndexMgr::GetNameIndex - Author: EricDav ---------------------------------------------------------------------------*/ CHRowIndex * CIndexMgr::GetNameIndex() { CSingleLock cl(&m_cs); cl.Lock(); INDEX_TYPE indexType; POSITION pos = m_listIndicies.GetHeadPosition(); while (pos) { CHRowIndex * pIndex = m_listIndicies.GetNext(pos); pIndex->GetType(&indexType); if (indexType == INDEX_TYPE_NAME) return pIndex; } return NULL; } /*!-------------------------------------------------------------------------- CIndexMgr::GetFilteredNameIndex - Author: EricDav ---------------------------------------------------------------------------*/ CHRowIndex * CIndexMgr::GetFilteredNameIndex() { CSingleLock cl(&m_cs); cl.Lock(); INDEX_TYPE indexType; POSITION pos = m_listFilteredIndices.GetHeadPosition(); while (pos) { CHRowIndex * pIndex = m_listFilteredIndices.GetNext(pos); pIndex->GetType(&indexType); if (indexType == INDEX_TYPE_FILTER) return pIndex; } return NULL; } /*!-------------------------------------------------------------------------- CIndexMgr::CleanupIndicies Removes all indicies except the name index, and a filtered view Author: EricDav ---------------------------------------------------------------------------*/ void CIndexMgr::CleanupIndicies() { CSingleLock cl(&m_cs); cl.Lock(); INDEX_TYPE indexType; // clean up the non-filtered indicies POSITION pos = m_listIndicies.GetHeadPosition(); while (pos) { POSITION posLast = pos; CHRowIndex * pIndex = m_listIndicies.GetNext(pos); pIndex->GetType(&indexType); if (indexType == INDEX_TYPE_NAME || indexType == INDEX_TYPE_FILTER) continue; m_listIndicies.RemoveAt(posLast); delete pIndex; } // now clean up the filtered indicies pos = m_listFilteredIndices.GetHeadPosition(); // delete all except the first one which is the filetered // name index //CHRowIndex * pIndex = m_listFilteredIndices.GetNext(pos); while (pos) { POSITION posLast = pos; CHRowIndex * pIndex = m_listFilteredIndices.GetNext(pos); pIndex->GetType(&indexType); if (indexType == INDEX_TYPE_NAME || indexType == INDEX_TYPE_FILTER) continue; m_listFilteredIndices.RemoveAt(posLast); delete pIndex; } } /*!-------------------------------------------------------------------------- CIndexMgr::GetHRow Returns an hrow based on an index into the current sorted list Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexMgr::GetHRow(int nIndex, LPHROW phrow) { CSingleLock cl(&m_cs); cl.Lock(); Assert(m_posCurrentIndex != NULL); //CHRowIndex * pIndex = m_listIndicies.GetAt(m_posCurrentIndex); CHRowIndex * pIndex; if (!m_bFiltered) pIndex = m_listIndicies.GetAt(m_posUpdatedIndex); else pIndex = m_listFilteredIndices.GetAt(m_posFilteredIndex); Assert(pIndex); if (phrow) *phrow = pIndex->GetHRow(nIndex); return hrOK; } /*!-------------------------------------------------------------------------- CIndexMgr::GetIndex Returns the index of an hrow from the current sorted list Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexMgr::GetIndex(HROW hrow, int * pIndex) { CSingleLock cl(&m_cs); cl.Lock(); Assert(m_posCurrentIndex != NULL); //CHRowIndex * pCurrentIndex = m_listIndicies.GetAt(m_posCurrentIndex); CHRowIndex * pCurrentIndex; if (!m_bFiltered) pCurrentIndex = m_listIndicies.GetAt(m_posUpdatedIndex); else pCurrentIndex = m_listFilteredIndices.GetAt(m_posFilteredIndex); Assert(pCurrentIndex); if (pIndex) *pIndex = pCurrentIndex->GetIndex(hrow); return hrOK; } HRESULT CIndexMgr::Filter(WINSDB_FILTER_TYPE FilterType, DWORD dwParam1, DWORD dwParam2) { CSingleLock cl(&m_cs); cl.Lock(); HRESULT hr = hrOK; CHRowIndex* pNameIndex; CHRowIndex* pNewIndex; POSITION pos; INDEX_TYPE indexType; UINT uCount; UINT i; BOOL bCheck = FALSE; HROW hrow; HRowArray hrowArray; pNewIndex = GetFilteredNameIndex(); Assert(pNewIndex); // clear the filtered name index first. pNewIndex->SetArray(hrowArray); pNameIndex = GetNameIndex(); Assert(pNameIndex); // do the filtering here. uCount = GetTotalCount(); for(i = 0; i< uCount; i++) { hrow = pNameIndex->GetHRow(i); if (hrow) bCheck = ((CFilteredIndexName *)pNewIndex)->CheckForFilter(&hrow); if (bCheck) pNewIndex->Add(hrow, TRUE); } // check to see if the filtered view has been sorted on something else besides // the name. If so, switch back the index to the named index because // otherwise we will need to resort which can be time consuming... if (m_listFilteredIndices.GetAt(m_posFilteredIndex) != pNewIndex) { m_posFilteredIndex = m_listFilteredIndices.Find(pNewIndex); } // get the current position of the filtered index in the list of indices m_posUpdatedIndex = m_posFilteredIndex; Assert(m_posUpdatedIndex); m_bFiltered = TRUE; return hr; } HRESULT CIndexMgr::AddFilter(WINSDB_FILTER_TYPE FilterType, DWORD dwParam1, DWORD dwParam2, LPCOLESTR strParam3) { CSingleLock cl(&m_cs); cl.Lock(); HRESULT hr = hrOK; CFilteredIndexName *pFilterName = (CFilteredIndexName *)GetFilteredNameIndex(); pFilterName->AddFilter(FilterType, dwParam1, dwParam2, strParam3); m_bFiltered = TRUE; return hr; } HRESULT CIndexMgr::ClearFilter(WINSDB_FILTER_TYPE FilterType) { CSingleLock cl(&m_cs); cl.Lock(); HRESULT hr = hrOK; CFilteredIndexName *pFilterName = (CFilteredIndexName *)GetFilteredNameIndex(); pFilterName->ClearFilter(FilterType); m_bFiltered = FALSE; // m_posCurrentIndex = m_posLastIndex; return hr; } HRESULT CIndexMgr::SetActiveView(WINSDB_VIEW_TYPE ViewType) { CSingleLock cl(&m_cs); cl.Lock(); HRESULT hr = hrOK; switch(ViewType) { case WINSDB_VIEW_FILTERED_DATABASE: m_bFiltered = TRUE; //m_posCurrentIndex = m_posFilteredIndex; m_posUpdatedIndex = m_posFilteredIndex; break; case WINSDB_VIEW_ENTIRE_DATABASE: m_bFiltered = FALSE; //m_posCurrentIndex = m_posLastIndex; m_posUpdatedIndex = m_posCurrentIndex; break; default: break; } return hr; } /*!-------------------------------------------------------------------------- Class CIndexName ---------------------------------------------------------------------------*/ /*!-------------------------------------------------------------------------- CIndexName::BCompare - Author: EricDav ---------------------------------------------------------------------------*/ int CIndexName::BCompare(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; LPCSTR puChar1 = (IS_DBREC_LONGNAME(pRec1)) ? (LPCSTR) *((char **) pRec1->szRecordName) : (LPCSTR) &pRec1->szRecordName[0]; LPCSTR puChar2 = (IS_DBREC_LONGNAME(pRec2)) ? (LPCSTR) *((char **) pRec2->szRecordName) : (LPCSTR) &pRec2->szRecordName[0]; return lstrcmpOEM(puChar1, puChar2); } int CIndexName::BCompareD(const void *elem1, const void *elem2) { return -BCompare(elem1, elem2); } /*!-------------------------------------------------------------------------- CIndexName::Sort - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexName::Sort() { if (m_bAscending) qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareA); else qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareD); return hrOK; } /*!-------------------------------------------------------------------------- CIndexName::QCompare - Author: EricDav ---------------------------------------------------------------------------*/ int __cdecl CIndexName::QCompareA(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; LPCSTR puChar1 = (IS_DBREC_LONGNAME(pRec1)) ? (LPCSTR) *((char **) pRec1->szRecordName) : (LPCSTR) &pRec1->szRecordName[0]; LPCSTR puChar2 = (IS_DBREC_LONGNAME(pRec2)) ? (LPCSTR) *((char **) pRec2->szRecordName) : (LPCSTR) &pRec2->szRecordName[0]; return lstrcmpOEM(puChar1, puChar2); } int __cdecl CIndexName::QCompareD(const void * elem1, const void * elem2) { return -QCompareA(elem1, elem2); } /*!-------------------------------------------------------------------------- Class CIndexType ---------------------------------------------------------------------------*/ /*!-------------------------------------------------------------------------- CIndexType::BCompare - Author: EricDav ---------------------------------------------------------------------------*/ int CIndexType::BCompare(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; LPCSTR puChar1 = (IS_DBREC_LONGNAME(pRec1)) ? (LPCSTR) *((char **) pRec1->szRecordName) : (LPCSTR) &pRec1->szRecordName[0]; LPCSTR puChar2 = (IS_DBREC_LONGNAME(pRec2)) ? (LPCSTR) *((char **) pRec2->szRecordName) : (LPCSTR) &pRec2->szRecordName[0]; if ((unsigned char) puChar1[15] > (unsigned char) puChar2[15]) return 1; else if ((unsigned char) puChar1[15] < (unsigned char) puChar2[15]) return -1; else return lstrcmpOEM(puChar1, puChar2); } int CIndexType::BCompareD(const void *elem1, const void *elem2) { return -BCompare(elem1, elem2); } /*!-------------------------------------------------------------------------- CIndexType::Sort - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexType::Sort() { if (m_bAscending) qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareA); else qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareD); return hrOK; } /*!-------------------------------------------------------------------------- CIndexType::QCompare - Author: EricDav ---------------------------------------------------------------------------*/ int __cdecl CIndexType::QCompareA(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; LPCSTR puChar1 = (IS_DBREC_LONGNAME(pRec1)) ? (LPCSTR) *((char **) pRec1->szRecordName) : (LPCSTR) &pRec1->szRecordName[0]; LPCSTR puChar2 = (IS_DBREC_LONGNAME(pRec2)) ? (LPCSTR) *((char **) pRec2->szRecordName) : (LPCSTR) &pRec2->szRecordName[0]; DWORD dwAddr1, dwAddr2; if (pRec1->szRecordName[18] & WINSDB_REC_MULT_ADDRS) { // if this record has multiple addresses, we want the 2nd // address, because the 1st address is always the WINS server // first dword is the count. LPDWORD pdwIpAddrs = (LPDWORD) pRec1->dwIpAdd; dwAddr1 = pdwIpAddrs[2]; } else { dwAddr1 = (DWORD) pRec1->dwIpAdd; } if (pRec2->szRecordName[18] & WINSDB_REC_MULT_ADDRS) { // if this record has multiple addresses, we want the 2nd // address, because the 1st address is always the WINS server // first dword is the count. LPDWORD pdwIpAddrs = (LPDWORD) pRec2->dwIpAdd; dwAddr2 = pdwIpAddrs[2]; } else { dwAddr2 = (DWORD) pRec2->dwIpAdd; } // check the types first. If they are the same, sort by IP address. // if for some reason the IP addresses are the same then sort by name. if ((unsigned char) puChar1[15] > (unsigned char) puChar2[15]) return 1; else if ((unsigned char) puChar1[15] < (unsigned char) puChar2[15]) return -1; else if (dwAddr1 > dwAddr2) return 1; else if (dwAddr1 < dwAddr2) return -1; else return lstrcmpOEM(puChar1, puChar2); } int __cdecl CIndexType::QCompareD(const void * elem1, const void * elem2) { return -QCompareA(elem1, elem2); } /*!-------------------------------------------------------------------------- Class CIndexIpAddr ---------------------------------------------------------------------------*/ /*!-------------------------------------------------------------------------- CIndexIpAddr::BCompare - Author: EricDav ---------------------------------------------------------------------------*/ int CIndexIpAddr::BCompare(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; DWORD dwAddr1, dwAddr2; if (pRec1->szRecordName[18] & WINSDB_REC_MULT_ADDRS) { // if this record has multiple addresses, we want the 2nd // address, because the 1st address is always the WINS server // first dword is the count. LPDWORD pdwIpAddrs = (LPDWORD) pRec1->dwIpAdd; dwAddr1 = pdwIpAddrs[2]; } else { dwAddr1 = (DWORD) pRec1->dwIpAdd; } if (pRec2->szRecordName[18] & WINSDB_REC_MULT_ADDRS) { // if this record has multiple addresses, we want the 2nd // address, because the 1st address is always the WINS server // first dword is the count. LPDWORD pdwIpAddrs = (LPDWORD) pRec2->dwIpAdd; dwAddr2 = pdwIpAddrs[2]; } else { dwAddr2 = (DWORD) pRec2->dwIpAdd; } if (dwAddr1 > dwAddr2) return 1; else if (dwAddr1 < dwAddr2) return -1; else { // if the addresses are the same, compare types, then names LPCSTR puChar1 = (IS_DBREC_LONGNAME(pRec1)) ? (LPCSTR) *((char **) pRec1->szRecordName) : (LPCSTR) &pRec1->szRecordName[0]; LPCSTR puChar2 = (IS_DBREC_LONGNAME(pRec2)) ? (LPCSTR) *((char **) pRec2->szRecordName) : (LPCSTR) &pRec2->szRecordName[0]; if ((unsigned char) puChar1[15] > (unsigned char) puChar2[15]) return 1; else if ((unsigned char) puChar1[15] < (unsigned char) puChar2[15]) return -1; else return lstrcmpOEM(puChar1, puChar2); } } int CIndexIpAddr::BCompareD(const void *elem1, const void *elem2) { return -BCompare(elem1, elem2); } /*!-------------------------------------------------------------------------- CIndexIpAddr::Sort - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexIpAddr::Sort() { if (m_bAscending) qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareA); else qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareD); return hrOK; } /*!-------------------------------------------------------------------------- CIndexIpAddr::QCompare - Author: EricDav ---------------------------------------------------------------------------*/ int __cdecl CIndexIpAddr::QCompareA(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; DWORD dwAddr1, dwAddr2; if (pRec1->szRecordName[18] & WINSDB_REC_MULT_ADDRS) { // if this record has multiple addresses, we want the 2nd // address, because the 1st address is always the WINS server // first dword is the count. LPDWORD pdwIpAddrs = (LPDWORD) pRec1->dwIpAdd; dwAddr1 = pdwIpAddrs[2]; } else { dwAddr1 = (DWORD) pRec1->dwIpAdd; } if (pRec2->szRecordName[18] & WINSDB_REC_MULT_ADDRS) { // if this record has multiple addresses, we want the 2nd // address, because the 1st address is always the WINS server // first dword is the count. LPDWORD pdwIpAddrs = (LPDWORD) pRec2->dwIpAdd; dwAddr2 = pdwIpAddrs[2]; } else { dwAddr2 = (DWORD) pRec2->dwIpAdd; } if (dwAddr1 > dwAddr2) return 1; else if (dwAddr1 < dwAddr2) return -1; else { // if the addresses are the same, compare types, then names LPCSTR puChar1 = (IS_DBREC_LONGNAME(pRec1)) ? (LPCSTR) *((char **) pRec1->szRecordName) : (LPCSTR) &pRec1->szRecordName[0]; LPCSTR puChar2 = (IS_DBREC_LONGNAME(pRec2)) ? (LPCSTR) *((char **) pRec2->szRecordName) : (LPCSTR) &pRec2->szRecordName[0]; if ((unsigned char) puChar1[15] > (unsigned char) puChar2[15]) return 1; else if ((unsigned char) puChar1[15] < (unsigned char) puChar2[15]) return -1; else return lstrcmpOEM(puChar1, puChar2); } } int __cdecl CIndexIpAddr::QCompareD(const void * elem1, const void * elem2) { return -QCompareA(elem1, elem2); } /*!-------------------------------------------------------------------------- Class CIndexVersion ---------------------------------------------------------------------------*/ /*!-------------------------------------------------------------------------- CIndexVersion::BCompare - Author: EricDav ---------------------------------------------------------------------------*/ int CIndexVersion::BCompare(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; if (pRec1->liVersion.QuadPart > pRec2->liVersion.QuadPart) return 1; else if (pRec1->liVersion.QuadPart < pRec2->liVersion.QuadPart) return -1; else return 0; } int CIndexVersion::BCompareD(const void *elem1, const void *elem2) { return -BCompare(elem1, elem2); } /*!-------------------------------------------------------------------------- CIndexVersion::Sort - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexVersion::Sort() { if (m_bAscending) qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareA); else qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareD); return hrOK; } /*!-------------------------------------------------------------------------- CIndexVersion::QCompare - Author: EricDav ---------------------------------------------------------------------------*/ int __cdecl CIndexVersion::QCompareA(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; if (pRec1->liVersion.QuadPart > pRec2->liVersion.QuadPart) return 1; else if (pRec1->liVersion.QuadPart < pRec2->liVersion.QuadPart) return -1; else return 0; } int __cdecl CIndexVersion::QCompareD(const void * elem1, const void * elem2) { return -QCompareA(elem1, elem2); } /*!-------------------------------------------------------------------------- Class CIndexExpiration ---------------------------------------------------------------------------*/ /*!-------------------------------------------------------------------------- CIndexExpiration::BCompare - Author: EricDav ---------------------------------------------------------------------------*/ int CIndexExpiration::BCompare(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; if (pRec1->dwExpiration > pRec2->dwExpiration) return 1; else if (pRec1->dwExpiration < pRec2->dwExpiration) return -1; else return 0; } int CIndexExpiration::BCompareD(const void *elem1, const void *elem2) { return -BCompare(elem1, elem2); } /*!-------------------------------------------------------------------------- CIndexExpiration::Sort - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexExpiration::Sort() { if (m_bAscending) qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareA); else qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareD); return hrOK; } /*!-------------------------------------------------------------------------- CIndexExpiration::QCompare - Author: EricDav ---------------------------------------------------------------------------*/ int __cdecl CIndexExpiration::QCompareA(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; if (pRec1->dwExpiration > pRec2->dwExpiration) return 1; else if (pRec1->dwExpiration < pRec2->dwExpiration) return -1; else return 0; } int __cdecl CIndexExpiration::QCompareD(const void * elem1, const void * elem2) { return -QCompareA(elem1, elem2); } /*!-------------------------------------------------------------------------- Class CIndexState ---------------------------------------------------------------------------*/ /*!-------------------------------------------------------------------------- CIndexState::BCompare - Author: EricDav ---------------------------------------------------------------------------*/ int CIndexState::BCompare(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; int nPri1 = 0, nPri2 = 0; // calculate relative priorities if (pRec1->szRecordName[18] & WINSDB_REC_ACTIVE) nPri1 = 0; else if (pRec1->szRecordName[18] & WINSDB_REC_RELEASED) nPri1 = 1; else if (pRec1->szRecordName[18] & WINSDB_REC_TOMBSTONE) nPri1 = 2; else if (pRec1->szRecordName[18] & WINSDB_REC_DELETED) nPri1 = 3; // now for record 2 if (pRec2->szRecordName[18] & WINSDB_REC_ACTIVE) nPri2 = 0; else if (pRec2->szRecordName[18] & WINSDB_REC_RELEASED) nPri2 = 1; else if (pRec2->szRecordName[18] & WINSDB_REC_TOMBSTONE) nPri2 = 2; else if (pRec2->szRecordName[18] & WINSDB_REC_DELETED) nPri2 = 3; if (nPri1 > nPri2) return 1; else if (nPri1 < nPri2) return -1; else { LPCSTR puChar1 = (IS_DBREC_LONGNAME(pRec1)) ? (LPCSTR) *((char **) pRec1->szRecordName) : (LPCSTR) &pRec1->szRecordName[0]; LPCSTR puChar2 = (IS_DBREC_LONGNAME(pRec2)) ? (LPCSTR) *((char **) pRec2->szRecordName) : (LPCSTR) &pRec2->szRecordName[0]; return lstrcmpOEM(puChar1, puChar2); } } int CIndexState::BCompareD(const void *elem1, const void *elem2) { return -BCompare(elem1, elem2); } /*!-------------------------------------------------------------------------- CIndexState::Sort - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexState::Sort() { if (m_bAscending) qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareA); else qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareD); return hrOK; } /*!-------------------------------------------------------------------------- CIndexState::QCompare - Author: EricDav ---------------------------------------------------------------------------*/ int __cdecl CIndexState::QCompareA(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; int nPri1 = 0, nPri2 = 0; // calculate relative priorities if (pRec1->szRecordName[18] & WINSDB_REC_ACTIVE) nPri1 = 0; else if (pRec1->szRecordName[18] & WINSDB_REC_RELEASED) nPri1 = 1; else if (pRec1->szRecordName[18] & WINSDB_REC_TOMBSTONE) nPri1 = 2; else if (pRec1->szRecordName[18] & WINSDB_REC_DELETED) nPri1 = 3; // now for record 2 if (pRec2->szRecordName[18] & WINSDB_REC_ACTIVE) nPri2 = 0; else if (pRec2->szRecordName[18] & WINSDB_REC_RELEASED) nPri2 = 1; else if (pRec2->szRecordName[18] & WINSDB_REC_TOMBSTONE) nPri2 = 2; else if (pRec2->szRecordName[18] & WINSDB_REC_DELETED) nPri2 = 3; if (nPri1 > nPri2) return 1; else if (nPri1 < nPri2) return -1; else { LPCSTR puChar1 = (IS_DBREC_LONGNAME(pRec1)) ? (LPCSTR) *((char **) pRec1->szRecordName) : (LPCSTR) &pRec1->szRecordName[0]; LPCSTR puChar2 = (IS_DBREC_LONGNAME(pRec2)) ? (LPCSTR) *((char **) pRec2->szRecordName) : (LPCSTR) &pRec2->szRecordName[0]; return lstrcmpOEM(puChar1, puChar2); } } int __cdecl CIndexState::QCompareD(const void * elem1, const void * elem2) { return -QCompareA(elem1, elem2); } /*!-------------------------------------------------------------------------- Class CIndexStatic ---------------------------------------------------------------------------*/ /*!-------------------------------------------------------------------------- CIndexStatic::BCompare - Author: EricDav ---------------------------------------------------------------------------*/ int CIndexStatic::BCompare(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; BOOL bStatic1 = pRec1->szRecordName[18] & LOBYTE(LOWORD(WINSDB_REC_STATIC)); BOOL bStatic2 = pRec2->szRecordName[18] & LOBYTE(LOWORD(WINSDB_REC_STATIC)); if (bStatic1 && !bStatic2) return 1; else if (!bStatic1 && bStatic2) return -1; else { LPCSTR puChar1 = (IS_DBREC_LONGNAME(pRec1)) ? (LPCSTR) *((char **) pRec1->szRecordName) : (LPCSTR) &pRec1->szRecordName[0]; LPCSTR puChar2 = (IS_DBREC_LONGNAME(pRec2)) ? (LPCSTR) *((char **) pRec2->szRecordName) : (LPCSTR) &pRec2->szRecordName[0]; return lstrcmpOEM(puChar1, puChar2); } } int CIndexStatic::BCompareD(const void *elem1, const void *elem2) { return -BCompare(elem1, elem2); } /*!-------------------------------------------------------------------------- CIndexStatic::Sort - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexStatic::Sort() { if (m_bAscending) qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareA); else qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareD); return hrOK; } /*!-------------------------------------------------------------------------- CIndexStatic::QCompare - Author: EricDav ---------------------------------------------------------------------------*/ int __cdecl CIndexStatic::QCompareA(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; BOOL bStatic1 = pRec1->szRecordName[18] & LOBYTE(LOWORD(WINSDB_REC_STATIC)); BOOL bStatic2 = pRec2->szRecordName[18] & LOBYTE(LOWORD(WINSDB_REC_STATIC)); if (bStatic1 && !bStatic2) return 1; else if (!bStatic1 && bStatic2) return -1; else { LPCSTR puChar1 = (IS_DBREC_LONGNAME(pRec1)) ? (LPCSTR) *((char **) pRec1->szRecordName) : (LPCSTR) &pRec1->szRecordName[0]; LPCSTR puChar2 = (IS_DBREC_LONGNAME(pRec2)) ? (LPCSTR) *((char **) pRec2->szRecordName) : (LPCSTR) &pRec2->szRecordName[0]; return lstrcmpOEM(puChar1, puChar2); } } int __cdecl CIndexStatic::QCompareD(const void * elem1, const void * elem2) { return -QCompareA(elem1, elem2); } /*!-------------------------------------------------------------------------- Class CIndexOwner ---------------------------------------------------------------------------*/ /*!-------------------------------------------------------------------------- CIndexOwner::BCompare - Author: EricDav ---------------------------------------------------------------------------*/ int CIndexOwner::BCompare(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; if (pRec1->dwOwner > pRec2->dwOwner) { return 1; } else if (pRec1->dwOwner < pRec2->dwOwner) { return -1; } else { // if the addresses are the same, compare names LPCSTR puChar1 = (IS_DBREC_LONGNAME(pRec1)) ? (LPCSTR) *((char **) pRec1->szRecordName) : (LPCSTR) &pRec1->szRecordName[0]; LPCSTR puChar2 = (IS_DBREC_LONGNAME(pRec2)) ? (LPCSTR) *((char **) pRec2->szRecordName) : (LPCSTR) &pRec2->szRecordName[0]; return lstrcmpOEM(puChar1, puChar2); } } int CIndexOwner::BCompareD(const void *elem1, const void *elem2) { return -BCompare(elem1, elem2); } /*!-------------------------------------------------------------------------- CIndexStatic::Sort - Author: EricDav ---------------------------------------------------------------------------*/ HRESULT CIndexOwner::Sort() { if (m_bAscending) qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareA); else qsort(m_hrowArray.GetData(), (size_t)m_hrowArray.GetSize(), sizeof(HROW), QCompareD); return hrOK; } /*!-------------------------------------------------------------------------- CIndexStatic::QCompare - Author: EricDav ---------------------------------------------------------------------------*/ int __cdecl CIndexOwner::QCompareA(const void * elem1, const void * elem2) { LPHROW phrow1 = (LPHROW) elem1; LPHROW phrow2 = (LPHROW) elem2; LPWINSDBRECORD pRec1 = (LPWINSDBRECORD) *phrow1; LPWINSDBRECORD pRec2 = (LPWINSDBRECORD) *phrow2; if (pRec1->dwOwner > pRec2->dwOwner) { return 1; } else if (pRec1->dwOwner < pRec2->dwOwner) { return -1; } else { // if the addresses are the same, compare names LPCSTR puChar1 = (IS_DBREC_LONGNAME(pRec1)) ? (LPCSTR) *((char **) pRec1->szRecordName) : (LPCSTR) &pRec1->szRecordName[0]; LPCSTR puChar2 = (IS_DBREC_LONGNAME(pRec2)) ? (LPCSTR) *((char **) pRec2->szRecordName) : (LPCSTR) &pRec2->szRecordName[0]; return lstrcmpOEM(puChar1, puChar2); } } int __cdecl CIndexOwner::QCompareD(const void * elem1, const void * elem2) { return -QCompareA(elem1, elem2); } HRESULT CFilteredIndexName::AddFilter(WINSDB_FILTER_TYPE FilterType, DWORD dwData1, DWORD dwData2, LPCOLESTR strData3) { HRESULT hr = hrOK; tIpReference ipRef; switch (FilterType) { case WINSDB_FILTER_BY_TYPE: m_mapFilterTypes.SetAt(dwData1, (BOOL&) dwData2); break; case WINSDB_FILTER_BY_OWNER: m_dwaFilteredOwners.Add(dwData1); break; case WINSDB_FILTER_BY_IPADDR: ipRef.Address = dwData1; ipRef.Mask = dwData2; m_taFilteredIp.Add(ipRef); break; case WINSDB_FILTER_BY_NAME: UINT nData3Len; nData3Len = (_tcslen(strData3)+1)*sizeof(TCHAR); m_pchFilteredName = new char[nData3Len]; if (m_pchFilteredName != NULL) { #ifdef _UNICODE if (WideCharToMultiByte(CP_OEMCP, 0, strData3, -1, m_pchFilteredName, nData3Len, NULL, NULL) == 0) { delete m_pchFilteredName; m_pchFilteredName = NULL; } #else CharToOem(strData3, m_pchFilteredName); #endif //m_pchFilteredName = _strupr(m_pchFilteredName); m_bMatchCase = dwData1; } break; default: Panic0("Invalid filter type passed to CFilteredIndexName::AddFilter"); break; } return hr; } BOOL CFilteredIndexName::CheckForFilter(LPHROW hrowCheck) { UINT nCountOwner = (UINT)m_dwaFilteredOwners.GetSize(); UINT nCountType = m_mapFilterTypes.GetHashTableSize(); UINT nCountIPAddrs = (UINT)m_taFilteredIp.GetSize(); BOOL bOwnerFilter = (nCountOwner == 0); BOOL bTypeFilter = (nCountType == 0); BOOL bIPAddrsFilter = (nCountIPAddrs == 0); BOOL bNameFilter = (m_pchFilteredName == NULL); LPWINSDBRECORD pRec = (LPWINSDBRECORD) *hrowCheck; UINT i, j; LPCSTR puChar; for (i = 0; !bOwnerFilter && i < nCountOwner; i++) { if (pRec->dwOwner == m_dwaFilteredOwners.GetAt(i)) bOwnerFilter = TRUE; } if (!bOwnerFilter) return FALSE; puChar = (IS_DBREC_LONGNAME(pRec)) ? (LPCSTR) *((char **) pRec->szRecordName) : (LPCSTR) &pRec->szRecordName[0]; if (!bTypeFilter) { DWORD dwType = puChar[0xF]; if (!m_mapFilterTypes.Lookup(dwType, bTypeFilter)) { // no entry for this name type. Check the FFFF name type (other) to see if we should // show it. dwType = 0xFFFF; m_mapFilterTypes.Lookup(dwType, bTypeFilter); } } if (!bTypeFilter) return FALSE; for (i = 0; !bIPAddrsFilter && i < nCountIPAddrs; i++) { if (pRec->szRecordName[18] & WINSDB_REC_MULT_ADDRS) { LPDWORD pdwIpAddrs = (LPDWORD) pRec->dwIpAdd; for (j=0; !bIPAddrsFilter && j < pdwIpAddrs[0]; j+=2) { bIPAddrsFilter = SubnetMatching(m_taFilteredIp[i], pdwIpAddrs[j+2]); } } else { bIPAddrsFilter = SubnetMatching(m_taFilteredIp[i], (DWORD)pRec->dwIpAdd); } } if(!bIPAddrsFilter) return FALSE; if (!bNameFilter) { bNameFilter = (PatternMatching(puChar, m_pchFilteredName, 16) == NULL); } return bNameFilter; } BOOL CFilteredIndexName::CheckWinsRecordForFilter(WinsRecord *pWinsRecord) { UINT nCountOwner = (UINT)m_dwaFilteredOwners.GetSize(); UINT nCountType = m_mapFilterTypes.GetHashTableSize(); UINT nCountIPAddrs = (UINT)m_taFilteredIp.GetSize(); BOOL bOwnerFilter = (nCountOwner == 0); BOOL bTypeFilter = (nCountType == 0); BOOL bIPAddrsFilter = (nCountIPAddrs == 0); BOOL bNameFilter = (m_pchFilteredName == NULL); UINT i, j; //------------------------------------- // check the owner filter first, if any for (i = 0; !bOwnerFilter && i < nCountOwner; i++) { if (pWinsRecord->dwOwner == m_dwaFilteredOwners.GetAt(i)) bOwnerFilter = TRUE; } if (!bOwnerFilter) return FALSE; //------------------------------------- // check the type filter if any if (!bTypeFilter) { DWORD dwType; // keep in mind the name's type is in the lowest 16 bits of pWinsRecord->dwType // (see WinsIntfToWinsRecord()) dwType = pWinsRecord->dwType & 0x0000ffff; if (!m_mapFilterTypes.Lookup(dwType, bTypeFilter)) { // no entry for this name type. Check the FFFF name type (other) to see if we should // show it. dwType = 0xFFFF; m_mapFilterTypes.Lookup(dwType, bTypeFilter); } } if (!bTypeFilter) return FALSE; //------------------------------------- // check the IP address filter if any for (i = 0; !bIPAddrsFilter && i < nCountIPAddrs; i++) { if (pWinsRecord->dwState & WINSDB_REC_MULT_ADDRS) { for (j=0; !bIPAddrsFilter && j < pWinsRecord->dwNoOfAddrs; j++) { bIPAddrsFilter = SubnetMatching(m_taFilteredIp[i], pWinsRecord->dwIpAdd[j]); } } else { bIPAddrsFilter = SubnetMatching(m_taFilteredIp[i], pWinsRecord->dwIpAdd[0]); } } if(!bIPAddrsFilter) return FALSE; //------------------------------------- // check the name filter if any if (!bNameFilter) { bNameFilter = (PatternMatching(pWinsRecord->szRecordName, m_pchFilteredName, 16) == NULL); } return bNameFilter; } LPCSTR CFilteredIndexName::PatternMatching(LPCSTR pName, LPCSTR pPattern, INT nNameLen) { LPCSTR pNameBak = pName; // it is guaranteed here we have a valid (not NULL) pattern while (*pPattern != '\0' && pName-pNameBak < nNameLen) { BOOL bChMatch = (*pPattern == *pName); if (!m_bMatchCase && !bChMatch) { bChMatch = (islower(*pPattern) && _toupper(*pPattern) == *pName) || (islower(*pName) && *pPattern == _toupper(*pName)); } if (*pPattern == '?' || bChMatch) { pPattern++; } else if (*pPattern == '*') { LPCSTR pTrail = pName; INT nTrailLen = nNameLen-(UINT)(pTrail-pNameBak); pPattern++; while ((pName = PatternMatching(pTrail, pPattern, nTrailLen)) != NULL) { pTrail++; nTrailLen--; if (*pTrail == '\0' || nTrailLen <= 0) break; } return pName; } else if (!bChMatch) { // in the test above, note that even in the unikely case *pName == '\0' // *pName will not match *pPattern so the loop is still broken - which is // the desired behavior. In this case the pattern was not consummed // and the name was, so the return will indicate the matching failed break; } pName++; } return *pPattern == '\0' ? NULL : pName; } BOOL CFilteredIndexName::SubnetMatching(tIpReference &IpRefPattern, DWORD dwIPAddress) { DWORD dwMask; return (IpRefPattern.Address & IpRefPattern.Mask) == (dwIPAddress & IpRefPattern.Mask); } HRESULT CFilteredIndexName::ClearFilter(WINSDB_FILTER_TYPE FilterType) { HRESULT hr = hrOK; switch(FilterType) { case WINSDB_FILTER_BY_TYPE: m_mapFilterTypes.RemoveAll(); break; case WINSDB_FILTER_BY_OWNER: m_dwaFilteredOwners.RemoveAll(); break; case WINSDB_FILTER_BY_IPADDR: m_taFilteredIp.RemoveAll(); break; case WINSDB_FILTER_BY_NAME: if (m_pchFilteredName != NULL) { delete m_pchFilteredName; m_pchFilteredName = NULL; } break; default: Panic0("Invalid filter type passed to CFilteredIndexName::ClearFilter"); break; } return hr; }