|
|
//++
//
// Copyright (c) 1999 Microsoft Corporation
//
// Module Name:
// hashlist.cpp
//
// Abstract:
// Used for creating hash list blobs.
//
// Revision History:
// Eugene Mesgar (eugenem) 6/16/99
// created
// Kanwaljit Marok (kmaork ) 6/07/99
// modified and ported to NT
//
//--
#include "flstructs.h"
#include "flhashlist.h"
#include "commonlibh.h"
#ifdef THIS_FILE
#undef THIS_FILE
#endif
static char __szTraceSourceFile[] = __FILE__;
#define THIS_FILE __szTraceSourceFile
#define TRACE_FILEID 0
#define FILEID 0
#define SAFEDELETE(p) if (p) { HeapFree( m_hHeapToUse, 0, p); p = NULL;} else ;
CFLHashList::CFLHashList() { m_pBasePointer = NULL; m_pListHeader = NULL; m_paHashArray = NULL; m_pBlobHeader = NULL;
m_lNumElements = m_ilOpenEntry = 0; m_dwSize = 0; m_ilOpenEntry = 0; m_hHeapToUse = GetProcessHeap(); }
CFLHashList::CFLHashList(HANDLE hHeap ) {
m_pBasePointer = NULL; m_pListHeader = NULL; m_paHashArray = NULL; m_pBlobHeader = NULL;
m_lNumElements = m_ilOpenEntry = 0; m_dwSize = 0; m_ilOpenEntry = 0; m_hHeapToUse = hHeap; }
CFLHashList::~CFLHashList() { CleanUpMemory(); }
BOOL CFLHashList::CleanUpMemory() { if( m_pBasePointer ) { HeapFree( m_hHeapToUse, 0, m_pBasePointer ); m_pBasePointer = NULL; }
m_dwSize = 0; m_ilOpenEntry = 0; m_lNumElements = 0; m_pBasePointer = NULL; m_pBlobHeader = NULL; m_paHashArray = NULL; m_pListHeader = NULL; return(TRUE); }
//
// Init function.. allocates memory, sets up base structures
//
BOOL CFLHashList::Init( LONG lNumNodes, DWORD dwNumChars) { DWORD dwBlobSize; DWORD dwNumBuckets=0;
TraceFunctEnter("CFLHashList::Init");
//
// Get the number of buckets we need
//
dwNumBuckets = GetNextHighestPrime( lNumNodes );
//
// We add 1 to NumNodes since the vxddat ignores node index since
// in the hashtable index 0 is null.
//
lNumNodes++;
//
// header
// size for dynmaic hash buckets
// list entries physical data
//
dwBlobSize = sizeof( ListHeader ) + ( sizeof(DWORD) * dwNumBuckets ) + ( sizeof(ListEntry) * (lNumNodes) ) + ( dwNumChars*sizeof(WCHAR)) + ( sizeof(WCHAR)*(lNumNodes-1)) ; if( m_pBasePointer ) { if( CleanUpMemory() == FALSE ) { DebugTrace(FILEID, "Error cleaning up memory.",0); goto cleanup; } }
if( (m_pBasePointer = HeapAlloc( m_hHeapToUse, 0, dwBlobSize ) ) == NULL ) { DebugTrace(FILEID, "Error allocating memory.", 0); goto cleanup; }
memset(m_pBasePointer, 0, dwBlobSize );
m_pBlobHeader = (BlobHeader *) m_pBasePointer; m_pListHeader = (ListHeader *) m_pBasePointer; m_pNodeIndex = (ListEntry *) ( (BYTE *) m_pBasePointer + sizeof( ListHeader ) + ( sizeof(DWORD) * dwNumBuckets ) ); m_paHashArray = (DWORD *) ( (BYTE *) m_pBasePointer + sizeof( ListHeader ));
m_pBlobHeader->m_dwBlbType = BLOB_TYPE_HASHLIST; m_pBlobHeader->m_dwVersion = BLOB_VERSION_NUM; m_pBlobHeader->m_dwMagicNum= BLOB_MAGIC_NUM ; m_pBlobHeader->m_dwEntries = lNumNodes - 1; // actual entries is one less
m_pBlobHeader->m_dwMaxSize = dwBlobSize;
m_pListHeader->m_dwDataOff = sizeof(ListHeader) + ( sizeof(DWORD) * dwNumBuckets ) + ( sizeof(ListEntry) * lNumNodes ); m_pListHeader->m_iHashBuckets = dwNumBuckets;
m_dwSize = dwBlobSize; m_ilOpenEntry = 1; m_lNumElements = lNumNodes; TraceFunctLeave(); return(TRUE);
cleanup: SAFEDELETE( m_pBasePointer ); TraceFunctLeave(); return( FALSE ); }
//
// is prime? these functions can be optimized i bet
//
BOOL CFLHashList::IsPrime( DWORD dwNumber) { DWORD cdw;
//
// prevent divide by 0 problems
//
if( dwNumber == 0 ) { return FALSE; }
if( dwNumber == 1 ) { return TRUE; } for(cdw = 2;cdw < dwNumber;cdw++) { if( (dwNumber % cdw ) == 0 ) { return FALSE; }
}
return TRUE; }
//
// get the next prime number
//
DWORD CFLHashList::GetNextHighestPrime( DWORD dwNumber ) { LONG clLoop;
if( dwNumber >= LARGEST_HASH_SIZE ) { return( LARGEST_HASH_SIZE ); } for( clLoop = dwNumber; clLoop < LARGEST_HASH_SIZE;clLoop++) { if( IsPrime( clLoop ) ) { return( clLoop ); } }
// nothing found, return large hash size.
return( LARGEST_HASH_SIZE ); }
//
// Adds a file to the hashed list
//
BOOL CFLHashList::AddFile(LPTSTR szFile, TCHAR chType) { BYTE abBuf[1024]; LONG lPeSize, lHashIndex, lNodeNum; ListEntry *pEntry;
TraceFunctEnter("CFLHashList::AddFile");
if( (lPeSize = CreatePathElem( szFile, abBuf )) == 0 ) { DebugTrace(FILEID,"Error creating PathElement",0); goto cleanup; }
if( m_ilOpenEntry == m_lNumElements ) { DebugTrace(FILEID,"Too many elements in HashList.",0); goto cleanup; }
if( (ULONG) lPeSize > ( m_dwSize - m_pListHeader->m_dwDataOff ) ) { DebugTrace(FILEID,"Insuffienct space left in data section",0); goto cleanup; }
//
// get a new node
//
lNodeNum = m_ilOpenEntry++;
//
// m_pNodeIndex is the base pointer to all file nodes
//
pEntry = m_pNodeIndex + lNodeNum;
pEntry->m_dwDataLen = lPeSize; pEntry->m_dwData = m_pListHeader->m_dwDataOff; //
// move global data offset.
//
m_pListHeader->m_dwDataOff += lPeSize; //
// copy the entry into our data space
//
memcpy( (BYTE *) m_pBasePointer + pEntry->m_dwData, abBuf, lPeSize );
//
// hash the name and add it to the linked lsit
//
lHashIndex = HASH( (BYTE *) m_pListHeader, (PathElement *) abBuf );
pEntry->m_iNext = m_paHashArray[lHashIndex]; m_paHashArray[lHashIndex] = lNodeNum;
//
// set the type.
//
if( chType == _TEXT('i') || chType == _TEXT('I') ) pEntry->m_dwType = NODE_TYPE_INCLUDE; else if( chType == _TEXT('e') || chType == _TEXT('E') ) pEntry->m_dwType = NODE_TYPE_EXCLUDE; else pEntry->m_dwType = NODE_TYPE_UNKNOWN; TraceFunctLeave(); return(TRUE); cleanup:
TraceFunctLeave(); return(FALSE); }
//
// Helper to convert path elements
//
DWORD CFLHashList::CreatePathElem( LPTSTR pszData, BYTE *pbLargeBuffer ) { int cbLen, i; DWORD dwReturn=0; PathElement *pElem = (PathElement *)pbLargeBuffer;
TraceFunctEnter("CFLHashList::CreatePathElem");
if( NULL == pszData ) { ErrorTrace(FILEID, "NULL pszData sent to CreatePathElem",0); goto cleanup; }
cbLen = _tcslen(pszData);
//
// Add on to cbLen for LENGH char in prefixed strings.
//
pElem->pe_length = (USHORT) (cbLen+1)*sizeof(USHORT);
//
// if we're not in unicode, lets make sure the high bits are clean
// Add sizeof(USHORT) to pElem offset to move past length char.
//
memset( pElem + sizeof(USHORT), 0, cbLen*2);
#ifndef UNICODE
if( !MultiByteToWideChar( GetCurrentCodePage(), 0, pszData, -1, pElem->pe_unichars, //move right 2 bytes past the length prefix
MAX_BUFFER) ) { DWORD dwError; dwError = GetLastError(); ErrorTrace(FILEID, "Error converting to Wide char ec-%d",dwError); goto cleanup; } #else
RtlCopyMemory( pElem->pe_unichars, pszData, cbLen*sizeof(WCHAR) ); #endif
dwReturn = pElem->pe_length; cleanup:
TraceFunctLeave(); return dwReturn; }
DWORD CFLHashList::GetSize() { return( m_dwSize ); }
LPVOID CFLHashList::GetBasePointer() { return( m_pBasePointer ); }
|