summaryrefslogtreecommitdiff
path: root/StormLib/src/SFileOpenFileEx.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/SFileOpenFileEx.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/SFileOpenFileEx.cpp')
-rw-r--r--StormLib/src/SFileOpenFileEx.cpp418
1 files changed, 0 insertions, 418 deletions
diff --git a/StormLib/src/SFileOpenFileEx.cpp b/StormLib/src/SFileOpenFileEx.cpp
deleted file mode 100644
index d77f25e35..000000000
--- a/StormLib/src/SFileOpenFileEx.cpp
+++ /dev/null
@@ -1,418 +0,0 @@
-/*****************************************************************************/
-/* SFileOpenFileEx.cpp Copyright (c) Ladislav Zezula 2003 */
-/*---------------------------------------------------------------------------*/
-/* Description : */
-/*---------------------------------------------------------------------------*/
-/* Date Ver Who Comment */
-/* -------- ---- --- ------- */
-/* xx.xx.99 1.00 Lad The first version of SFileOpenFileEx.cpp */
-/*****************************************************************************/
-
-#define __STORMLIB_SELF__
-#include "StormLib.h"
-#include "StormCommon.h"
-
-/*****************************************************************************/
-/* Local functions */
-/*****************************************************************************/
-
-static DWORD FindHashIndex(TMPQArchive * ha, DWORD dwFileIndex)
-{
- TMPQHash * pHashTableEnd;
- TMPQHash * pHash;
- DWORD dwFirstIndex = HASH_ENTRY_FREE;
-
- // Should only be called if the archive has hash table
- assert(ha->pHashTable != NULL);
-
- // Multiple hash table entries can point to the file table entry.
- // We need to search all of them
- pHashTableEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
- for(pHash = ha->pHashTable; pHash < pHashTableEnd; pHash++)
- {
- if(MPQ_BLOCK_INDEX(pHash) == dwFileIndex)
- {
- // Duplicate hash entry found
- if(dwFirstIndex != HASH_ENTRY_FREE)
- return HASH_ENTRY_FREE;
- dwFirstIndex = (DWORD)(pHash - ha->pHashTable);
- }
- }
-
- // Return the hash table entry index
- return dwFirstIndex;
-}
-
-static const char * GetPatchFileName(TMPQArchive * ha, const char * szFileName, char * szBuffer)
-{
- TMPQNamePrefix * pPrefix;
-
- // Are there patches in the current MPQ?
- if(ha->dwFlags & MPQ_FLAG_PATCH)
- {
- // The patch prefix must be already known here
- assert(ha->pPatchPrefix != NULL);
- pPrefix = ha->pPatchPrefix;
-
- // The patch name for "OldWorld\\XXX\\YYY" is "Base\\XXX\YYY"
- // We need to remove the "OldWorld\\" prefix
- if(!_strnicmp(szFileName, "OldWorld\\", 9))
- szFileName += 9;
-
- // Create the file name from the known patch entry
- memcpy(szBuffer, pPrefix->szPatchPrefix, pPrefix->nLength);
- strcpy(szBuffer + pPrefix->nLength, szFileName);
- szFileName = szBuffer;
- }
-
- return szFileName;
-}
-
-static bool OpenLocalFile(const char * szFileName, HANDLE * PtrFile)
-{
- TFileStream * pStream;
- TMPQFile * hf = NULL;
- TCHAR szFileNameT[MAX_PATH];
-
- // Convert the file name to UNICODE (if needed)
- StringCopy(szFileNameT, _countof(szFileNameT), szFileName);
-
- // Open the file and create the TMPQFile structure
- pStream = FileStream_OpenFile(szFileNameT, STREAM_FLAG_READ_ONLY);
- if(pStream != NULL)
- {
- // Allocate and initialize file handle
- hf = CreateFileHandle(NULL, NULL);
- if(hf != NULL)
- {
- hf->pStream = pStream;
- *PtrFile = hf;
- return true;
- }
- else
- {
- FileStream_Close(pStream);
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- }
- }
- *PtrFile = NULL;
- return false;
-}
-
-bool OpenPatchedFile(HANDLE hMpq, const char * szFileName, HANDLE * PtrFile)
-{
- TMPQArchive * haBase = NULL;
- TMPQArchive * ha = (TMPQArchive *)hMpq;
- TFileEntry * pFileEntry;
- TMPQFile * hfPatch; // Pointer to patch file
- TMPQFile * hfBase = NULL; // Pointer to base open file
- TMPQFile * hf = NULL;
- HANDLE hPatchFile;
- char szNameBuffer[MAX_PATH];
-
- // First of all, find the latest archive where the file is in base version
- // (i.e. where the original, unpatched version of the file exists)
- while(ha != NULL)
- {
- // If the file is there, then we remember the archive
- pFileEntry = GetFileEntryExact(ha, GetPatchFileName(ha, szFileName, szNameBuffer), 0, NULL);
- if(pFileEntry != NULL && (pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
- haBase = ha;
-
- // Move to the patch archive
- ha = ha->haPatch;
- }
-
- // If we couldn't find the base file in any of the patches, it doesn't exist
- if((ha = haBase) != NULL)
- {
- // Now open the base file
- if(SFileOpenFileEx((HANDLE)ha, GetPatchFileName(ha, szFileName, szNameBuffer), SFILE_OPEN_BASE_FILE, (HANDLE *)&hfBase))
- {
- // The file must be a base file, i.e. without MPQ_FILE_PATCH_FILE
- assert((hfBase->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0);
- hf = hfBase;
-
- // Now open all patches and attach them on top of the base file
- for(ha = ha->haPatch; ha != NULL; ha = ha->haPatch)
- {
- // Prepare the file name with a correct prefix
- if(SFileOpenFileEx((HANDLE)ha, GetPatchFileName(ha, szFileName, szNameBuffer), SFILE_OPEN_BASE_FILE, &hPatchFile))
- {
- // Remember the new version
- hfPatch = (TMPQFile *)hPatchFile;
-
- // We should not find patch file
- assert((hfPatch->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) != 0);
-
- // Attach the patch to the base file
- hf->hfPatch = hfPatch;
- hf = hfPatch;
- }
- }
- }
- }
- else
- {
- SetLastError(ERROR_FILE_NOT_FOUND);
- }
-
- // Give the updated base MPQ
- if(PtrFile != NULL)
- *PtrFile = (HANDLE)hfBase;
- return (hfBase != NULL);
-}
-
-/*****************************************************************************/
-/* Public functions */
-/*****************************************************************************/
-
-//-----------------------------------------------------------------------------
-// SFileEnumLocales enums all locale versions within MPQ.
-// Functions fills all available language identifiers on a file into the buffer
-// pointed by plcLocales. There must be enough entries to copy the localed,
-// otherwise the function returns ERROR_INSUFFICIENT_BUFFER.
-
-DWORD WINAPI SFileEnumLocales(
- HANDLE hMpq,
- const char * szFileName,
- LCID * PtrLocales,
- LPDWORD PtrMaxLocales,
- DWORD dwSearchScope)
-{
- TMPQArchive * ha = (TMPQArchive *)hMpq;
- TMPQHash * pFirstHash;
- TMPQHash * pHash;
- DWORD dwFileIndex = 0;
- DWORD dwMaxLocales;
- DWORD dwLocales = 0;
-
- // Test the parameters
- if(!IsValidMpqHandle(hMpq))
- return ERROR_INVALID_HANDLE;
- if(szFileName == NULL || *szFileName == 0)
- return ERROR_INVALID_PARAMETER;
- if(ha->pHashTable == NULL)
- return ERROR_NOT_SUPPORTED;
- if(PtrMaxLocales == NULL)
- return ERROR_INVALID_PARAMETER;
- if(IsPseudoFileName(szFileName, &dwFileIndex))
- return ERROR_INVALID_PARAMETER;
-
- // Keep compiler happy
- dwMaxLocales = PtrMaxLocales[0];
- dwSearchScope = dwSearchScope;
-
- // Parse all files with that name
- pFirstHash = pHash = GetFirstHashEntry(ha, szFileName);
- while(pHash != NULL)
- {
- // Put the locales to the buffer
- if(PtrLocales != NULL && dwLocales < dwMaxLocales)
- *PtrLocales++ = pHash->lcLocale;
- dwLocales++;
-
- // Get the next locale
- pHash = GetNextHashEntry(ha, pFirstHash, pHash);
- }
-
- // Give the caller the number of locales and return
- PtrMaxLocales[0] = dwLocales;
- return (dwLocales <= dwMaxLocales) ? ERROR_SUCCESS : ERROR_INSUFFICIENT_BUFFER;
-}
-
-//-----------------------------------------------------------------------------
-// SFileOpenFileEx
-//
-// hMpq - Handle of opened MPQ archive
-// szFileName - Name of file to open
-// dwSearchScope - Where to search
-// PtrFile - Pointer to store opened file handle
-
-bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * PtrFile)
-{
- TMPQArchive * ha = IsValidMpqHandle(hMpq);
- TFileEntry * pFileEntry = NULL;
- TMPQFile * hf = NULL;
- DWORD dwHashIndex = HASH_ENTRY_FREE;
- DWORD dwFileIndex = 0;
- DWORD dwErrCode = ERROR_SUCCESS;
- bool bOpenByIndex = false;
-
- // Don't accept NULL pointer to file handle
- if(szFileName == NULL || *szFileName == 0)
- dwErrCode = ERROR_INVALID_PARAMETER;
-
- // When opening a file from MPQ, the handle must be valid
- if(dwSearchScope != SFILE_OPEN_LOCAL_FILE && ha == NULL)
- dwErrCode = ERROR_INVALID_HANDLE;
-
- // When not checking for existence, the pointer to file handle must be valid
- if(dwSearchScope != SFILE_OPEN_CHECK_EXISTS && PtrFile == NULL)
- dwErrCode = ERROR_INVALID_PARAMETER;
-
- // Prepare the file opening
- if(dwErrCode == ERROR_SUCCESS)
- {
- switch(dwSearchScope)
- {
- case SFILE_OPEN_FROM_MPQ:
- case SFILE_OPEN_BASE_FILE:
- case SFILE_OPEN_CHECK_EXISTS:
-
- // If this MPQ has no patches, open the file from this MPQ directly
- if(ha->haPatch == NULL || dwSearchScope == SFILE_OPEN_BASE_FILE)
- {
- pFileEntry = GetFileEntryLocale2(ha, szFileName, g_lcFileLocale, &dwHashIndex);
- }
-
- // If this MPQ is a patched archive, open the file as patched
- else
- {
- return OpenPatchedFile(hMpq, szFileName, PtrFile);
- }
- break;
-
- case SFILE_OPEN_ANY_LOCALE:
-
- // This open option is reserved for opening MPQ internal listfile.
- // No argument validation. Tries to open file with neutral locale first,
- // then any other available.
- pFileEntry = GetFileEntryLocale2(ha, szFileName, 0, &dwHashIndex);
- break;
-
- case SFILE_OPEN_LOCAL_FILE:
-
- // Open a local file
- return OpenLocalFile(szFileName, PtrFile);
-
- default:
-
- // Don't accept any other value
- dwErrCode = ERROR_INVALID_PARAMETER;
- break;
- }
- }
-
- // Check whether the file really exists in the MPQ
- if(dwErrCode == ERROR_SUCCESS)
- {
- // If we didn't find the file, try to open it using pseudo file name ("File
- if (pFileEntry == NULL || (pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0)
- {
- // Check the pseudo-file name ("File00000001.ext")
- if ((bOpenByIndex = IsPseudoFileName(szFileName, &dwFileIndex)) == true)
- {
- // Get the file entry for the file
- if (dwFileIndex < ha->dwFileTableSize)
- {
- pFileEntry = ha->pFileTable + dwFileIndex;
- }
- }
-
- // Still not found?
- if (pFileEntry == NULL)
- {
- dwErrCode = ERROR_FILE_NOT_FOUND;
- }
- }
-
- // Perform some checks of invalid files
- if (pFileEntry != NULL)
- {
- // MPQ protectors use insanely amount of fake files, often with very high size.
- // We won't open any files whose compressed size is bigger than archive size
- // If the file is not compressed, its size cannot be bigger than archive size
- if ((pFileEntry->dwFlags & MPQ_FILE_COMPRESS_MASK) == 0 && (pFileEntry->dwFileSize > ha->FileSize))
- {
- dwErrCode = ERROR_FILE_CORRUPT;
- pFileEntry = NULL;
- }
-
- // Ignore unknown loading flags (example: MPQ_2016_v1_WME4_4.w3x)
-// if(pFileEntry->dwFlags & ~MPQ_FILE_VALID_FLAGS)
-// {
-// dwErrCode = ERROR_NOT_SUPPORTED;
-// pFileEntry = NULL;
-// }
- }
- }
-
- // Did the caller just wanted to know if the file exists?
- if(dwErrCode == ERROR_SUCCESS && dwSearchScope != SFILE_OPEN_CHECK_EXISTS)
- {
- // Allocate file handle
- hf = CreateFileHandle(ha, pFileEntry);
- if(hf != NULL)
- {
- // Get the hash index for the file
- if(ha->pHashTable != NULL && dwHashIndex == HASH_ENTRY_FREE)
- dwHashIndex = FindHashIndex(ha, dwFileIndex);
- if(dwHashIndex != HASH_ENTRY_FREE)
- hf->pHashEntry = ha->pHashTable + dwHashIndex;
- hf->dwHashIndex = dwHashIndex;
-
- // If the MPQ has sector CRC enabled, enable if for the file
- if(ha->dwFlags & MPQ_FLAG_CHECK_SECTOR_CRC)
- hf->bCheckSectorCRCs = true;
-
- // If we know the real file name, copy it to the file entry
- if(bOpenByIndex == false)
- {
- // If there is no file name yet, allocate it
- AllocateFileName(ha, pFileEntry, szFileName);
-
- // If the file is encrypted, we should detect the file key
- if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
- {
- hf->dwFileKey = DecryptFileKey(szFileName,
- pFileEntry->ByteOffset,
- pFileEntry->dwFileSize,
- pFileEntry->dwFlags);
- }
- }
- }
- else
- {
- dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
- }
- }
-
- // Give the file entry
- if(PtrFile != NULL)
- PtrFile[0] = hf;
-
- // Return error code
- if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
- return (dwErrCode == ERROR_SUCCESS);
-}
-
-//-----------------------------------------------------------------------------
-// SFileHasFile
-//
-// hMpq - Handle of opened MPQ archive
-// szFileName - Name of file to look for
-
-bool WINAPI SFileHasFile(HANDLE hMpq, const char * szFileName)
-{
- return SFileOpenFileEx(hMpq, szFileName, SFILE_OPEN_CHECK_EXISTS, NULL);
-}
-
-//-----------------------------------------------------------------------------
-// bool WINAPI SFileCloseFile(HANDLE hFile);
-
-bool WINAPI SFileCloseFile(HANDLE hFile)
-{
- TMPQFile * hf = (TMPQFile *)hFile;
-
- if(!IsValidFileHandle(hFile))
- {
- SetLastError(ERROR_INVALID_HANDLE);
- return false;
- }
-
- // Free the structure
- FreeFileHandle(hf);
- return true;
-}