windows-nt/Source/XPSP1/NT/ds/security/cryptoapi/pkitrust/mscat32/dbcomp.cpp

1108 lines
30 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+---------------------------------------------------------------------------
//
// Microsoft Windows NT Security
// Copyright (C) Microsoft Corporation, 1997 - 1999
//
// File: dbcomp.cpp
//
// Contents: Hash Database Compactor
//
// History: 9-8-1998 kirtd Created
//
//----------------------------------------------------------------------------
#include <global.hxx>
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::CHashDbCompactor, public
//
// Synopsis: Constructor
//
//----------------------------------------------------------------------------
CHashDbCompactor::CHashDbCompactor ()
{
m_hDbLock = NULL;
m_pwszDbDirectory = NULL;
m_cUniqueCatalogs = 0;
m_cAllocatedUniqueCatalogs = 0;
m_aUniqueCatalogs = NULL;
m_iLastUniqueCatalogFoundByName = 0;
m_pwszTempKeyPath[0] = L'\0';
m_pwszTempDataPath[0] = L'\0';
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::~CHashDbCompactor, public
//
// Synopsis: Destructor
//
//----------------------------------------------------------------------------
CHashDbCompactor::~CHashDbCompactor ()
{
if ( m_hDbLock != NULL )
{
CloseHandle( m_hDbLock );
}
if ( m_pwszTempKeyPath[ 0 ] != L'\0' )
{
DeleteFileU( m_pwszTempKeyPath );
}
if ( m_pwszTempDataPath[ 0 ] != L'\0' )
{
DeleteFileU( m_pwszTempDataPath );
}
delete m_pwszDbDirectory;
delete m_aUniqueCatalogs;
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::Initialize, public
//
// Synopsis: initialize the compactor
//
//----------------------------------------------------------------------------
BOOL
CHashDbCompactor::Initialize (
IN LPCWSTR pwszDbLock,
IN LPCWSTR pwszDbDirectory
)
{
if ( ( m_hDbLock = CreateMutexU( NULL, FALSE, pwszDbLock ) ) == NULL )
{
return( FALSE );
}
m_pwszDbDirectory = new WCHAR [ wcslen( pwszDbDirectory ) + 1 ];
if ( m_pwszDbDirectory != NULL )
{
wcscpy( m_pwszDbDirectory, pwszDbDirectory );
}
else
{
SetLastError( E_OUTOFMEMORY );
return( FALSE );
}
if ( GrowUniqueCatalogs( INITIAL_UNIQUE_CATALOGS ) == FALSE )
{
return( FALSE );
}
assert( m_aUniqueCatalogs != NULL );
assert( m_cAllocatedUniqueCatalogs == INITIAL_UNIQUE_CATALOGS );
if ( ( GetTempFileNameU(
pwszDbDirectory,
L"",
0,
m_pwszTempKeyPath
) == FALSE ) ||
( GetTempFileNameU(
pwszDbDirectory,
L"",
0,
m_pwszTempDataPath
) == FALSE ) )
{
return( FALSE );
}
return( TRUE );
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::LockDatabase, public
//
// Synopsis: lock the database
//
//----------------------------------------------------------------------------
VOID
CHashDbCompactor::LockDatabase ()
{
WaitForSingleObject( m_hDbLock, INFINITE );
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::UnlockDatabase, public
//
// Synopsis: unlock the database
//
//----------------------------------------------------------------------------
VOID
CHashDbCompactor::UnlockDatabase ()
{
ReleaseMutex( m_hDbLock );
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::MapDatabase, public
//
// Synopsis: map the database
//
//----------------------------------------------------------------------------
BOOL
CHashDbCompactor::MapDatabase (
IN LPCWSTR pwszDbName,
OUT PCRYPT_DATA_BLOB pKey,
OUT LPWSTR* ppwszKeyPath,
OUT PCRYPT_DATA_BLOB pData,
OUT LPWSTR* ppwszDataPath
)
{
BOOL fResult = TRUE;
LPWSTR pwszKeyDbPath = NULL;
LPWSTR pwszDataDbPath = NULL;
DWORD cwDirectory = 0;
DWORD cwName = 0;
HANDLE hKeyFile = INVALID_HANDLE_VALUE;
HANDLE hDataFile = INVALID_HANDLE_VALUE;
HANDLE hMappedKeyFile = NULL;
HANDLE hMappedDataFile = NULL;
LPBYTE pbKey = NULL;
LPBYTE pbData = NULL;
DWORD cwKeyExt = 0;
DWORD cwDataExt = 0;
DWORD cbKeyFileSize = 0;
DWORD cbDataFileSize = 0;
cwDirectory = wcslen( m_pwszDbDirectory );
cwName = wcslen( pwszDbName );
cwKeyExt = wcslen( DB_KEY_EXT );
cwDataExt = wcslen( DB_DATA_EXT );
pwszKeyDbPath = new WCHAR [ cwDirectory + cwName + cwKeyExt + 2 ];
pwszDataDbPath = new WCHAR [ cwDirectory + cwName + cwDataExt + 2 ];
if ( ( pwszKeyDbPath != NULL ) && ( pwszDataDbPath != NULL ) )
{
wcscpy( pwszKeyDbPath, m_pwszDbDirectory );
wcscat( pwszKeyDbPath, L"\\" );
wcscat( pwszKeyDbPath, pwszDbName );
wcscpy( pwszDataDbPath, pwszKeyDbPath );
wcscat( pwszKeyDbPath, DB_KEY_EXT );
wcscat( pwszDataDbPath, DB_DATA_EXT );
}
else
{
SetLastError( E_OUTOFMEMORY );
fResult = FALSE;
}
if ( fResult == TRUE )
{
DWORD dwErr = 0;
hKeyFile = CreateFileU(
pwszKeyDbPath,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hKeyFile == INVALID_HANDLE_VALUE)
{
dwErr = GetLastError();
}
hDataFile = CreateFileU(
pwszDataDbPath,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if (hDataFile == INVALID_HANDLE_VALUE)
{
dwErr = GetLastError();
}
if ( ( hKeyFile != INVALID_HANDLE_VALUE ) &&
( hDataFile != INVALID_HANDLE_VALUE ) )
{
cbKeyFileSize = GetFileSize( hKeyFile, NULL );
cbDataFileSize = GetFileSize( hDataFile, NULL );
if ( cbKeyFileSize > 0 )
{
hMappedKeyFile = CreateFileMapping(
hKeyFile,
NULL,
PAGE_READONLY,
0,
0,
NULL
);
}
if ( cbDataFileSize > 0 )
{
hMappedDataFile = CreateFileMapping(
hDataFile,
NULL,
PAGE_READONLY,
0,
0,
NULL
);
}
}
if ( hMappedKeyFile != NULL )
{
pbKey = (LPBYTE)MapViewOfFile(
hMappedKeyFile,
FILE_MAP_READ,
0,
0,
0
);
}
if ( hMappedDataFile != NULL )
{
pbData = (LPBYTE)MapViewOfFile(
hMappedDataFile,
FILE_MAP_READ,
0,
0,
0
);
}
if ( ( ( pbKey == NULL ) && ( cbKeyFileSize != 0 ) ) ||
( ( pbData == NULL ) && ( cbDataFileSize != 0 ) ) )
{
fResult = FALSE;
}
}
if ( fResult == TRUE )
{
pKey->cbData = cbKeyFileSize;
pKey->pbData = pbKey;
*ppwszKeyPath = pwszKeyDbPath;
pData->cbData = cbDataFileSize;
pData->pbData = pbData;
*ppwszDataPath = pwszDataDbPath;
}
else
{
delete pwszKeyDbPath;
delete pwszDataDbPath;
}
if ( hKeyFile != INVALID_HANDLE_VALUE )
{
CloseHandle( hKeyFile );
}
if ( hDataFile != INVALID_HANDLE_VALUE )
{
CloseHandle( hDataFile );
}
if ( hMappedKeyFile != NULL )
{
CloseHandle( hMappedKeyFile );
}
if ( hMappedDataFile != NULL )
{
CloseHandle( hMappedDataFile );
}
return( fResult );
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::UnmapDatabase, public
//
// Synopsis: unmap the database
//
//----------------------------------------------------------------------------
VOID
CHashDbCompactor::UnmapDatabase (
IN PCRYPT_DATA_BLOB pKey,
IN PCRYPT_DATA_BLOB pData
)
{
FlushCompactionAnalysis();
if ( pKey->pbData != NULL )
{
UnmapViewOfFile( pKey->pbData );
}
if ( pData->pbData != NULL )
{
UnmapViewOfFile( pData->pbData );
}
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::AnalyzeDataForCompaction, public
//
// Synopsis: analyze the database data for compaction
//
//----------------------------------------------------------------------------
BOOL
CHashDbCompactor::AnalyzeDataForCompaction (
IN PCRYPT_DATA_BLOB pData,
IN OPTIONAL LPCSTR pszUnwantedCatalog
)
{
BOOL fResult = TRUE;
HashMastRec* pHashMastRecord;
DWORD cbToNextRecord;
DWORD cRecord;
DWORD cCount;
PUNIQUE_CATALOG pUniqueCatalog;
if ( m_cUniqueCatalogs > 0 )
{
if ( FlushCompactionAnalysis() == FALSE )
{
return( FALSE );
}
}
pHashMastRecord = (HashMastRec *)(
pData->pbData + BFILE_HEADERSIZE + sizeof( DWORD )
);
cbToNextRecord = sizeof( HashMastRec ) + sizeof( DWORD );
if ( pData->cbData < BFILE_HEADERSIZE )
{
cRecord = 0;
}
else
{
cRecord = ( pData->cbData - BFILE_HEADERSIZE ) / cbToNextRecord;
}
for ( cCount = 0; ( fResult == TRUE ) && ( cCount < cRecord ); cCount++ )
{
if ( ( pszUnwantedCatalog == NULL ) ||
( _strnicmp(
pHashMastRecord->CatName,
pszUnwantedCatalog,
MAX_PATH
) != 0 ) )
{
pUniqueCatalog = FindUniqueCatalogByName(
pHashMastRecord->CatName
);
if ( ( pUniqueCatalog == NULL ) &&
( CatalogFileExists(
pHashMastRecord->CatName,
MAX_PATH
) == TRUE ) )
{
fResult = AddUniqueCatalog( pHashMastRecord );
}
}
pHashMastRecord = (HashMastRec *)(
(LPBYTE)pHashMastRecord + cbToNextRecord
);
}
return( fResult );
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::FlushCompactionAnalysis, public
//
// Synopsis: flush the last compaction analysis done
//
//----------------------------------------------------------------------------
BOOL
CHashDbCompactor::FlushCompactionAnalysis ()
{
DWORD cAllocatedUniqueCatalogs;
DWORD cUniqueCatalogs;
PUNIQUE_CATALOG aUniqueCatalogs;
if ( m_cAllocatedUniqueCatalogs == INITIAL_UNIQUE_CATALOGS )
{
m_cUniqueCatalogs = 0;
m_iLastUniqueCatalogFoundByName = 0;
return( TRUE );
}
aUniqueCatalogs = m_aUniqueCatalogs;
cUniqueCatalogs = m_cUniqueCatalogs;
cAllocatedUniqueCatalogs = m_cAllocatedUniqueCatalogs;
m_aUniqueCatalogs = NULL;
m_cUniqueCatalogs = 0;
m_cAllocatedUniqueCatalogs = 0;
if ( GrowUniqueCatalogs( INITIAL_UNIQUE_CATALOGS ) == FALSE )
{
m_aUniqueCatalogs = aUniqueCatalogs;
m_cUniqueCatalogs = cUniqueCatalogs;
m_cAllocatedUniqueCatalogs = cAllocatedUniqueCatalogs;
return( FALSE );
}
delete aUniqueCatalogs;
m_iLastUniqueCatalogFoundByName = 0;
return( TRUE );
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::WriteCompactedDatabase, public
//
// Synopsis: write the compacted database
//
//----------------------------------------------------------------------------
BOOL
CHashDbCompactor::WriteCompactedDatabase (
IN PCRYPT_DATA_BLOB pKey,
IN PCRYPT_DATA_BLOB pData,
IN OPTIONAL LPCSTR pszUnwantedCatalog
)
{
BOOL fResult = FALSE;
HANDLE hFile;
HANDLE hDataFile;
HANDLE hMap;
DWORD cCount;
DWORD cbSize;
LPBYTE pbDataFile = NULL;
LPBYTE pbFile = NULL;
HashMastRec* pHashMastRecord;
PUNIQUE_CATALOG pUniqueCatalog;
LPDWORD pdw;
DWORD RecordId;
DWORD cKey;
LPBYTE pbKey;
LPBYTE pb;
BFILE_HEADER* pHeader = NULL;
hDataFile = CreateFileU(
m_pwszTempDataPath,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if ( hDataFile == INVALID_HANDLE_VALUE )
{
return( FALSE );
}
cbSize = ( sizeof( DWORD ) + sizeof( HashMastRec ) ) * m_cUniqueCatalogs;
cbSize += BFILE_HEADERSIZE;
if ( SetFilePointer( hDataFile, cbSize, NULL, FILE_BEGIN ) != 0xFFFFFFFF )
{
fResult = SetEndOfFile( hDataFile );
}
if ( fResult == TRUE )
{
if ( ( hMap = CreateFileMapping(
hDataFile,
NULL,
PAGE_READWRITE,
0,
0,
NULL
) ) != NULL )
{
pbDataFile = (LPBYTE)MapViewOfFile( hMap, FILE_MAP_WRITE, 0, 0, 0 );
CloseHandle( hMap );
}
if ( pbDataFile != NULL )
{
memcpy( pbDataFile, BFILE_SIG, BFILE_SIZEOFSIG );
pHeader = (BFILE_HEADER *)( pbDataFile + BFILE_SIZEOFSIG );
memset( pHeader, 0, sizeof( BFILE_HEADER ) );
pHeader->sVersion = BFILE_VERSION_1;
pHeader->sIntVersion = CATDB_VERSION_1;
pHeader->cbKey = KEY_SIZE;
pHeader->cbData = sizeof( HashMastRec );
}
else
{
fResult = FALSE;
}
}
pdw = (LPDWORD)( pbDataFile + BFILE_HEADERSIZE );
pHashMastRecord = (HashMastRec *)( (LPBYTE)pdw + sizeof( DWORD ) );
for ( cCount = 0;
( cCount < m_cUniqueCatalogs ) && ( fResult == TRUE );
cCount++ )
{
RecordId = cCount + 1;
memcpy( pdw, &RecordId, sizeof( DWORD ) );
memcpy(
pHashMastRecord,
&m_aUniqueCatalogs[ cCount ].HashDbRecord,
sizeof( HashMastRec )
);
pdw = (LPDWORD)(
(LPBYTE)pdw + sizeof( HashMastRec ) + sizeof( DWORD )
);
pHashMastRecord = (HashMastRec *)( (LPBYTE)pdw + sizeof( DWORD ) );
}
if ( fResult == FALSE )
{
if ( pbDataFile != NULL )
{
UnmapViewOfFile( pbDataFile );
}
CloseHandle( hDataFile );
return( FALSE );
}
fResult = FALSE;
pbFile = NULL;
hFile = CreateFileU(
m_pwszTempKeyPath,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if ( hFile == INVALID_HANDLE_VALUE )
{
UnmapViewOfFile( pbDataFile );
CloseHandle( hDataFile );
return( FALSE );
}
if ( SetFilePointer( hFile, pKey->cbData, NULL, FILE_BEGIN ) != 0xFFFFFFFF )
{
fResult = SetEndOfFile( hFile );
}
if ( ( fResult == TRUE ) && ( pKey->cbData > 0 ) )
{
if ( ( hMap = CreateFileMapping(
hFile,
NULL,
PAGE_READWRITE,
0,
0,
NULL
) ) != NULL )
{
pbFile = (LPBYTE)MapViewOfFile( hMap, FILE_MAP_WRITE, 0, 0, 0 );
CloseHandle( hMap );
}
if ( pbFile == NULL )
{
fResult = FALSE;
}
}
cKey = pKey->cbData / KEY_RECORD_SIZE;
pdw = (LPDWORD)( pKey->pbData + KEY_SIZE );
pbKey = pKey->pbData;
pb = pbFile;
RecordId = 0;
__try
{
for ( cCount = 0; ( cCount < cKey ) && ( fResult == TRUE ); cCount++ )
{
if ( ( *pdw + sizeof( HashMastRec ) + sizeof( DWORD ) ) <= pData->cbData )
{
pHashMastRecord = (HashMastRec *)(
pData->pbData + *pdw + sizeof( DWORD )
);
if ( ( pszUnwantedCatalog == NULL ) ||
( _strnicmp(
pHashMastRecord->CatName,
pszUnwantedCatalog,
MAX_PATH
) != 0 ) )
{
pUniqueCatalog = FindUniqueCatalogByName(
pHashMastRecord->CatName
);
if ( pUniqueCatalog == NULL )
{
pdw = (LPDWORD)( (LPBYTE)pdw + KEY_RECORD_SIZE );
pbKey += KEY_RECORD_SIZE;
continue;
}
memcpy(
pb,
pbKey,
KEY_SIZE
);
pb += KEY_SIZE;
memcpy(
pb,
(LPBYTE)&pUniqueCatalog->UniqueOffset,
sizeof( DWORD )
);
pb += sizeof( DWORD );
RecordId += 1;
}
}
pdw = (LPDWORD)( (LPBYTE)pdw + KEY_RECORD_SIZE );
pbKey += KEY_RECORD_SIZE;
}
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
SetLastError( GetExceptionCode() );
fResult = FALSE;
}
if ( pbFile != NULL )
{
UnmapViewOfFile( pbFile );
}
if ( fResult == TRUE )
{
cbSize = RecordId * KEY_RECORD_SIZE;
pHeader->cbSortedEOF = cbSize;
pHeader->dwLastRecNum = ( RecordId > 0 ) ? ( RecordId - 1 ) : 0;
pHeader->fDirty = FALSE;
if ( SetFilePointer( hFile, cbSize, NULL, FILE_BEGIN ) != 0xFFFFFFFF )
{
fResult = SetEndOfFile( hFile );
}
}
UnmapViewOfFile( pbDataFile );
CloseHandle( hDataFile );
CloseHandle( hFile );
return( fResult );
}
BOOL MyMoveFileEx(
LPCWSTR lpExistingFileName,
LPCWSTR lpNewFileName,
DWORD dwFlags
)
{
BYTE rgbExisting[_MAX_PATH];
BYTE rgbNew[_MAX_PATH];
char * szExisting = NULL;
char * szNew = NULL;
BOOL bResult = FALSE;
if (FIsWinNT())
{
return(MoveFileExW(lpExistingFileName, lpNewFileName, dwFlags));
}
if ((MkMBStr(rgbExisting, _MAX_PATH, lpExistingFileName, &szExisting)) &&
(MkMBStr(rgbNew, _MAX_PATH, lpNewFileName, &szNew)))
{
bResult = DeleteFile(szNew);
if (bResult)
{
bResult = MoveFileA(szExisting, szNew);
}
}
FreeMBStr(rgbExisting, szExisting);
FreeMBStr(rgbNew, szNew);
return (bResult);
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::CommitCompactedDatabase, public
//
// Synopsis: commit the compacted database
//
//----------------------------------------------------------------------------
BOOL
CHashDbCompactor::CommitCompactedDatabase (
IN LPCWSTR pwszFinalKeyPath,
IN LPCWSTR pwszFinalDataPath
)
{
DWORD dwErr = 0;
if ( MyMoveFileEx(
m_pwszTempKeyPath,
pwszFinalKeyPath,
MOVEFILE_COPY_ALLOWED |
MOVEFILE_REPLACE_EXISTING |
MOVEFILE_WRITE_THROUGH
) == FALSE )
{
dwErr = GetLastError();
return( FALSE );
}
return( MyMoveFileEx(
m_pwszTempDataPath,
pwszFinalDataPath,
MOVEFILE_COPY_ALLOWED |
MOVEFILE_REPLACE_EXISTING |
MOVEFILE_WRITE_THROUGH
) );
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::FreeString, public
//
// Synopsis: free allocated string
//
//----------------------------------------------------------------------------
VOID
CHashDbCompactor::FreeString (IN LPWSTR pwsz)
{
delete pwsz;
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::GrowUniqueCatalogs, public
//
// Synopsis: grow the unique catalogs array
//
//----------------------------------------------------------------------------
BOOL
CHashDbCompactor::GrowUniqueCatalogs (DWORD cGrow)
{
BOOL fResult = FALSE;
DWORD cAllocatedUniqueCatalogs;
PUNIQUE_CATALOG aUniqueCatalogs;
cAllocatedUniqueCatalogs = m_cAllocatedUniqueCatalogs + cGrow;
aUniqueCatalogs = new UNIQUE_CATALOG [ cAllocatedUniqueCatalogs ];
if ( aUniqueCatalogs == NULL )
{
SetLastError( E_OUTOFMEMORY );
return( FALSE );
}
memset(
aUniqueCatalogs,
0,
sizeof( UNIQUE_CATALOG ) * cAllocatedUniqueCatalogs
);
if ( m_aUniqueCatalogs != NULL )
{
memcpy(
aUniqueCatalogs,
m_aUniqueCatalogs,
m_cUniqueCatalogs * sizeof( UNIQUE_CATALOG )
);
delete m_aUniqueCatalogs;
}
m_cAllocatedUniqueCatalogs = cAllocatedUniqueCatalogs;
m_aUniqueCatalogs = aUniqueCatalogs;
return( TRUE );
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::FindUniqueCatalogByName, public
//
// Synopsis: find a unique catalog entry given a catalog name
//
//----------------------------------------------------------------------------
PUNIQUE_CATALOG
CHashDbCompactor::FindUniqueCatalogByName (LPCSTR pszCatalogName)
{
DWORD cCount;
if ( ( m_iLastUniqueCatalogFoundByName < m_cUniqueCatalogs ) &&
( _strnicmp(
m_aUniqueCatalogs[ m_iLastUniqueCatalogFoundByName ].HashDbRecord.CatName,
pszCatalogName,
MAX_PATH
) == 0 ) )
{
return( &m_aUniqueCatalogs[ m_iLastUniqueCatalogFoundByName ] );
}
for ( cCount = 0; cCount < m_cUniqueCatalogs; cCount++ )
{
if ( _strnicmp(
m_aUniqueCatalogs[ cCount ].HashDbRecord.CatName,
pszCatalogName,
MAX_PATH
) == 0 )
{
m_iLastUniqueCatalogFoundByName = cCount;
return( &m_aUniqueCatalogs[ cCount ] );
}
}
return( NULL );
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::AddUniqueCatalog, public
//
// Synopsis: add a unique catalog to the array
//
//----------------------------------------------------------------------------
BOOL
CHashDbCompactor::AddUniqueCatalog (HashMastRec* pHashMastRecord)
{
DWORD UniqueOffset;
if ( m_cUniqueCatalogs == m_cAllocatedUniqueCatalogs )
{
if ( GrowUniqueCatalogs( GROW_UNIQUE_CATALOGS ) == FALSE )
{
return( FALSE );
}
}
UniqueOffset = ( m_cUniqueCatalogs * (
sizeof( HashMastRec ) + sizeof( DWORD )
) ) + BFILE_HEADERSIZE;
m_aUniqueCatalogs[ m_cUniqueCatalogs ].HashDbRecord = *pHashMastRecord;
m_aUniqueCatalogs[ m_cUniqueCatalogs ].UniqueOffset = UniqueOffset;
m_cUniqueCatalogs += 1;
return( TRUE );
}
//+---------------------------------------------------------------------------
//
// Member: CHashDbCompactor::CatalogFileExists, public
//
// Synopsis: check if the catalog file exists in the database directory
//
//----------------------------------------------------------------------------
BOOL
CHashDbCompactor::CatalogFileExists (LPCSTR pszCatalogName, DWORD cbName)
{
BOOL fResult = FALSE;
WCHAR pwszFile[ MAX_PATH ];
WCHAR pwszPath[ MAX_PATH ];
HANDLE hFile;
if ( MultiByteToWideChar(
CP_ACP,
0,
pszCatalogName,
cbName,
pwszFile,
MAX_PATH
) == 0 )
{
return( FALSE );
}
if ( ( wcslen( m_pwszDbDirectory ) + wcslen( pwszFile ) + 2 ) > MAX_PATH )
{
return( FALSE );
}
wcscpy( pwszPath, m_pwszDbDirectory );
wcscat( pwszPath, L"\\" );
wcscat( pwszPath, pwszFile );
if ( ( hFile = CreateFileU(
pwszPath,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
) ) != INVALID_HANDLE_VALUE )
{
CloseHandle( hFile );
fResult = TRUE;
}
return( fResult );
}
//+---------------------------------------------------------------------------
//
// Function: CatalogCompactHashDatabase
//
// Synopsis: API for compacting the catalog hash database
//
//----------------------------------------------------------------------------
BOOL WINAPI
CatalogCompactHashDatabase (
IN LPCWSTR pwszDbLock,
IN LPCWSTR pwszDbDirectory,
IN LPCWSTR pwszDbName,
IN OPTIONAL LPCWSTR pwszUnwantedCatalog
)
{
BOOL fResult;
CHashDbCompactor HashDbCompactor;
LPWSTR pwszKeyPath = NULL;
LPWSTR pwszDataPath = NULL;
CRYPT_DATA_BLOB KeyMap;
CRYPT_DATA_BLOB DataMap;
BOOL fDatabaseMapped = FALSE;
CHAR szUnwantedCatalog[ MAX_PATH + 1 ];
LPSTR pszUnwantedCatalog = NULL;
if ( pwszUnwantedCatalog != NULL )
{
pszUnwantedCatalog = szUnwantedCatalog;
if ( WideCharToMultiByte(
CP_ACP,
0,
pwszUnwantedCatalog,
-1,
pszUnwantedCatalog,
MAX_PATH,
NULL,
NULL
) == FALSE )
{
return( FALSE );
}
}
fResult = HashDbCompactor.Initialize( pwszDbLock, pwszDbDirectory );
if ( fResult == FALSE )
{
return( FALSE );
}
HashDbCompactor.LockDatabase();
__try
{
fResult = HashDbCompactor.MapDatabase(
pwszDbName,
&KeyMap,
&pwszKeyPath,
&DataMap,
&pwszDataPath
);
if ( fResult == TRUE )
{
fDatabaseMapped = TRUE;
fResult = HashDbCompactor.AnalyzeDataForCompaction(
&DataMap,
pszUnwantedCatalog
);
}
if ( fResult == TRUE )
{
fResult = HashDbCompactor.WriteCompactedDatabase(
&KeyMap,
&DataMap,
pszUnwantedCatalog
);
}
if ( fDatabaseMapped == TRUE )
{
HashDbCompactor.UnmapDatabase( &KeyMap, &DataMap );
}
if ( fResult == TRUE )
{
fResult = HashDbCompactor.CommitCompactedDatabase(
pwszKeyPath,
pwszDataPath
);
}
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
SetLastError( GetExceptionCode() );
fResult = FALSE;
}
HashDbCompactor.UnlockDatabase();
if ( pwszKeyPath != NULL )
{
HashDbCompactor.FreeString( pwszKeyPath );
}
if ( pwszDataPath != NULL )
{
HashDbCompactor.FreeString( pwszDataPath );
}
return( fResult );
}