diff options
Diffstat (limited to 'dep/CascLib/src/CascFindFile.cpp')
-rw-r--r-- | dep/CascLib/src/CascFindFile.cpp | 283 |
1 files changed, 106 insertions, 177 deletions
diff --git a/dep/CascLib/src/CascFindFile.cpp b/dep/CascLib/src/CascFindFile.cpp index a5ec5766654..129403188c5 100644 --- a/dep/CascLib/src/CascFindFile.cpp +++ b/dep/CascLib/src/CascFindFile.cpp @@ -15,192 +15,124 @@ //----------------------------------------------------------------------------- // Local functions -static TCascSearch * IsValidSearchHandle(HANDLE hFind) +// Reset the search structure. Called before each search +static void ResetFindData(PCASC_FIND_DATA pFindData) { - TCascSearch * pSearch = (TCascSearch *)hFind; - - return (pSearch != NULL && pSearch->szClassName != NULL && !strcmp(pSearch->szClassName, "TCascSearch") && pSearch->szMask != NULL) ? pSearch : NULL; + // Reset the variables + ZeroMemory16(pFindData->CKey); + ZeroMemory16(pFindData->EKey); + pFindData->szFileName[0] = 0; + pFindData->szPlainName = pFindData->szFileName; + pFindData->TagBitMask = 0; + pFindData->dwFileDataId = CASC_INVALID_ID; + pFindData->dwFileSize = CASC_INVALID_SIZE; + pFindData->dwLocaleFlags = CASC_INVALID_ID; + pFindData->dwContentFlags = CASC_INVALID_ID; + pFindData->NameType = CascNameFull; + pFindData->bFileAvailable = false; + pFindData->bCanOpenByName = false; + pFindData->bCanOpenByDataId = false; + pFindData->bCanOpenByCKey = false; + pFindData->bCanOpenByEKey = false; } -static void FreeSearchHandle(TCascSearch * pSearch) +static void SupplyFakeFileName(PCASC_FIND_DATA pFindData) { - // Only if the storage handle is valid - assert(pSearch != NULL); - - // Close (dereference) the archive handle - if(pSearch->hs != NULL) + // If the file can be open by file data id, create fake file name + if(pFindData->bCanOpenByDataId) { - // Give root handler chance to free their stuff - RootHandler_EndSearch(pSearch->hs->pRootHandler, pSearch); + CascStrPrintf(pFindData->szFileName, _countof(pFindData->szFileName), "FILE%08X.dat", pFindData->dwFileDataId); + pFindData->NameType = CascNameDataId; + return; + } - // Dereference the storage handle - CascCloseStorage((HANDLE)pSearch->hs); - pSearch->hs = NULL; + // If the file can be open by CKey, convert the CKey to file name + if(pFindData->bCanOpenByCKey) + { + StringFromBinary(pFindData->CKey, MD5_HASH_SIZE, pFindData->szFileName); + pFindData->NameType = CascNameCKey; + return; } - // Free the file cache and frame array - if(pSearch->szMask != NULL) - CASC_FREE(pSearch->szMask); - if(pSearch->szListFile != NULL) - CASC_FREE(pSearch->szListFile); -// if(pSearch->pStruct1C != NULL) -// delete pSearch->pStruct1C; - if(pSearch->pCache != NULL) - ListFile_Free(pSearch->pCache); - - // Free the structure itself - pSearch->szClassName = NULL; - CASC_FREE(pSearch); + // CKey should be always present + StringFromBinary(pFindData->EKey, MD5_HASH_SIZE, pFindData->szFileName); + pFindData->NameType = CascNameEKey; + assert(pFindData->bCanOpenByEKey != false); } -static TCascSearch * AllocateSearchHandle(TCascStorage * hs, const TCHAR * szListFile, const char * szMask) +static bool CopyCKeyEntryToFindData(PCASC_FIND_DATA pFindData, PCASC_CKEY_ENTRY pCKeyEntry) { - TCascSearch * pSearch; - size_t cbToAllocate; - - // When using the MNDX info, do not allocate the extra bit array - cbToAllocate = sizeof(TCascSearch) + ((hs->pEncodingMap->TableSize + 7) / 8); - pSearch = (TCascSearch *)CASC_ALLOC(BYTE, cbToAllocate); - if(pSearch != NULL) - { - // Initialize the structure - memset(pSearch, 0, cbToAllocate); - pSearch->szClassName = "TCascSearch"; - - // Save the search handle - pSearch->hs = hs; - hs->dwRefCount++; - - // If the mask was not given, use default - if(szMask == NULL) - szMask = "*"; - - // Save the other variables - if(szListFile != NULL) - { - pSearch->szListFile = CascNewStr(szListFile, 0); - if(pSearch->szListFile == NULL) - { - FreeSearchHandle(pSearch); - return NULL; - } - } - - // Allocate the search mask - pSearch->szMask = CascNewStr(szMask, 0); - if(pSearch->szMask == NULL) - { - FreeSearchHandle(pSearch); - return NULL; - } - } - - return pSearch; + // Supply both keys + CopyMemory16(pFindData->CKey, pCKeyEntry->CKey); + CopyMemory16(pFindData->EKey, pCKeyEntry->EKey); + pFindData->bCanOpenByCKey = (pCKeyEntry->Flags & CASC_CE_HAS_CKEY) ? true : false; + pFindData->bCanOpenByEKey = (pCKeyEntry->Flags & CASC_CE_HAS_EKEY) ? true : false; + + // Supply the tag mask + pFindData->TagBitMask = pCKeyEntry->TagBitMask; + + // Supply the plain name. Only do that if the found name is not a CKey/EKey + if(pFindData->szFileName[0] != 0) + pFindData->szPlainName = (char *)GetPlainFileName(pFindData->szFileName); + + // If we retrieved the file size directly from the root provider, use it + // Otherwise, supply EncodedSize or ContentSize, whichever is available (but ContentSize > EncodedSize) + if(pFindData->dwFileSize == CASC_INVALID_SIZE) + pFindData->dwFileSize = pCKeyEntry->ContentSize; + + // Set flag indicating that the file is locally available + pFindData->bFileAvailable = (pCKeyEntry->Flags & CASC_CE_FILE_IS_LOCAL); + + // Supply a fake file name, if there is none supplied by the root handler + if(pFindData->szFileName[0] == 0) + SupplyFakeFileName(pFindData); + return true; } // Perform searching using root-specific provider. // The provider may need the listfile static bool DoStorageSearch_RootFile(TCascSearch * pSearch, PCASC_FIND_DATA pFindData) { - PCASC_ENCODING_ENTRY pEncodingEntry; - PCASC_INDEX_ENTRY pIndexEntry; - QUERY_KEY EncodingKey; - QUERY_KEY IndexKey; - LPBYTE pbEncodingKey; - DWORD EncodingIndex = 0; - DWORD ByteIndex; - DWORD BitMask; + PCASC_CKEY_ENTRY pCKeyEntry; + TCascStorage * hs = pSearch->hs; + + // Reset the search structure + ResetFindData(pFindData); + // Enumerate over all files for(;;) { - DWORD LocaleFlags = 0; - DWORD FileDataId = CASC_INVALID_ID; - DWORD FileSize = CASC_INVALID_SIZE; - - // Attempt to find (the next) file from the root entry - pbEncodingKey = RootHandler_Search(pSearch->hs->pRootHandler, pSearch, &FileSize, &LocaleFlags, &FileDataId); - if(pbEncodingKey == NULL) + // Attempt to find (the next) file from the root handler + pCKeyEntry = hs->pRootHandler->Search(pSearch, pFindData); + if(pCKeyEntry == NULL) return false; - // Verify whether the encoding key exists in the encoding table - EncodingKey.pbData = pbEncodingKey; - EncodingKey.cbData = MD5_HASH_SIZE; - pEncodingEntry = FindEncodingEntry(pSearch->hs, &EncodingKey, &EncodingIndex); - if(pEncodingEntry != NULL) - { - // Mark the item as already found - // Note: Duplicate items are allowed while we are searching using file names - // Do not exclude items from search if they were found before - ByteIndex = (DWORD)(EncodingIndex / 8); - BitMask = 1 << (EncodingIndex & 0x07); - pSearch->BitArray[ByteIndex] |= BitMask; - - // Locate the index entry - IndexKey.pbData = GET_INDEX_KEY(pEncodingEntry); - IndexKey.cbData = MD5_HASH_SIZE; - pIndexEntry = FindIndexEntry(pSearch->hs, &IndexKey); - if(pIndexEntry == NULL) - continue; - - // If we retrieved the file size directly from the root provider, use it - // Otherwise, we need to retrieve it from the encoding entry - if(FileSize == CASC_INVALID_SIZE) - FileSize = ConvertBytesToInteger_4(pEncodingEntry->FileSizeBE); - - // Fill-in the found file - strcpy(pFindData->szFileName, pSearch->szFileName); - memcpy(pFindData->EncodingKey, pEncodingEntry->EncodingKey, MD5_HASH_SIZE); - pFindData->szPlainName = (char *)GetPlainFileName(pFindData->szFileName); - pFindData->dwLocaleFlags = LocaleFlags; - pFindData->dwFileDataId = FileDataId; - pFindData->dwFileSize = FileSize; - return true; - } + // The entry is expected to be referenced by the root directory + assert(pCKeyEntry->RefCount != 0); + + // Copy the CKey entry to the find data and return it + return CopyCKeyEntryToFindData(pFindData, pCKeyEntry); } } -static bool DoStorageSearch_EncodingKey(TCascSearch * pSearch, PCASC_FIND_DATA pFindData) +static bool DoStorageSearch_CKey(TCascSearch * pSearch, PCASC_FIND_DATA pFindData) { - PCASC_ENCODING_ENTRY pEncodingEntry; - PCASC_INDEX_ENTRY pIndexEntry; + PCASC_CKEY_ENTRY pCKeyEntry; TCascStorage * hs = pSearch->hs; - QUERY_KEY IndexKey; - DWORD ByteIndex; - DWORD BitMask; + size_t nTotalItems = hs->CKeyArray.ItemCount(); - // Check for encoding keys that haven't been found yet - while(pSearch->IndexLevel1 < hs->pEncodingMap->TableSize) + // Reset the find data structure + ResetFindData(pFindData); + + // Check for CKeys that haven't been found yet + while(pSearch->nFileIndex < nTotalItems) { - // Check if that entry has been reported before - ByteIndex = (DWORD)(pSearch->IndexLevel1 / 8); - BitMask = 1 << (pSearch->IndexLevel1 & 0x07); - if((pSearch->BitArray[ByteIndex] & BitMask) == 0) + // Locate the n-th CKey entry. If this entry is not referenced by the root handler, we include it in the search result + pCKeyEntry = (PCASC_CKEY_ENTRY)hs->CKeyArray.ItemAt(pSearch->nFileIndex++); + if((pCKeyEntry->Flags & CASC_CE_FOLDER_ENTRY) == 0 && pCKeyEntry->RefCount == 0) { - // Locate the index entry - pEncodingEntry = (PCASC_ENCODING_ENTRY)hs->pEncodingMap->HashTable[pSearch->IndexLevel1]; - if(pEncodingEntry != NULL) - { - IndexKey.pbData = GET_INDEX_KEY(pEncodingEntry); - IndexKey.cbData = MD5_HASH_SIZE; - pIndexEntry = FindIndexEntry(pSearch->hs, &IndexKey); - if(pIndexEntry != NULL) - { - // Fill-in the found file - memcpy(pFindData->EncodingKey, pEncodingEntry->EncodingKey, MD5_HASH_SIZE); - pFindData->szFileName[0] = 0; - pFindData->szPlainName = pFindData->szFileName; - pFindData->dwLocaleFlags = CASC_LOCALE_NONE; - pFindData->dwFileSize = ConvertBytesToInteger_4(pEncodingEntry->FileSizeBE); - - // Mark the entry as already-found - pSearch->BitArray[ByteIndex] |= BitMask; - return true; - } - } + return CopyCKeyEntryToFindData(pFindData, pCKeyEntry); } - - // Go to the next encoding entry - pSearch->IndexLevel1++; } // Nameless search ended @@ -210,36 +142,37 @@ static bool DoStorageSearch_EncodingKey(TCascSearch * pSearch, PCASC_FIND_DATA p static bool DoStorageSearch(TCascSearch * pSearch, PCASC_FIND_DATA pFindData) { // State 0: No search done yet - if(pSearch->dwState == 0) + if(pSearch->nSearchState == 0) { // Does the search specify listfile? if(pSearch->szListFile != NULL) pSearch->pCache = ListFile_OpenExternal(pSearch->szListFile); // Move the search phase to the listfile searching - pSearch->IndexLevel1 = 0; - pSearch->dwState++; + pSearch->nSearchState = 1; + pSearch->nFileIndex = 0; } // State 1: Searching the list file - if(pSearch->dwState == 1) + if(pSearch->nSearchState == 1) { if(DoStorageSearch_RootFile(pSearch, pFindData)) return true; // Move to the nameless search state - pSearch->IndexLevel1 = 0; - pSearch->dwState++; + pSearch->nSearchState = 2; + pSearch->nFileIndex = 0; } - // State 2: Searching the remaining entries - if(pSearch->dwState == 2 && (pSearch->szMask == NULL || !strcmp(pSearch->szMask, "*"))) + // State 2: Searching the remaining entries by CKey + if(pSearch->nSearchState == 2 && (pSearch->szMask == NULL || !strcmp(pSearch->szMask, "*"))) { - if(DoStorageSearch_EncodingKey(pSearch, pFindData)) + if(DoStorageSearch_CKey(pSearch, pFindData)) return true; // Move to the final search state - pSearch->dwState++; + pSearch->nSearchState++; + pSearch->nFileIndex = 0; } return false; @@ -250,16 +183,16 @@ static bool DoStorageSearch(TCascSearch * pSearch, PCASC_FIND_DATA pFindData) HANDLE WINAPI CascFindFirstFile( HANDLE hStorage, - const char * szMask, + LPCSTR szMask, PCASC_FIND_DATA pFindData, - const TCHAR * szListFile) + LPCTSTR szListFile) { TCascStorage * hs; TCascSearch * pSearch = NULL; int nError = ERROR_SUCCESS; // Check parameters - if((hs = IsValidStorageHandle(hStorage)) == NULL) + if((hs = TCascStorage::IsValid(hStorage)) == NULL) nError = ERROR_INVALID_HANDLE; if(szMask == NULL || pFindData == NULL) nError = ERROR_INVALID_PARAMETER; @@ -267,11 +200,8 @@ HANDLE WINAPI CascFindFirstFile( // Init the search structure and search handle if(nError == ERROR_SUCCESS) { - // Clear the entire search structure - memset(pFindData, 0, sizeof(CASC_FIND_DATA)); - // Allocate the search handle - pSearch = AllocateSearchHandle(hs, szListFile, szMask); + pSearch = new TCascSearch(hs, szListFile, szMask); if(pSearch == NULL) nError = ERROR_NOT_ENOUGH_MEMORY; } @@ -285,8 +215,7 @@ HANDLE WINAPI CascFindFirstFile( if(nError != ERROR_SUCCESS) { - if(pSearch != NULL) - FreeSearchHandle(pSearch); + delete pSearch; pSearch = (TCascSearch *)INVALID_HANDLE_VALUE; } @@ -299,7 +228,7 @@ bool WINAPI CascFindNextFile( { TCascSearch * pSearch; - pSearch = IsValidSearchHandle(hFind); + pSearch = TCascSearch::IsValid(hFind); if(pSearch == NULL || pFindData == NULL) { SetLastError(ERROR_INVALID_PARAMETER); @@ -314,13 +243,13 @@ bool WINAPI CascFindClose(HANDLE hFind) { TCascSearch * pSearch; - pSearch = IsValidSearchHandle(hFind); + pSearch = TCascSearch::IsValid(hFind); if(pSearch == NULL) { SetLastError(ERROR_INVALID_PARAMETER); return false; } - FreeSearchHandle(pSearch); + delete pSearch; return true; } |