diff options
| author | briaguya <70942617+briaguya-ai@users.noreply.github.com> | 2022-11-14 05:22:34 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-11-14 11:22:34 +0100 |
| commit | 3914781ebfd5cb22717cc207cb3d37d8754d0eb7 (patch) | |
| tree | 2e412b87e66b1deef47bef242e7189a200cea0ff /StormLib/src/SFileFindFile.cpp | |
| parent | 9eb29ed81cb497a6a216811255f8af7daf3f8bd8 (diff) | |
Import libultraship as a submodule (#1943)
Co-authored-by: briaguya <briaguya>
Co-authored-by: Christopher Leggett <chris@leggett.dev>
Co-authored-by: David Chavez <davi@dcvz.io>
Diffstat (limited to 'StormLib/src/SFileFindFile.cpp')
| -rw-r--r-- | StormLib/src/SFileFindFile.cpp | 483 |
1 files changed, 0 insertions, 483 deletions
diff --git a/StormLib/src/SFileFindFile.cpp b/StormLib/src/SFileFindFile.cpp deleted file mode 100644 index 856de443e..000000000 --- a/StormLib/src/SFileFindFile.cpp +++ /dev/null @@ -1,483 +0,0 @@ -/*****************************************************************************/ -/* SFileFindFile.cpp Copyright (c) Ladislav Zezula 2003 */ -/*---------------------------------------------------------------------------*/ -/* A module for file searching within MPQs */ -/*---------------------------------------------------------------------------*/ -/* Date Ver Who Comment */ -/* -------- ---- --- ------- */ -/* 25.03.03 1.00 Lad The first version of SFileFindFile.cpp */ -/*****************************************************************************/ - -#define __STORMLIB_SELF__ -#include "StormLib.h" -#include "StormCommon.h" - -//----------------------------------------------------------------------------- -// Private structure used for file search (search handle) - -// Used by searching in MPQ archives -struct TMPQSearch -{ - TMPQArchive * ha; // Handle to MPQ, where the search runs - TFileEntry ** pSearchTable; // Table for files that have been already found - DWORD dwSearchTableItems; // Number of items in the search table - DWORD dwNextIndex; // Next file index to be checked - DWORD dwFlagMask; // For checking flag mask - char szSearchMask[1]; // Search mask (variable length) -}; - -//----------------------------------------------------------------------------- -// Local functions - -static TMPQSearch * IsValidSearchHandle(HANDLE hFind) -{ - TMPQSearch * hs = (TMPQSearch *)hFind; - - if(hs != NULL && IsValidMpqHandle(hs->ha)) - return hs; - - return NULL; -} - -bool SFileCheckWildCard(const char * szString, const char * szWildCard) -{ - const char * szWildCardPtr; - - for(;;) - { - // If there is '?' in the wildcard, we skip one char - while(szWildCard[0] == '?') - { - if(szString[0] == 0) - return false; - - szWildCard++; - szString++; - } - - // Handle '*' - szWildCardPtr = szWildCard; - if(szWildCardPtr[0] != 0) - { - if(szWildCardPtr[0] == '*') - { - while(szWildCardPtr[0] == '*') - szWildCardPtr++; - - if(szWildCardPtr[0] == 0) - return true; - - if(AsciiToUpperTable[szWildCardPtr[0]] == AsciiToUpperTable[szString[0]]) - { - if(SFileCheckWildCard(szString, szWildCardPtr)) - return true; - } - } - else - { - if(AsciiToUpperTable[szWildCardPtr[0]] != AsciiToUpperTable[szString[0]]) - return false; - - szWildCard = szWildCardPtr + 1; - } - - if(szString[0] == 0) - return false; - szString++; - } - else - { - return (szString[0] == 0) ? true : false; - } - } -} - -static DWORD GetSearchTableItems(TMPQArchive * ha) -{ - DWORD dwMergeItems = 0; - - // Loop over all patches - while(ha != NULL) - { - // Append the number of files - dwMergeItems += (ha->pHetTable != NULL) ? ha->pHetTable->dwEntryCount - : ha->pHeader->dwBlockTableSize; - // Move to the patched archive - ha = ha->haPatch; - } - - // Return the double size of number of items - return (dwMergeItems | 1); -} - -static bool FileWasFoundBefore( - TMPQArchive * ha, - TMPQSearch * hs, - TFileEntry * pFileEntry) -{ - TFileEntry * pEntry; - char * szRealFileName = pFileEntry->szFileName; - DWORD dwStartIndex; - DWORD dwNameHash; - DWORD dwIndex; - - if(hs->pSearchTable != NULL && szRealFileName != NULL) - { - // If we are in patch MPQ, we check if patch prefix matches - // and then trim the patch prefix - if(ha->pPatchPrefix != NULL) - { - // If the patch prefix doesn't fit, we pretend that the file - // was there before and it will be skipped - if(_strnicmp(szRealFileName, ha->pPatchPrefix->szPatchPrefix, ha->pPatchPrefix->nLength)) - return true; - - szRealFileName += ha->pPatchPrefix->nLength; - } - - // Calculate the hash to the table - dwNameHash = ha->pfnHashString(szRealFileName, MPQ_HASH_NAME_A); - dwStartIndex = dwIndex = (dwNameHash % hs->dwSearchTableItems); - - // The file might have been found before - // only if this is not the first MPQ being searched - if(ha->haBase != NULL) - { - // Enumerate all entries in the search table - for(;;) - { - // Get the file entry at that position - pEntry = hs->pSearchTable[dwIndex]; - if(pEntry == NULL) - break; - - if(pEntry->szFileName != NULL) - { - // Does the name match? - if(!_stricmp(pEntry->szFileName, szRealFileName)) - return true; - } - - // Move to the next entry - dwIndex = (dwIndex + 1) % hs->dwSearchTableItems; - if(dwIndex == dwStartIndex) - break; - } - } - - // Put the entry to the table for later use - hs->pSearchTable[dwIndex] = pFileEntry; - } - return false; -} - -static TFileEntry * FindPatchEntry(TMPQArchive * ha, TFileEntry * pFileEntry) -{ - TFileEntry * pPatchEntry = pFileEntry; - TFileEntry * pTempEntry; - char szFileName[MAX_PATH+1]; - - // Can't find patch entry for a file that doesn't have name - if(pFileEntry->szFileName != NULL && pFileEntry->szFileName[0] != 0) - { - // Go while there are patches - while(ha->haPatch != NULL) - { - // Move to the patch archive - ha = ha->haPatch; - szFileName[0] = 0; - - // Prepare the prefix for the file name - if(ha->pPatchPrefix && ha->pPatchPrefix->nLength) - StringCopy(szFileName, _countof(szFileName), ha->pPatchPrefix->szPatchPrefix); - StringCat(szFileName, _countof(szFileName), pFileEntry->szFileName); - - // Try to find the file there - pTempEntry = GetFileEntryExact(ha, szFileName, 0, NULL); - if(pTempEntry != NULL) - pPatchEntry = pTempEntry; - } - } - - // Return the found patch entry - return pPatchEntry; -} - -static bool DoMPQSearch_FileEntry( - TMPQSearch * hs, - SFILE_FIND_DATA * lpFindFileData, - TMPQArchive * ha, - TMPQHash * pHashEntry, - TFileEntry * pFileEntry) -{ - TFileEntry * pPatchEntry; - HANDLE hFile = NULL; - const char * szFileName; - size_t nPrefixLength = (ha->pPatchPrefix != NULL) ? ha->pPatchPrefix->nLength : 0; - DWORD dwBlockIndex; - char szNameBuff[MAX_PATH]; - - // Is it a file but not a patch file? - if((pFileEntry->dwFlags & hs->dwFlagMask) == MPQ_FILE_EXISTS) - { - // Ignore fake files which are not compressed but have size higher than the archive - if ((pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) == 0 && (pFileEntry->dwFileSize > ha->FileSize)) - return false; - - // Now we have to check if this file was not enumerated before - if(!FileWasFoundBefore(ha, hs, pFileEntry)) - { -// if(pFileEntry != NULL && !_stricmp(pFileEntry->szFileName, "TriggerLibs\\NativeLib.galaxy")) -// DebugBreak(); - - // Find a patch to this file - // Note: This either succeeds or returns pFileEntry - pPatchEntry = FindPatchEntry(ha, pFileEntry); - - // Prepare the block index - dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable); - if(dwBlockIndex == 569) - szNameBuff[0] = 'F'; - - // Get the file name. If it's not known, we will create pseudo-name - szFileName = pFileEntry->szFileName; - if(szFileName == NULL) - { - // Open the file by its pseudo-name. - StringCreatePseudoFileName(szNameBuff, _countof(szNameBuff), dwBlockIndex, "xxx"); - if(SFileOpenFileEx((HANDLE)hs->ha, szNameBuff, SFILE_OPEN_BASE_FILE, &hFile)) - { - SFileGetFileName(hFile, szNameBuff); - szFileName = szNameBuff; - SFileCloseFile(hFile); - } - } - - // If the file name is still NULL, we cannot include the file to search results - if(szFileName != NULL) - { - // Check the file name against the wildcard - if(SFileCheckWildCard(szFileName + nPrefixLength, hs->szSearchMask)) - { - // Fill the found entry. hash entry and block index are taken from the base MPQ - lpFindFileData->dwHashIndex = HASH_ENTRY_FREE; - lpFindFileData->dwBlockIndex = dwBlockIndex; - lpFindFileData->dwFileSize = pPatchEntry->dwFileSize; - lpFindFileData->dwFileFlags = pPatchEntry->dwFlags; - lpFindFileData->dwCompSize = pPatchEntry->dwCmpSize; - lpFindFileData->lcLocale = 0; // pPatchEntry->lcLocale; - - // Fill the filetime - lpFindFileData->dwFileTimeHi = (DWORD)(pPatchEntry->FileTime >> 32); - lpFindFileData->dwFileTimeLo = (DWORD)(pPatchEntry->FileTime); - - // Fill-in the entries from hash table entry, if given - if(pHashEntry != NULL) - { - lpFindFileData->dwHashIndex = (DWORD)(pHashEntry - ha->pHashTable); - lpFindFileData->lcLocale = pHashEntry->lcLocale; - } - - // Fill the file name and plain file name - StringCopy(lpFindFileData->cFileName, _countof(lpFindFileData->cFileName), szFileName + nPrefixLength); - lpFindFileData->szPlainName = (char *)GetPlainFileName(lpFindFileData->cFileName); - return true; - } - } - } - } - - // Either not a valid item or was found before - return false; -} - -static DWORD DoMPQSearch_HashTable(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData, TMPQArchive * ha) -{ - TMPQHash * pHashTableEnd = ha->pHashTable + ha->pHeader->dwHashTableSize; - TMPQHash * pHash; - - // Parse the file table - for(pHash = ha->pHashTable + hs->dwNextIndex; pHash < pHashTableEnd; pHash++) - { - // Increment the next index for subsequent search - hs->dwNextIndex++; - - // Does this hash table entry point to a proper block table entry? - if(IsValidHashEntry(ha, pHash)) - { - // Check if this file entry should be included in the search result - if(DoMPQSearch_FileEntry(hs, lpFindFileData, ha, pHash, ha->pFileTable + MPQ_BLOCK_INDEX(pHash))) - return ERROR_SUCCESS; - } - } - - // No more files - return ERROR_NO_MORE_FILES; -} - -static DWORD DoMPQSearch_FileTable(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData, TMPQArchive * ha) -{ - TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize; - TFileEntry * pFileEntry; - - // Parse the file table - for(pFileEntry = ha->pFileTable + hs->dwNextIndex; pFileEntry < pFileTableEnd; pFileEntry++) - { - // Increment the next index for subsequent search - hs->dwNextIndex++; - - // Check if this file entry should be included in the search result - if(DoMPQSearch_FileEntry(hs, lpFindFileData, ha, NULL, pFileEntry)) - return ERROR_SUCCESS; - } - - // No more files - return ERROR_NO_MORE_FILES; -} - -// Performs one MPQ search -static DWORD DoMPQSearch(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData) -{ - TMPQArchive * ha = hs->ha; - DWORD dwErrCode; - - // Start searching with base MPQ - while(ha != NULL) - { - // If the archive has hash table, we need to use hash table - // in order to catch hash table index and file locale. - // Note: If multiple hash table entries, point to the same block entry, - // we need, to report them all - dwErrCode = (ha->pHashTable != NULL) ? DoMPQSearch_HashTable(hs, lpFindFileData, ha) - : DoMPQSearch_FileTable(hs, lpFindFileData, ha); - if(dwErrCode == ERROR_SUCCESS) - return dwErrCode; - - // If there is no more patches in the chain, stop it. - // This also keeps hs->ha non-NULL, which is required - // for freeing the handle later - if(ha->haPatch == NULL) - break; - - // Move to the next patch in the patch chain - hs->ha = ha = ha->haPatch; - hs->dwNextIndex = 0; - } - - // No more files found, return error - return ERROR_NO_MORE_FILES; -} - -static void FreeMPQSearch(TMPQSearch *& hs) -{ - if(hs != NULL) - { - if(hs->pSearchTable != NULL) - STORM_FREE(hs->pSearchTable); - STORM_FREE(hs); - hs = NULL; - } -} - -//----------------------------------------------------------------------------- -// Public functions - -HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const TCHAR * szListFile) -{ - TMPQArchive * ha = (TMPQArchive *)hMpq; - TMPQSearch * hs = NULL; - size_t nSize = 0; - DWORD dwErrCode = ERROR_SUCCESS; - - // Check for the valid parameters - if(!IsValidMpqHandle(hMpq)) - dwErrCode = ERROR_INVALID_HANDLE; - if(szMask == NULL || lpFindFileData == NULL) - dwErrCode = ERROR_INVALID_PARAMETER; - - // Include the listfile into the MPQ's internal listfile - // Note that if the listfile name is NULL, do nothing because the - // internal listfile is always included. - if(dwErrCode == ERROR_SUCCESS && szListFile != NULL && *szListFile != 0) - dwErrCode = SFileAddListFile((HANDLE)ha, szListFile); - - // Allocate the structure for MPQ search - if(dwErrCode == ERROR_SUCCESS) - { - nSize = sizeof(TMPQSearch) + strlen(szMask) + 1; - if((hs = (TMPQSearch *)STORM_ALLOC(char, nSize)) == NULL) - dwErrCode = ERROR_NOT_ENOUGH_MEMORY; - } - - // Perform the first search - if(dwErrCode == ERROR_SUCCESS) - { - memset(hs, 0, sizeof(TMPQSearch)); - strcpy(hs->szSearchMask, szMask); - hs->dwFlagMask = MPQ_FILE_EXISTS; - hs->ha = ha; - - // If the archive is patched archive, we have to create a merge table - // to prevent files being repeated - if(ha->haPatch != NULL) - { - hs->dwSearchTableItems = GetSearchTableItems(ha); - hs->pSearchTable = STORM_ALLOC(TFileEntry *, hs->dwSearchTableItems); - hs->dwFlagMask = MPQ_FILE_EXISTS | MPQ_FILE_PATCH_FILE; - if(hs->pSearchTable != NULL) - memset(hs->pSearchTable, 0, hs->dwSearchTableItems * sizeof(TFileEntry *)); - else - dwErrCode = ERROR_NOT_ENOUGH_MEMORY; - } - } - - // Perform first item searching - if(dwErrCode == ERROR_SUCCESS) - { - dwErrCode = DoMPQSearch(hs, lpFindFileData); - } - - // Cleanup - if(dwErrCode != ERROR_SUCCESS) - { - FreeMPQSearch(hs); - SetLastError(dwErrCode); - } - - // Return the result value - return (HANDLE)hs; -} - -bool WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData) -{ - TMPQSearch * hs = IsValidSearchHandle(hFind); - DWORD dwErrCode = ERROR_SUCCESS; - - // Check the parameters - if(hs == NULL) - dwErrCode = ERROR_INVALID_HANDLE; - if(lpFindFileData == NULL) - dwErrCode = ERROR_INVALID_PARAMETER; - - if(dwErrCode == ERROR_SUCCESS) - dwErrCode = DoMPQSearch(hs, lpFindFileData); - - if(dwErrCode != ERROR_SUCCESS) - SetLastError(dwErrCode); - return (dwErrCode == ERROR_SUCCESS); -} - -bool WINAPI SFileFindClose(HANDLE hFind) -{ - TMPQSearch * hs = IsValidSearchHandle(hFind); - - // Check the parameters - if(hs == NULL) - { - SetLastError(ERROR_INVALID_HANDLE); - return false; - } - - FreeMPQSearch(hs); - return true; -} |
