summaryrefslogtreecommitdiff
path: root/StormLib/src/SFileFindFile.cpp
diff options
context:
space:
mode:
authorbriaguya <70942617+briaguya-ai@users.noreply.github.com>2022-11-14 05:22:34 -0500
committerGitHub <noreply@github.com>2022-11-14 11:22:34 +0100
commit3914781ebfd5cb22717cc207cb3d37d8754d0eb7 (patch)
tree2e412b87e66b1deef47bef242e7189a200cea0ff /StormLib/src/SFileFindFile.cpp
parent9eb29ed81cb497a6a216811255f8af7daf3f8bd8 (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.cpp483
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;
-}