|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: cBFile.cpp
//
// Contents: Microsoft Internet Security
//
// History: 24-Oct-1997 pberkman created
//
//--------------------------------------------------------------------------
#include "global.hxx"
#include "stack.hxx"
#include "cbfile.hxx"
cBFile_::cBFile_(CRITICAL_SECTION *pCriticalSection, WCHAR *pwszBFilePath, WCHAR *pwszBFileBaseName, DWORD cbKey, DWORD cbData, SHORT sVersion, BOOL *pfCreatedOK) { SECURITY_ATTRIBUTES sa; SECURITY_ATTRIBUTES* psa = NULL; SECURITY_DESCRIPTOR sd;
SID_IDENTIFIER_AUTHORITY siaWorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY; PSID psidEveryone = NULL; DWORD dwAclSize; PACL pDacl = NULL; DWORD dwErr = 0;
pCritical = pCriticalSection; fDirty = FALSE; fReadOnly = FALSE; hKFile = INVALID_HANDLE_VALUE; hDFile = INVALID_HANDLE_VALUE; pbKMap = NULL; pbDMap = NULL; cbDMap = 0; hDMutex = NULL;
fUseRecNumAsKey = FALSE;
*pfCreatedOK = TRUE; // will be set to FALSE in case of ANY failure
pwszPath = NULL; pwszBaseName = NULL;
__try {
pwszPath = (LPWSTR) new WCHAR[wcslen(pwszBFilePath) + 1]; if (pwszPath == NULL) { goto MemoryError; } wcscpy(pwszPath, pwszBFilePath);
pwszBaseName = (LPWSTR) new WCHAR[wcslen(pwszBFileBaseName) + 1]; if (pwszBaseName == NULL) { goto MemoryError; } wcscpy(pwszBaseName, pwszBFileBaseName);
memset(&sHeader, 0x00, sizeof(BFILE_HEADER)); memset(&sRecord, 0x00, sizeof(BFILE_RECORD));
sHeader.sIntVersion = BFILE_VERSION_1; sHeader.sVersion = (DWORD)sVersion; sHeader.cbKey = cbKey; sHeader.cbData = cbData;
if ( FIsWinNT() == TRUE ) { if (!AllocateAndInitializeSid( &siaWorldSidAuthority, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &psidEveryone)) { goto ErrorReturn; }
//
// compute size of ACL
//
dwAclSize = sizeof(ACL) + ( sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) ) + GetLengthSid(psidEveryone);
//
// allocate storage for Acl
//
if (NULL == (pDacl = (PACL) new BYTE[dwAclSize])) { goto MemoryError; }
if (!InitializeAcl(pDacl, dwAclSize, ACL_REVISION)) { goto ErrorReturn; }
if (!AddAccessAllowedAce( pDacl, ACL_REVISION, SYNCHRONIZE,// | MUTEX_MODIFY_STATE,
psidEveryone)) { goto ErrorReturn; }
if ( InitializeSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION ) == FALSE ) { goto ErrorReturn; }
if ( SetSecurityDescriptorDacl( &sd, TRUE, pDacl, FALSE ) == FALSE ) { goto ErrorReturn; }
sa.nLength = sizeof( SECURITY_ATTRIBUTES ); sa.lpSecurityDescriptor = &sd; sa.bInheritHandle = FALSE;
psa = &sa; }
hDMutex = CreateMutexU( psa, FALSE, pwszBFileBaseName ); if ( hDMutex == NULL ) { hDMutex = OpenMutexU( SYNCHRONIZE, FALSE, pwszBFileBaseName ); if ( hDMutex == NULL ) { dwErr = GetLastError(); goto ErrorReturn; } }
fInitialized = TRUE; // set it now becuase OpenFiles uses "Lock".
if (!(this->OpenFiles())) { goto FileError; }
} // __try
__except(EXCEPTION_EXECUTE_HANDLER) { if (pbKMap != NULL) { UnmapViewOfFile(pbKMap); pbKMap = NULL; }
if (pbDMap != NULL) { UnmapViewOfFile(pbDMap); pbDMap = NULL; }
if (hDFile != INVALID_HANDLE_VALUE) { CloseHandle(hDFile); hDFile = INVALID_HANDLE_VALUE; }
if (hKFile != INVALID_HANDLE_VALUE) { CloseHandle(hKFile); hKFile = INVALID_HANDLE_VALUE; }
if (hDMutex != NULL) { CloseHandle(hDMutex); hDMutex = NULL; }
if (pwszPath != NULL) { delete[](pwszPath); pwszPath = NULL; }
if (pwszBaseName != NULL) { delete[](pwszBaseName); pwszBaseName = NULL; } goto ErrorReturn; }
sRecord.cbKey = sHeader.cbKey; sRecord.cbData = sHeader.cbData;
if (!(sRecord.pvKey = (void *)new BYTE[cbKey + sizeof(DWORD)]) || !(sRecord.pvData = (void *)new BYTE[cbData + sizeof(DWORD)])) { goto MemoryError; }
sRecord.pvData = (BYTE *)sRecord.pvData + sizeof(DWORD); // we use the first dword for rec # (see addrec)
memset(sRecord.pvKey, 0x00, cbKey); memset(sRecord.pvData, 0x00, cbData);
CommonReturn:
if (pDacl != NULL) { delete[] pDacl; }
if (psidEveryone) { FreeSid(psidEveryone); } return;
ErrorReturn: fInitialized = FALSE; *pfCreatedOK = FALSE; goto CommonReturn;
SET_ERROR_VAR_EX(DBG_SS, MemoryError, ERROR_NOT_ENOUGH_MEMORY); SET_ERROR_VAR_EX(DBG_SS, FileError, ERROR_FILE_NOT_FOUND); }
cBFile_::~cBFile_(void) { if (fDirty) { this->Sort(); }
if (pbKMap != NULL) { UnmapViewOfFile(pbKMap); }
if (pbDMap != NULL) { UnmapViewOfFile(pbDMap); }
if (hDFile != INVALID_HANDLE_VALUE) { CloseHandle(hDFile); }
if (hKFile != INVALID_HANDLE_VALUE) { CloseHandle(hKFile); }
if (hDMutex != NULL) { CloseHandle(hDMutex); }
if (pwszPath != NULL) { delete[](pwszPath); }
if (pwszBaseName != NULL) { delete[](pwszBaseName); }
DELETE_OBJECT(sRecord.pvKey);
if (sRecord.pvData) { sRecord.pvData = (BYTE *)sRecord.pvData - sizeof(DWORD); // we bumped the pointer in the constructer, put it back..
delete sRecord.pvData; } }
BOOL cBFile_::Initialize(void) { return(fInitialized); }
DWORD cBFile_::GetNumKeys(void) { DWORD dwRet;
dwRet = GetFileSize(this->hKFile, NULL);
if (dwRet > 0) { dwRet /= BFILE_KEYSIZE;
return(dwRet); }
return(0); }
void cBFile_::setKey(void *pvInKey) { memcpy(sRecord.pvKey, pvInKey, sRecord.cbKey); }
void cBFile_::setData(void *pvInData) { memcpy(sRecord.pvData, pvInData, sRecord.cbData); }
BOOL cBFile_::Find(void) { DWORD cbDOff; DWORD dwLastGood; void *pvKey; BOOL fRet;
pvKey = new BYTE[sRecord.cbKey];
if (!(pvKey)) { goto MemoryError; }
memcpy(pvKey, sRecord.pvKey, sRecord.cbKey);
if (this->BinaryFind(&cbDOff)) { dwLastGood = this->dwFirstNextRecNum;
while (this->GetPrev(dwLastGood)) { if (memcmp(pvKey, sRecord.pvKey, sRecord.cbKey) != 0) { break; }
dwLastGood = this->dwFirstNextRecNum; }
if (dwLastGood > 0) { dwLastGood--;
delete pvKey;
return(this->GetNext(dwLastGood)); }
delete pvKey;
__try {
return(this->GetDataRecord(cbDOff));
} __except(EXCEPTION_EXECUTE_HANDLER) { this->UnmapAll(); SetLastError(GetExceptionCode()); }
return(FALSE); }
fRet = FALSE;
CommonReturn: if (pvKey) { delete pvKey; }
return(fRet);
ErrorReturn: fRet = FALSE; goto CommonReturn;
SET_ERROR_VAR_EX(DBG_SS, MemoryError, ERROR_NOT_ENOUGH_MEMORY); }
BOOL cBFile_::GetFirst(void) { BOOL fRet;
this->dwFirstNextRecNum = 0;
if (!(this->pbKMap)) { return(FALSE); }
__try {
if (!this->ReadHeader()) { goto ErrorReturn; }
DWORD cbOff;
memcpy(sRecord.pvKey, &this->pbKMap[0], sRecord.cbKey); memcpy(&cbOff, &this->pbKMap[sRecord.cbKey], sizeof(DWORD));
if (!(this->GetDataRecord(cbOff))) { goto cBFileCorrupt; }
fRet = TRUE;
} __except(EXCEPTION_EXECUTE_HANDLER) { this->UnmapAll(); SetLastError(GetExceptionCode()); goto cBFileCorrupt; }
CommonReturn: return(fRet);
ErrorReturn: fRet = FALSE; goto CommonReturn;
TRACE_ERROR_EX(DBG_SS, cBFileCorrupt); }
BOOL cBFile_::GetNext(DWORD dwCurRec) { BOOL fRet;
if (!(this->pbKMap)) { return(FALSE); }
if (dwCurRec == 0xffffffff) { dwCurRec = this->dwFirstNextRecNum; }
DWORD cbOff;
dwCurRec++;
if (((dwCurRec + 1) * BFILE_KEYSIZE) > sHeader.cbSortedEOF) { goto cBFileNoNext; }
__try {
memcpy(sRecord.pvKey, &this->pbKMap[dwCurRec * BFILE_KEYSIZE], sRecord.cbKey); memcpy(&cbOff, &this->pbKMap[(dwCurRec * BFILE_KEYSIZE) + sRecord.cbKey], sizeof(DWORD));
if (!(this->GetDataRecord(cbOff))) { goto cBFileCorrupt; }
this->dwFirstNextRecNum = dwCurRec;
fRet = TRUE;
} __except(EXCEPTION_EXECUTE_HANDLER) { this->UnmapAll(); SetLastError(GetExceptionCode()); goto cBFileCorrupt; }
CommonReturn: return(fRet);
ErrorReturn: fRet = FALSE; this->dwFirstNextRecNum = 0; goto CommonReturn;
TRACE_ERROR_EX(DBG_SS, cBFileNoNext); TRACE_ERROR_EX(DBG_SS, cBFileCorrupt); }
BOOL cBFile_::GetPrev(DWORD dwCurRec) { BOOL fRet;
if (!(this->pbKMap) || (sHeader.cbSortedEOF == 0)) { goto cBFileNoPrev; }
if (dwCurRec == 0xffffffff) { dwCurRec = this->dwFirstNextRecNum; }
DWORD cb; DWORD cbOff;
if (dwCurRec < 1) { goto cBFileNoPrev; }
dwCurRec--;
if (((dwCurRec + 1) * BFILE_KEYSIZE) >= sHeader.cbSortedEOF) { goto cBFileNoPrev; }
__try {
memcpy(sRecord.pvKey, &this->pbKMap[dwCurRec * BFILE_KEYSIZE], sRecord.cbKey); memcpy(&cbOff, &this->pbKMap[(dwCurRec * BFILE_KEYSIZE) + sRecord.cbKey], sizeof(DWORD));
if (!(this->GetDataRecord(cbOff))) { goto cBFileCorrupt; }
this->dwFirstNextRecNum = dwCurRec;
fRet = TRUE;
} __except(EXCEPTION_EXECUTE_HANDLER) { this->UnmapAll(); SetLastError(GetExceptionCode()); goto cBFileCorrupt; }
CommonReturn: return(fRet);
ErrorReturn: fRet = FALSE; this->dwFirstNextRecNum = 0; goto CommonReturn;
TRACE_ERROR_EX(DBG_SS, cBFileNoPrev); TRACE_ERROR_EX(DBG_SS, cBFileCorrupt); }
BOOL cBFile_::Update(void) { DWORD cbDOff;
if ( fReadOnly == TRUE ) { SetLastError( ERROR_ACCESS_DENIED ); return( FALSE ); }
if (this->BinaryFind(&cbDOff)) { this->UpdateDataRecord(cbDOff);
return(TRUE); }
return(FALSE); }
BOOL cBFile_::Add(void) { if ( fReadOnly == TRUE ) { SetLastError( ERROR_ACCESS_DENIED ); return( FALSE ); }
if (!this->AddDirtyKey()) { return(FALSE); }
return(TRUE); }
BOOL cBFile_::Lock(void) { WaitForSingleObject( this->hDMutex, INFINITE ); return(TRUE); }
BOOL cBFile_::Unlock(void) { ReleaseMutex( this->hDMutex ); return( TRUE ); }
void cBFile_::SpeedSort(void) { Stack_ *pcStack;
if ( fReadOnly == TRUE ) { assert( FALSE && "A sort should not be forced in read-only mode." ); return; }
pcStack = NULL;
if (!(this->pbKMap)) { goto RemapError; }
if (!(this->Lock())) { goto LockFileError; }
//
// load dirty in memory and sort it
//
DWORD cbCurKey; DWORD cbTotal;
if (!(pcStack = new Stack_(pCritical))) { goto MemoryError; }
cbTotal = GetFileSize(this->hKFile, NULL); cbCurKey = sHeader.cbSortedEOF;
__try {
while (cbCurKey < cbTotal) { pcStack->Add(BFILE_KEYSIZE, &this->pbKMap[cbCurKey]);
cbCurKey += BFILE_KEYSIZE; }
pcStack->Sort(0, sRecord.cbKey, STACK_SORTTYPE_BINARY);
//
// shuffle into sorted
//
DWORD dwIdx; DWORD dwInsertion; DWORD cbFreeSpace; BYTE *pbKey; BYTE *pbCurrentKey; BYTE *pbStartFreeSpace;
pbStartFreeSpace = &this->pbKMap[sHeader.cbSortedEOF]; cbFreeSpace = pcStack->Count() * BFILE_KEYSIZE;
dwIdx = (long)pcStack->Count() - 1;
while (pbKey = (BYTE *)pcStack->Get(dwIdx)) { //
// get the starting point of our "window"
//
dwInsertion = this->GetInsertionPoint(pbKey);
//
// move the old data to the current free space "window"
//
memmove(&this->pbKMap[dwInsertion + cbFreeSpace], &this->pbKMap[dwInsertion], sHeader.cbSortedEOF - dwInsertion);
//
// after this, the insersion point has free space the size of the "window" - key size
//
cbFreeSpace -= BFILE_KEYSIZE;
//
// add the new key to the end of the "free space" window.
//
memcpy(&this->pbKMap[dwInsertion + cbFreeSpace], pbKey, BFILE_KEYSIZE);
//
// keep the end of the search up to date for these insertions....
//
sHeader.cbSortedEOF = dwInsertion;
if (dwIdx == 0) { break; }
dwIdx--; }
sHeader.cbSortedEOF = cbTotal; sHeader.fDirty = FALSE; fDirty = FALSE;
this->UpdateHeader();
} __except( EXCEPTION_EXECUTE_HANDLER ) { this->UnmapAll(); SetLastError( GetExceptionCode() ); goto RemapError; }
ErrorReturn: this->Unlock(); DELETE_OBJECT(pcStack); return;
TRACE_ERROR_EX(DBG_SS, LockFileError); TRACE_ERROR_EX(DBG_SS, RemapError);
SET_ERROR_VAR_EX(DBG_SS, MemoryError, ERROR_NOT_ENOUGH_MEMORY); }
DWORD cBFile_::GetInsertionPoint(void *pvIn) { DWORD dwEnd; DWORD dwMiddle; DWORD dwStart; DWORD dwHalf; DWORD dwCur; DWORD dwRet; BYTE *pb; int cmp;
dwStart = 0; dwEnd = sHeader.cbSortedEOF / BFILE_KEYSIZE; dwMiddle = dwEnd / 2L; dwHalf = dwMiddle; dwCur = 0; if (sHeader.cbSortedEOF >= BFILE_KEYSIZE) { dwRet = sHeader.cbSortedEOF - BFILE_KEYSIZE; } else { dwRet = 0; }
for EVER { pb = this->pbKMap + (dwMiddle * BFILE_KEYSIZE);
cmp = memcmp(pvIn, pb, sRecord.cbKey);
if (cmp == 0) { dwRet = (DWORD)(pb - this->pbKMap); break; }
if ( (dwMiddle == 0) || (dwMiddle == (sHeader.cbSortedEOF / BFILE_KEYSIZE)) || ((dwHalf == 0) && (dwMiddle == dwStart)) ) { DWORD dwFind;
dwFind = dwRet; cmp = (-1);
while ((cmp < 0) && ((dwFind + BFILE_KEYSIZE) <= sHeader.cbSortedEOF)) { cmp = memcmp(pvIn, &this->pbKMap[dwFind], sRecord.cbKey);
dwRet = dwFind;
dwFind += BFILE_KEYSIZE; }
break; }
if (cmp < 0) { dwEnd = dwMiddle; dwRet = (dwMiddle * BFILE_KEYSIZE); } else { dwStart = dwMiddle; }
dwHalf = (dwEnd - dwStart) / 2L; dwMiddle = dwStart + dwHalf; }
return(dwRet); }
void *cBFile_::GetDumpKey(DWORD dwIdx, void *pvRetKey, DWORD *pdwRecOffset) { DWORD dwOffset;
dwOffset = dwIdx * BFILE_KEYSIZE;
if (dwOffset >= GetFileSize(this->hKFile, NULL)) { return(NULL); }
__try {
memcpy(pvRetKey, &this->pbKMap[dwOffset], sRecord.cbKey);
memcpy(pdwRecOffset, &this->pbKMap[dwOffset + sRecord.cbKey], sizeof(DWORD));
return(pvRetKey);
} __except(EXCEPTION_EXECUTE_HANDLER) { this->UnmapAll(); SetLastError(GetExceptionCode()); }
return(NULL); }
BOOL cBFile_::GetHeader(BFILE_HEADER *psHeader) { __try {
if (!this->ReadHeader()) { return(FALSE); }
memcpy(psHeader, &sHeader, sizeof(BFILE_HEADER));
return(TRUE);
} __except(EXCEPTION_EXECUTE_HANDLER) { this->UnmapAll(); SetLastError(GetExceptionCode()); }
return(FALSE); }
void cBFile_::Sort(void) { if ( fReadOnly == TRUE ) { assert( FALSE && "A sort should not be forced in read-only mode." ); return; }
EnterCriticalSection(pCritical);
if (!FIsWinNT()) { //
// The only reason this is here is to work around some underlying
// bug in the OS. If we just call RemapKey() and RemapData() then
// we end up with some bogus state on the key and data files which will
// ultimately result in a sharing violation when trying to open the files
// at a later time.
//
if (this->pbKMap != NULL) { UnmapViewOfFile(this->pbKMap); this->pbKMap = NULL; }
if (this->pbDMap != NULL) { UnmapViewOfFile(this->pbDMap); this->pbDMap = NULL; }
if (hDFile != INVALID_HANDLE_VALUE) { CloseHandle(hDFile); hDFile = INVALID_HANDLE_VALUE; }
if (hKFile != INVALID_HANDLE_VALUE) { CloseHandle(hKFile); hKFile = INVALID_HANDLE_VALUE; }
this->OpenFiles(); } else { this->RemapKey(); this->RemapData(); }
#if 0
if (sHeader.cbSortedEOF > 0) { this->SpeedSort(); LeaveCriticalSection(pCritical); return; } #endif
BYTE *pb; Stack_ *pcStack;
pcStack = NULL; pb = NULL;
if (!(this->Lock())) { goto LockFileError; }
DWORD dwLen; DWORD cbFile; DWORD dwIdx; DWORD i; BYTE *pbStack;
if (!(pcStack = new Stack_(pCritical))) { goto MemoryError; }
dwLen = BFILE_KEYSIZE;
if (!(pb = new BYTE[dwLen])) { goto MemoryError; }
cbFile = GetFileSize(this->hKFile, NULL);
__try {
for (i = 0; i < cbFile; i += dwLen) { pcStack->Add(dwLen, &this->pbKMap[i]); }
pcStack->Sort(0, sRecord.cbKey, STACK_SORTTYPE_BINARY);
dwIdx = 0; i = 0; while (pbStack = (BYTE *)pcStack->Get(dwIdx)) { if ((i + dwLen) > cbFile) { goto FileSizeError; }
memcpy(&this->pbKMap[i], pbStack, dwLen);
dwIdx++; i += dwLen; }
sHeader.cbSortedEOF = cbFile; sHeader.fDirty = FALSE; fDirty = FALSE;
this->UpdateHeader();
} __except( EXCEPTION_EXECUTE_HANDLER ) { this->UnmapAll(); SetLastError( GetExceptionCode() ); }
ErrorReturn: this->Unlock();
DELETE_OBJECT(pcStack); DELETE_OBJECT(pb);
LeaveCriticalSection(pCritical); return;
TRACE_ERROR_EX(DBG_SS, FileSizeError); TRACE_ERROR_EX(DBG_SS, LockFileError);
SET_ERROR_VAR_EX(DBG_SS, MemoryError, ERROR_NOT_ENOUGH_MEMORY); }
BOOL cBFile_::AddDirtyKey(void) { DWORD cbOff; DWORD cb;
if ( fReadOnly == TRUE ) { assert( FALSE && "Add dirty key should not occur in read-only mode." ); return(FALSE); }
this->Lock();
__try {
if (!this->ReadHeader()) { return(FALSE); }
sHeader.dwLastRecNum++; sRecord.dwRecNum = sHeader.dwLastRecNum;
if ((cbOff = this->AddDataRecord()) != 0xffffffff) { if (fUseRecNumAsKey) { memcpy(sRecord.pvKey, &sRecord.dwRecNum, sizeof(DWORD)); }
memcpy((BYTE *)sRecord.pvKey + sRecord.cbKey, &cbOff, sizeof(DWORD)); // speed...
SetFilePointer(this->hKFile, 0, NULL, FILE_END); if (FIsWinNT()) { WriteFile(this->hKFile, sRecord.pvKey, sRecord.cbKey + sizeof(DWORD), &cb, NULL); // WriteFile(this->hKFile, &cbOff, sizeof(DWORD), &cb, NULL);
} else { if (this->pbKMap != NULL) { UnmapViewOfFile(this->pbKMap); this->pbKMap = NULL; WriteFile(this->hKFile, sRecord.pvKey, sRecord.cbKey + sizeof(DWORD), &cb, NULL); this->RemapKey(); } else { WriteFile(this->hKFile, sRecord.pvKey, sRecord.cbKey + sizeof(DWORD), &cb, NULL); } }
sHeader.fDirty = TRUE; this->fDirty = TRUE;
this->UpdateHeader(); }
} __except( EXCEPTION_EXECUTE_HANDLER ) { this->UnmapAll(); SetLastError( GetExceptionCode() ); }
this->Unlock();
return(TRUE); }
BOOL cBFile_::GetDataRecord(DWORD cbDataOffset) { DWORD cb;
memset(sRecord.pvData, 0x00, sRecord.cbData);
if (this->cbDMap < (cbDataOffset + sizeof(DWORD) + sRecord.cbData)) { return(FALSE); }
memcpy(&sRecord.dwRecNum, &this->pbDMap[cbDataOffset], sizeof(DWORD)); memcpy(sRecord.pvData, &this->pbDMap[cbDataOffset + sizeof(DWORD)], sRecord.cbData);
return(TRUE); }
void cBFile_::UpdateDataRecord(DWORD cbDataOffset) { DWORD cb;
if ( fReadOnly == TRUE ) { assert( FALSE && "Update data record should not occur in read-only mode." ); return; }
this->Lock();
if (this->cbDMap < (cbDataOffset + sizeof(DWORD) + sRecord.cbData)) { this->Unlock(); return; }
__try {
memcpy(&this->pbDMap[cbDataOffset + sizeof(DWORD)], sRecord.pvData, sRecord.cbData);
} __except( EXCEPTION_EXECUTE_HANDLER ) { this->UnmapAll(); SetLastError( GetExceptionCode() ); }
this->Unlock(); }
DWORD cBFile_::AddDataRecord(void) { DWORD cbRet;
if ( fReadOnly == TRUE ) { SetLastError( ERROR_ACCESS_DENIED ); return( 0xFFFFFFFF ); }
//
// no lock here because it is called from add key which
// does a lock
//
if ((cbRet = SetFilePointer(this->hDFile, 0, NULL, FILE_END)) != 0xffffffff) { DWORD cb; BYTE *pv;
pv = (BYTE *)sRecord.pvData - sizeof(DWORD); memcpy(pv, &sRecord.dwRecNum, sizeof(DWORD));
if (FIsWinNT()) { WriteFile(this->hDFile, pv, sizeof(DWORD) + sRecord.cbData, &cb, NULL); // WriteFile(this->hDFile, sRecord.pvData, sRecord.cbData, &cb, NULL);
} else { if (this->pbDMap != NULL) { UnmapViewOfFile(this->pbDMap); this->pbDMap = NULL; WriteFile(this->hDFile, pv, sizeof(DWORD) + sRecord.cbData, &cb, NULL); this->RemapData(); } else { WriteFile(this->hDFile, pv, sizeof(DWORD) + sRecord.cbData, &cb, NULL); } } }
return(cbRet); }
BOOL cBFile_::BinaryFind(DWORD *pcbDataOffset) { if (sHeader.fDirty) { this->Sort(); }
if (sHeader.cbSortedEOF == 0) { return(FALSE); }
if (!(this->pbKMap)) { return(FALSE); }
DWORD dwEnd; DWORD dwMiddle; DWORD dwStart; DWORD dwHalf; DWORD dwCur; void *pv; int cmp;
dwStart = 0; dwEnd = sHeader.cbSortedEOF / BFILE_KEYSIZE; dwHalf = dwMiddle = dwEnd / 2L; dwCur = 0;
__try {
for EVER { pv = (void *)(this->pbKMap + (dwMiddle * BFILE_KEYSIZE));
cmp = memcmp(sRecord.pvKey, pv, sRecord.cbKey);
if (cmp == 0) { memcpy(pcbDataOffset, (char *)pv + sRecord.cbKey, sizeof(DWORD));
this->dwFirstNextRecNum = (DWORD)((BYTE *)pv - this->pbKMap) / BFILE_KEYSIZE;
return(TRUE); }
if ((dwMiddle == 0) || (dwMiddle == (sHeader.cbSortedEOF / BFILE_KEYSIZE)) || ((dwHalf == 0) && (dwMiddle == dwStart))) { break; }
if (cmp < 0) { dwEnd = dwMiddle; } else { dwStart = dwMiddle; }
dwHalf = (dwEnd - dwStart) / 2L; dwMiddle = dwStart + dwHalf; }
} __except( EXCEPTION_EXECUTE_HANDLER ) { this->UnmapAll(); SetLastError( GetExceptionCode() ); }
return(FALSE); }
BOOL cBFile_::ReadHeader(void) { if ((this->pbDMap) && (this->cbDMap >= (sizeof(BFILE_HEADER) + BFILE_SIZEOFSIG))) { memcpy(&this->sHeader, &this->pbDMap[BFILE_SIZEOFSIG], sizeof(BFILE_HEADER)); } else if (SetFilePointer(this->hDFile, BFILE_SIZEOFSIG, NULL, FILE_BEGIN) != 0xffffffff) { DWORD cb;
if (!ReadFile(this->hDFile, &this->sHeader, sizeof(BFILE_HEADER), &cb, NULL)) { return(FALSE); } } else { memset(&this->sHeader, 0x00, sizeof(BFILE_HEADER)); }
return(TRUE); }
BOOL cBFile_::UpdateHeader(void) { if ( fReadOnly == TRUE ) { SetLastError( ERROR_ACCESS_DENIED ); return( FALSE ); }
if ((this->pbDMap) && (this->cbDMap >= (sizeof(BFILE_HEADER) + BFILE_SIZEOFSIG))) { memcpy(&this->pbDMap[BFILE_SIZEOFSIG], &this->sHeader, sizeof(BFILE_HEADER)); return(TRUE); }
if (SetFilePointer(this->hDFile, BFILE_SIZEOFSIG, NULL, FILE_BEGIN) != 0xffffffff) { DWORD cbWritten;
WriteFile(this->hDFile, &this->sHeader, sizeof(BFILE_HEADER), &cbWritten, NULL);
return(TRUE); }
return(FALSE); }
BOOL cBFile_::OpenFiles(void) { BOOL fRet = TRUE; WCHAR wszFile[MAX_PATH]; DWORD cbWritten; int iBaseEnd;
wcscpy(&wszFile[0], pwszPath); if (wszFile[wcslen(pwszPath) - 1] != L'\\') { wcscat(&wszFile[0], L"\\"); } wcscat(&wszFile[0], pwszBaseName); iBaseEnd = wcslen(&wszFile[0]);
wcscpy(&wszFile[iBaseEnd], BFILE_DATAEXT);
hDFile = CreateFileU(&wszFile[0], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (hDFile == INVALID_HANDLE_VALUE) { if ( GetLastError() == ERROR_ACCESS_DENIED ) { hDFile = CreateFileU(&wszFile[0], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
fReadOnly = TRUE; } else { hDFile = CreateFileU(&wszFile[0], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, CREATE_NEW, 0, NULL); }
if (hDFile == INVALID_HANDLE_VALUE) { return(FALSE); }
if ( fReadOnly == FALSE ) { WriteFile(this->hDFile, BFILE_SIG, BFILE_SIZEOFSIG, &cbWritten, NULL);
this->Lock();
__try {
fRet = this->UpdateHeader();
} __except( EXCEPTION_EXECUTE_HANDLER ) { fRet = FALSE; }
this->Unlock();
if ( fRet == FALSE ) { return( FALSE ); }
wcscpy(&wszFile[iBaseEnd], BFILE_KEYEXT);
hKFile = CreateFileU(&wszFile[0], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL); } else { wcscpy(&wszFile[iBaseEnd], BFILE_KEYEXT);
hKFile = CreateFileU(&wszFile[0], GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); } } else { wcscpy(&wszFile[iBaseEnd], BFILE_KEYEXT);
hKFile = CreateFileU(&wszFile[0], GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL); }
if ((hDFile == INVALID_HANDLE_VALUE) || (hKFile == INVALID_HANDLE_VALUE)) { return(FALSE); }
fRet &= this->RemapKey(); fRet &= this->RemapData();
if ( fRet == FALSE ) { return( FALSE ); }
__try {
if (!this->ReadHeader()) { return FALSE; }
} __except( EXCEPTION_EXECUTE_HANDLER ) { fRet = FALSE; }
return(fRet); }
BOOL cBFile_::RemapKey(void) { LPBYTE pbOldMap; HANDLE hMappedFile; DWORD PageAccess = PAGE_READWRITE; DWORD FileMapAccess = FILE_MAP_WRITE;
pbOldMap = this->pbKMap;
if ( fReadOnly == TRUE ) { PageAccess = PAGE_READONLY; FileMapAccess = FILE_MAP_READ; }
hMappedFile = CreateFileMapping(this->hKFile, NULL, PageAccess, 0, 0, NULL);
if (!(hMappedFile) || (hMappedFile == INVALID_HANDLE_VALUE)) { return(TRUE); // could be the first call!
}
this->pbKMap = (BYTE *)MapViewOfFile(hMappedFile, FileMapAccess, 0, 0, 0); if ( this->pbKMap != NULL ) { if ( pbOldMap != NULL ) { UnmapViewOfFile( pbOldMap ); }
this->cbKMap = GetFileSize(this->hKFile, NULL); } else { this->pbKMap = pbOldMap; }
CloseHandle(hMappedFile);
if ( ( pbOldMap == NULL ) && ( this->pbKMap == NULL ) ) { return(FALSE); }
return(TRUE); }
BOOL cBFile_::RemapData(void) { LPBYTE pbOldMap; HANDLE hMappedFile; DWORD PageAccess = PAGE_READWRITE; DWORD FileMapAccess = FILE_MAP_WRITE;
pbOldMap = this->pbDMap;
if ( fReadOnly == TRUE ) { PageAccess = PAGE_READONLY; FileMapAccess = FILE_MAP_READ; }
hMappedFile = CreateFileMapping(this->hDFile, NULL, PageAccess, 0, 0, NULL);
if (!(hMappedFile) || (hMappedFile == INVALID_HANDLE_VALUE)) { return(TRUE); // could be the first call!
}
this->pbDMap = (BYTE *)MapViewOfFile(hMappedFile, FileMapAccess, 0, 0, 0); if ( this->pbDMap != NULL ) { if ( pbOldMap != NULL ) { UnmapViewOfFile( pbOldMap ); }
this->cbDMap = GetFileSize(this->hDFile, NULL); } else { this->pbDMap = pbOldMap; }
CloseHandle(hMappedFile);
if ( ( pbOldMap == NULL ) && ( this->pbDMap == NULL ) ) { return(FALSE); }
return(TRUE); }
void cBFile_::UnmapAll(void) { if (this->pbKMap != NULL) { UnmapViewOfFile(this->pbKMap); this->pbKMap = NULL; }
if (this->pbDMap != NULL) { UnmapViewOfFile(this->pbDMap); this->pbDMap = NULL; } }
|