aboutsummaryrefslogtreecommitdiff
path: root/src/SFileFindFile.cpp
diff options
context:
space:
mode:
authorunknown <C:\Ladik\Mail>2015-05-13 17:41:34 +0200
committerunknown <C:\Ladik\Mail>2015-05-13 17:41:34 +0200
commitc45446094e3dec085d82bcad8edda7ef41ec83c2 (patch)
tree8800f86411aa7a5f2aad0a15f0f7995f76274e20 /src/SFileFindFile.cpp
parent3cfa7f2a1a81b226f5a5c3a43f4f9bd5704881f9 (diff)
+ SFileFindFile now correctly returns hash index and locale, if exist
Diffstat (limited to 'src/SFileFindFile.cpp')
-rw-r--r--src/SFileFindFile.cpp194
1 files changed, 125 insertions, 69 deletions
diff --git a/src/SFileFindFile.cpp b/src/SFileFindFile.cpp
index 198f960..828dbfb 100644
--- a/src/SFileFindFile.cpp
+++ b/src/SFileFindFile.cpp
@@ -208,94 +208,150 @@ static TFileEntry * FindPatchEntry(TMPQArchive * ha, TFileEntry * pFileEntry)
return pPatchEntry;
}
-// Performs one MPQ search
-static int DoMPQSearch(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData)
+static bool DoMPQSearch_FileEntry(
+ TMPQSearch * hs,
+ SFILE_FIND_DATA * lpFindFileData,
+ TMPQArchive * ha,
+ TMPQHash * pHashEntry,
+ TFileEntry * pFileEntry)
{
- TMPQArchive * ha = hs->ha;
- TFileEntry * pFileTableEnd;
TFileEntry * pPatchEntry;
- TFileEntry * pFileEntry;
+ HANDLE hFile = NULL;
const char * szFileName;
- HANDLE hFile;
- char szNameBuff[MAX_PATH];
+ size_t nPrefixLength = (ha->pPatchPrefix != NULL) ? ha->pPatchPrefix->nLength : 0;
DWORD dwBlockIndex;
- size_t nPrefixLength;
+ char szNameBuff[MAX_PATH];
- // Start searching with base MPQ
- while(ha != NULL)
+ // Is it a file but not a patch file?
+ if((pFileEntry->dwFlags & hs->dwFlagMask) == MPQ_FILE_EXISTS)
{
- // Now parse the file entry table in order to get all files.
- pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
- pFileEntry = ha->pFileTable + hs->dwNextIndex;
+ // 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();
- // Get the length of the patch prefix (0 if none)
- nPrefixLength = (ha->pPatchPrefix != NULL) ? ha->pPatchPrefix->nLength : 0;
+ // Find a patch to this file
+ pPatchEntry = FindPatchEntry(ha, pFileEntry);
+ if(pPatchEntry == NULL)
+ pPatchEntry = pFileEntry;
- // Parse the file table
- while(pFileEntry < pFileTableEnd)
- {
- // Increment the next index for subsequent search
- hs->dwNextIndex++;
+ // Prepare the block index
+ dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable);
- // Is it a file but not a patch file?
- if((pFileEntry->dwFlags & hs->dwFlagMask) == MPQ_FILE_EXISTS)
+ // Get the file name. If it's not known, we will create pseudo-name
+ szFileName = pFileEntry->szFileName;
+ if(szFileName == NULL)
{
- // Now we have to check if this file was not enumerated before
- if(!FileWasFoundBefore(ha, hs, pFileEntry))
+ // Open the file by its pseudo-name.
+ sprintf(szNameBuff, "File%08u.xxx", (unsigned int)dwBlockIndex);
+ if(SFileOpenFileEx((HANDLE)hs->ha, szNameBuff, SFILE_OPEN_BASE_FILE, &hFile))
{
-// if(pFileEntry != NULL && !_stricmp(pFileEntry->szFileName, "TriggerLibs\\NativeLib.galaxy"))
-// DebugBreak();
-
- // Find a patch to this file
- pPatchEntry = FindPatchEntry(ha, pFileEntry);
- if(pPatchEntry == NULL)
- pPatchEntry = pFileEntry;
-
- // Prepare the block index
- dwBlockIndex = (DWORD)(pFileEntry - ha->pFileTable);
+ SFileGetFileName(hFile, szNameBuff);
+ szFileName = szNameBuff;
+ SFileCloseFile(hFile);
+ }
+ }
- // Get the file name. If it's not known, we will create pseudo-name
- szFileName = pFileEntry->szFileName;
- if(szFileName == NULL)
+ // 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(CheckWildCard(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)
{
- // Open the file by its pseudo-name.
- sprintf(szNameBuff, "File%08u.xxx", (unsigned int)dwBlockIndex);
- if(SFileOpenFileEx((HANDLE)hs->ha, szNameBuff, SFILE_OPEN_BASE_FILE, &hFile))
- {
- SFileGetFileName(hFile, szNameBuff);
- szFileName = szNameBuff;
- SFileCloseFile(hFile);
- }
+ lpFindFileData->dwHashIndex = (DWORD)(pHashEntry - ha->pHashTable);
+ lpFindFileData->lcLocale = pHashEntry->lcLocale;
}
- // 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(CheckWildCard(szFileName + nPrefixLength, hs->szSearchMask))
- {
- // Fill the found entry. hash entry and block index are taken from the base MPQ
- 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 the file name and plain file name
- strcpy(lpFindFileData->cFileName, szFileName + nPrefixLength);
- lpFindFileData->szPlainName = (char *)GetPlainFileName(lpFindFileData->cFileName);
- return ERROR_SUCCESS;
- }
- }
+ // Fill the file name and plain file name
+ strcpy(lpFindFileData->cFileName, szFileName + nPrefixLength);
+ lpFindFileData->szPlainName = (char *)GetPlainFileName(lpFindFileData->cFileName);
+ return true;
}
}
+ }
+ }
+
+ // Either not a valid item or was found before
+ return false;
+}
- pFileEntry++;
+static int 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 + pHash->dwBlockIndex))
+ return ERROR_SUCCESS;
}
+ }
+
+ // No more files
+ return ERROR_NO_MORE_FILES;
+}
+
+static int 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 int DoMPQSearch(TMPQSearch * hs, SFILE_FIND_DATA * lpFindFileData)
+{
+ TMPQArchive * ha = hs->ha;
+ int nError;
+
+ // 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
+ nError = (ha->pHashTable != NULL) ? DoMPQSearch_HashTable(hs, lpFindFileData, ha)
+ : DoMPQSearch_FileTable(hs, lpFindFileData, ha);
+ if(nError == ERROR_SUCCESS)
+ return nError;
// If there is no more patches in the chain, stop it.
// This also keeps hs->ha non-NULL, which is required