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.
403 lines
8.5 KiB
403 lines
8.5 KiB
//++
|
|
//
|
|
// 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 );
|
|
}
|
|
|
|
|