aboutsummaryrefslogtreecommitdiff
path: root/src/SFileOpenFileEx.cpp
diff options
context:
space:
mode:
authorLadislav Zezula <ladislav.zezula@avg.com>2013-12-05 15:59:00 +0100
committerLadislav Zezula <ladislav.zezula@avg.com>2013-12-05 15:59:00 +0100
commitc34c37b3418f1e5ab3678ce65d46f81803dec91d (patch)
tree4a9cf4c61634691981f9dc367b53dac4070f8d0d /src/SFileOpenFileEx.cpp
parentff0c25952a28a927c48738ab5207b9bda69e588a (diff)
+ StormLib 9.0 BETA
Diffstat (limited to 'src/SFileOpenFileEx.cpp')
-rw-r--r--src/SFileOpenFileEx.cpp96
1 files changed, 46 insertions, 50 deletions
diff --git a/src/SFileOpenFileEx.cpp b/src/SFileOpenFileEx.cpp
index 4180cd7..c2cf5d4 100644
--- a/src/SFileOpenFileEx.cpp
+++ b/src/SFileOpenFileEx.cpp
@@ -16,11 +16,19 @@
/* Local functions */
/*****************************************************************************/
-static const char * GetPrefixedName(TMPQArchive * ha, const char * szFileName, char * szBuffer)
+static const char * GetPatchFileName(TMPQArchive * ha, const char * szFileName, char * szBuffer)
{
if(ha->cchPatchPrefix != 0)
{
+ // Copy the patch prefix
memcpy(szBuffer, ha->szPatchPrefix, ha->cchPatchPrefix);
+
+ // 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;
+
+ // Copy the rest of the name
strcpy(szBuffer + ha->cchPatchPrefix, szFileName);
szFileName = szBuffer;
}
@@ -61,10 +69,11 @@ static bool OpenLocalFile(const char * szFileName, HANDLE * phFile)
bool OpenPatchedFile(HANDLE hMpq, const char * szFileName, DWORD dwReserved, HANDLE * phFile)
{
+ TMPQArchive * haBase = NULL;
TMPQArchive * ha = (TMPQArchive *)hMpq;
+ TFileEntry * pFileEntry;
TMPQFile * hfPatch; // Pointer to patch file
TMPQFile * hfBase = NULL; // Pointer to base open file
- TMPQFile * hfLast = NULL; // The highest file in the chain that is not patch file
TMPQFile * hf = NULL;
HANDLE hPatchFile;
char szPrefixBuffer[MAX_PATH];
@@ -72,66 +81,52 @@ bool OpenPatchedFile(HANDLE hMpq, const char * szFileName, DWORD dwReserved, HAN
// Keep this flag here for future updates
dwReserved = dwReserved;
- // First of all, try to open the original version of the file in any of the patch chain
+ // 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)
{
- // Prepare the file name with a correct prefix
- if(SFileOpenFileEx((HANDLE)ha, GetPrefixedName(ha, szFileName, szPrefixBuffer), SFILE_OPEN_BASE_FILE, (HANDLE *)&hfBase))
- {
- // The file must be a base file, i.e. without MPQ_FILE_PATCH_FILE
- if((hfBase->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
- {
- hf = hfLast = hfBase;
- break;
- }
-
- SFileCloseFile((HANDLE)hfBase);
- }
+ // If the file is there, then we remember the archive
+ pFileEntry = GetFileEntryExact(ha, GetPatchFileName(ha, szFileName, szPrefixBuffer), 0);
+ if(pFileEntry != NULL && (pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
+ haBase = ha;
- // Move to the next file in the patch chain
+ // Move to the patch archive
ha = ha->haPatch;
}
- // If we couldn't find the file in any of the patches, it doesn't exist
- if(hf == NULL)
+ // If we couldn't find the base file in any of the patches, it doesn't exist
+ if((ha = haBase) == NULL)
{
SetLastError(ERROR_FILE_NOT_FOUND);
return false;
}
- // Now keep going in the patch chain and open every patch file that is there
- for(ha = ha->haPatch; ha != NULL; ha = ha->haPatch)
+ // Now open the base file
+ if(SFileOpenFileEx((HANDLE)ha, GetPatchFileName(ha, szFileName, szPrefixBuffer), SFILE_OPEN_BASE_FILE, (HANDLE *)&hfBase))
{
- // Prepare the file name with a correct prefix
- if(SFileOpenFileEx((HANDLE)ha, GetPrefixedName(ha, szFileName, szPrefixBuffer), SFILE_OPEN_BASE_FILE, &hPatchFile))
+ // 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)
{
- // Remember the new version
- hfPatch = (TMPQFile *)hPatchFile;
+ // Prepare the file name with a correct prefix
+ if(SFileOpenFileEx((HANDLE)ha, GetPatchFileName(ha, szFileName, szPrefixBuffer), SFILE_OPEN_BASE_FILE, &hPatchFile))
+ {
+ // Remember the new version
+ hfPatch = (TMPQFile *)hPatchFile;
- // If we encountered a full replacement of the file,
- // we have to remember the highest full file
- if((hfPatch->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) == 0)
- hfLast = hfPatch;
+ // We should not find patch file
+ assert((hfPatch->pFileEntry->dwFlags & MPQ_FILE_PATCH_FILE) != 0);
- // Set current patch to base file and move on
- hf->hfPatchFile = hfPatch;
- hf = hfPatch;
+ // Attach the patch to the base file
+ hf->hfPatch = hfPatch;
+ hf = hfPatch;
+ }
}
}
- // Now we need to free all files that are below the highest unpatched version
- while(hfBase != hfLast)
- {
- TMPQFile * hfNext = hfBase->hfPatchFile;
-
- // Free the file below
- hfBase->hfPatchFile = NULL;
- FreeMPQFile(hfBase);
-
- // Move the base to the next file
- hfBase = hfNext;
- }
-
// Give the updated base MPQ
if(phFile != NULL)
*phFile = (HANDLE)hfBase;
@@ -163,7 +158,7 @@ int WINAPI SFileEnumLocales(
DWORD dwLocales = 0;
// Test the parameters
- if(!IsValidMpqHandle(ha))
+ if(!IsValidMpqHandle(hMpq))
return ERROR_INVALID_HANDLE;
if(szFileName == NULL || *szFileName == 0)
return ERROR_INVALID_PARAMETER;
@@ -236,7 +231,7 @@ bool WINAPI SFileHasFile(HANDLE hMpq, const char * szFileName)
bool bIsPseudoName;
int nError = ERROR_SUCCESS;
- if(!IsValidMpqHandle(ha))
+ if(!IsValidMpqHandle(hMpq))
nError = ERROR_INVALID_HANDLE;
if(szFileName == NULL || *szFileName == 0)
nError = ERROR_INVALID_PARAMETER;
@@ -251,7 +246,7 @@ bool WINAPI SFileHasFile(HANDLE hMpq, const char * szFileName)
while(ha != NULL)
{
// Verify presence of the file
- pFileEntry = (bIsPseudoName == false) ? GetFileEntryLocale(ha, GetPrefixedName(ha, szFileName, szPrefixBuffer), lcFileLocale)
+ pFileEntry = (bIsPseudoName == false) ? GetFileEntryLocale(ha, GetPatchFileName(ha, szFileName, szPrefixBuffer), lcFileLocale)
: GetFileEntryByIndex(ha, dwFileIndex);
// Verify the file flags
if(pFileEntry != NULL && (pFileEntry->dwFlags & dwFlagsToCheck) == MPQ_FILE_EXISTS)
@@ -301,7 +296,7 @@ bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearch
case SFILE_OPEN_FROM_MPQ:
case SFILE_OPEN_BASE_FILE:
- if(!IsValidMpqHandle(ha))
+ if(!IsValidMpqHandle(hMpq))
{
nError = ERROR_INVALID_HANDLE;
break;
@@ -369,6 +364,7 @@ bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearch
if(nError != ERROR_SUCCESS)
{
SetLastError(nError);
+ *phFile = NULL;
return false;
}
}
@@ -409,7 +405,7 @@ bool WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearch
if(bOpenByIndex == false)
{
// If there is no file name yet, allocate it
- AllocateFileName(pFileEntry, szFileName);
+ AllocateFileName(ha, pFileEntry, szFileName);
// If the file is encrypted, we should detect the file key
if(pFileEntry->dwFlags & MPQ_FILE_ENCRYPTED)
@@ -454,7 +450,7 @@ bool WINAPI SFileCloseFile(HANDLE hFile)
{
TMPQFile * hf = (TMPQFile *)hFile;
- if(!IsValidFileHandle(hf))
+ if(!IsValidFileHandle(hFile))
{
SetLastError(ERROR_INVALID_HANDLE);
return false;