aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/CascOpenFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'dep/CascLib/src/CascOpenFile.cpp')
-rw-r--r--dep/CascLib/src/CascOpenFile.cpp346
1 files changed, 105 insertions, 241 deletions
diff --git a/dep/CascLib/src/CascOpenFile.cpp b/dep/CascLib/src/CascOpenFile.cpp
index 9db3691af48..741ab1e1005 100644
--- a/dep/CascLib/src/CascOpenFile.cpp
+++ b/dep/CascLib/src/CascOpenFile.cpp
@@ -15,196 +15,63 @@
//-----------------------------------------------------------------------------
// Local functions
-TCascFile * IsValidFileHandle(HANDLE hFile)
+PCASC_CKEY_ENTRY FindCKeyEntry_CKey(TCascStorage * hs, LPBYTE pbCKey, PDWORD PtrIndex)
{
- TCascFile * hf = (TCascFile *)hFile;
-
- return (hf != NULL && hf->hs != NULL && hf->szClassName != NULL && !strcmp(hf->szClassName, "TCascFile")) ? hf : NULL;
+ return (PCASC_CKEY_ENTRY)hs->CKeyMap.FindObject(pbCKey, PtrIndex);
}
-PCASC_INDEX_ENTRY FindIndexEntry(TCascStorage * hs, PQUERY_KEY pIndexKey)
+PCASC_CKEY_ENTRY FindCKeyEntry_EKey(TCascStorage * hs, LPBYTE pbEKey, PDWORD PtrIndex)
{
- PCASC_INDEX_ENTRY pIndexEntry = NULL;
-
- if(hs->pIndexEntryMap != NULL)
- pIndexEntry = (PCASC_INDEX_ENTRY)Map_FindObject(hs->pIndexEntryMap, pIndexKey->pbData, NULL);
-
- return pIndexEntry;
-}
-
-PCASC_ENCODING_ENTRY FindEncodingEntry(TCascStorage * hs, PQUERY_KEY pEncodingKey, PDWORD PtrIndex)
-{
- PCASC_ENCODING_ENTRY pEncodingEntry = NULL;
-
- if(hs->pEncodingMap != NULL)
- pEncodingEntry = (PCASC_ENCODING_ENTRY)Map_FindObject(hs->pEncodingMap, pEncodingKey->pbData, PtrIndex);
-
- return pEncodingEntry;
+ return (PCASC_CKEY_ENTRY)hs->EKeyMap.FindObject(pbEKey, PtrIndex);
}
-static TCascFile * CreateFileHandle(TCascStorage * hs, PCASC_INDEX_ENTRY pIndexEntry)
+bool OpenFileByCKeyEntry(TCascStorage * hs, PCASC_CKEY_ENTRY pCKeyEntry, DWORD dwOpenFlags, HANDLE * PtrFileHandle)
{
- ULONGLONG FileOffsMask = ((ULONGLONG)1 << hs->KeyMapping[0].SegmentBits) - 1;
- ULONGLONG FileOffset = ConvertBytesToInteger_5(pIndexEntry->FileOffsetBE);
- TCascFile * hf;
+ TCascFile * hf = NULL;
+ int nError = ERROR_FILE_NOT_FOUND;
- // Allocate the CASC file structure
- hf = (TCascFile *)CASC_ALLOC(TCascFile, 1);
- if(hf != NULL)
+ // If the CKey entry is NULL, we consider the file non-existant
+ if(pCKeyEntry != NULL)
{
- // Initialize the structure
- memset(hf, 0, sizeof(TCascFile));
- hf->ArchiveIndex = (DWORD)(FileOffset >> hs->KeyMapping[0].SegmentBits);
- hf->HeaderOffset = (DWORD)(FileOffset & FileOffsMask);
- hf->szClassName = "TCascFile";
-
- // Copy the file size. Note that for all files except ENCODING,
- // this is the compressed file size
- hf->CompressedSize = ConvertBytesToInteger_4_LE(pIndexEntry->FileSizeLE);
-
- // For now, we set the file size to be equal to compressed size
- // This is used when loading the ENCODING file, which does not
- // have entry in the encoding table
- hf->FileSize = hf->CompressedSize;
-
- // Increment the number of references to the archive
- hs->dwRefCount++;
- hf->hs = hs;
- }
-
- return hf;
-}
-
-static bool OpenFileByIndexKey(TCascStorage * hs, PQUERY_KEY pIndexKey, DWORD dwFlags, TCascFile ** ppCascFile)
-{
- PCASC_INDEX_ENTRY pIndexEntry;
- int nError = ERROR_SUCCESS;
-
- CASCLIB_UNUSED(dwFlags);
-
- // Find the key entry in the array of file keys
- pIndexEntry = FindIndexEntry(hs, pIndexKey);
- if(pIndexEntry == NULL)
- nError = ERROR_FILE_NOT_FOUND;
-
- // Create the file handle structure
- if(nError == ERROR_SUCCESS)
- {
- ppCascFile[0] = CreateFileHandle(hs, pIndexEntry);
- if(ppCascFile[0] == NULL)
- nError = ERROR_FILE_NOT_FOUND;
+ // Create the file handle structure
+ if((hf = new TCascFile(hs, pCKeyEntry)) != NULL)
+ {
+ hf->bVerifyIntegrity = (dwOpenFlags & CASC_STRICT_DATA_CHECK) ? true : false;
+ hf->bDownloadFileIf = (hs->dwFeatures & CASC_FEATURE_ONLINE) ? true : false;
+ nError = ERROR_SUCCESS;
+ }
+ else
+ {
+ nError = ERROR_NOT_ENOUGH_MEMORY;
+ }
}
-#ifdef CASCLIB_TEST
- if(nError == ERROR_SUCCESS && ppCascFile[0] != NULL)
- {
- ppCascFile[0]->FileSize_IdxEntry = ConvertBytesToInteger_4_LE(pIndexEntry->FileSizeLE);
- }
-#endif
+ // Give the output parameter, no matter what
+ PtrFileHandle[0] = (HANDLE)hf;
+ // Handle last error
if(nError != ERROR_SUCCESS)
SetLastError(nError);
return (nError == ERROR_SUCCESS);
}
-static bool OpenFileByEncodingKey(TCascStorage * hs, PQUERY_KEY pEncodingKey, DWORD dwFlags, TCascFile ** ppCascFile)
-{
- PCASC_ENCODING_ENTRY pEncodingEntry;
- QUERY_KEY IndexKey;
-
- // Find the encoding entry
- pEncodingEntry = FindEncodingEntry(hs, pEncodingKey, NULL);
- if(pEncodingEntry == NULL)
- {
- SetLastError(ERROR_FILE_NOT_FOUND);
- return false;
- }
-
- // Prepare the file index and open the file by index
- // Note: We don't know what to do if there is more than just one index key
- // We always take the first file present. Is that correct?
- IndexKey.pbData = GET_INDEX_KEY(pEncodingEntry);
- IndexKey.cbData = MD5_HASH_SIZE;
- if(OpenFileByIndexKey(hs, &IndexKey, dwFlags, ppCascFile))
- {
- // Check if the file handle was created
- if(ppCascFile[0] != NULL)
- {
- // Fill-in the file size. For all files except ENCODING,
- // this overrides the value stored in the index entry.
- ppCascFile[0]->FileSize = ConvertBytesToInteger_4(pEncodingEntry->FileSizeBE);
-
-#ifdef CASCLIB_TEST
- ppCascFile[0]->FileSize_EncEntry = ConvertBytesToInteger_4(pEncodingEntry->FileSizeBE);
-#endif
- return true;
- }
- }
-
- return false;
-}
-
//-----------------------------------------------------------------------------
// Public functions
-bool WINAPI CascOpenFileByIndexKey(HANDLE hStorage, PQUERY_KEY pIndexKey, DWORD dwFlags, HANDLE * phFile)
-{
- TCascStorage * hs;
-
- // Validate the storage handle
- hs = IsValidStorageHandle(hStorage);
- if(hs == NULL)
- {
- SetLastError(ERROR_INVALID_HANDLE);
- return false;
- }
-
- // Validate the other parameters
- if(pIndexKey == NULL || pIndexKey->pbData == NULL || pIndexKey->cbData == 0 || phFile == NULL)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return false;
- }
-
- // Use the internal function to open the file
- return OpenFileByIndexKey(hs, pIndexKey, dwFlags, (TCascFile **)phFile);
-}
-
-bool WINAPI CascOpenFileByEncodingKey(HANDLE hStorage, PQUERY_KEY pEncodingKey, DWORD dwFlags, HANDLE * phFile)
+bool WINAPI CascOpenFile(HANDLE hStorage, const void * pvFileName, DWORD dwLocaleFlags, DWORD dwOpenFlags, HANDLE * PtrFileHandle)
{
+ PCASC_CKEY_ENTRY pCKeyEntry = NULL;
TCascStorage * hs;
-
- // Validate the storage handle
- hs = IsValidStorageHandle(hStorage);
- if(hs == NULL)
- {
- SetLastError(ERROR_INVALID_HANDLE);
- return false;
- }
-
- // Validate the other parameters
- if(pEncodingKey == NULL || pEncodingKey->pbData == NULL || pEncodingKey->cbData == 0 || phFile == NULL)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return false;
- }
-
- // Use the internal function fo open the file
- return OpenFileByEncodingKey(hs, pEncodingKey, dwFlags, (TCascFile **)phFile);
-}
-
-bool WINAPI CascOpenFile(HANDLE hStorage, const char * szFileName, DWORD dwLocale, DWORD dwFlags, HANDLE * phFile)
-{
- TCascStorage * hs;
- QUERY_KEY EncodingKey;
- LPBYTE pbEncodingKey;
- BYTE KeyBuffer[MD5_HASH_SIZE];
+ const char * szFileName;
+ DWORD FileDataId = CASC_INVALID_ID;
+ BYTE CKeyEKeyBuffer[MD5_HASH_SIZE];
int nError = ERROR_SUCCESS;
- CASCLIB_UNUSED(dwLocale);
+ // This parameter is not used
+ CASCLIB_UNUSED(dwLocaleFlags);
// Validate the storage handle
- hs = IsValidStorageHandle(hStorage);
+ hs = TCascStorage::IsValid(hStorage);
if(hs == NULL)
{
SetLastError(ERROR_INVALID_HANDLE);
@@ -212,107 +79,104 @@ bool WINAPI CascOpenFile(HANDLE hStorage, const char * szFileName, DWORD dwLocal
}
// Validate the other parameters
- if(szFileName == NULL || szFileName[0] == 0 || phFile == NULL)
+ if(PtrFileHandle == NULL)
{
SetLastError(ERROR_INVALID_PARAMETER);
return false;
}
- // If the user is opening the file via encoding key, skip the ROOT file processing
- if((dwFlags & CASC_OPEN_BY_ENCODING_KEY) == 0)
- {
- // Let the root directory provider get us the encoding key
- pbEncodingKey = RootHandler_GetKey(hs->pRootHandler, szFileName);
- if(pbEncodingKey == NULL)
- {
+ // Retrieve the CKey/EKey from the file name in different modes
+ switch(dwOpenFlags & CASC_OPEN_TYPE_MASK)
+ {
+ case CASC_OPEN_BY_NAME:
+
+ // The 'pvFileName' must be zero terminated ANSI file name
+ szFileName = (const char *)pvFileName;
+ if(szFileName == NULL || szFileName[0] == 0)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+
+ // The first chance: Try to find the file by name (using the root handler)
+ pCKeyEntry = hs->pRootHandler->GetFile(hs, szFileName);
+ if(pCKeyEntry != NULL)
+ break;
+
+ // Second chance: If the file name is actually a file data id, we convert it to file data ID
+ if(IsFileDataIdName(szFileName, FileDataId))
+ {
+ pCKeyEntry = hs->pRootHandler->GetFile(hs, FileDataId);
+ if(pCKeyEntry != NULL)
+ break;
+ }
+
+ // Third chance: If the file name is a string representation of CKey/EKey, we try to query for CKey
+ if(IsFileCKeyEKeyName(szFileName, CKeyEKeyBuffer))
+ {
+ pCKeyEntry = FindCKeyEntry_CKey(hs, CKeyEKeyBuffer);
+ if(pCKeyEntry != NULL)
+ break;
+
+ pCKeyEntry = FindCKeyEntry_EKey(hs, CKeyEKeyBuffer);
+ if(pCKeyEntry != NULL)
+ break;
+ }
+
SetLastError(ERROR_FILE_NOT_FOUND);
return false;
- }
- // Setup the encoding key
- EncodingKey.pbData = pbEncodingKey;
- EncodingKey.cbData = MD5_HASH_SIZE;
- }
- else
- {
- // Check the length of the file name
- if(strlen(szFileName) < MD5_STRING_SIZE)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return false;
- }
+ case CASC_OPEN_BY_CKEY:
- // Convert the file name to binary blob
- EncodingKey.pbData = KeyBuffer;
- EncodingKey.cbData = MD5_HASH_SIZE;
- nError = ConvertStringToBinary(szFileName, MD5_STRING_SIZE, KeyBuffer);
- }
+ // The 'pvFileName' must be a pointer to 16-byte CKey or EKey
+ if(pvFileName == NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
- // Use the encoding key to find the file in the encoding table entry
- if(nError == ERROR_SUCCESS)
- {
- if(!OpenFileByEncodingKey(hs, &EncodingKey, dwFlags, (TCascFile **)phFile))
- {
- assert(GetLastError() != ERROR_SUCCESS);
- nError = GetLastError();
- }
- }
+ // Search the CKey map in order to find the CKey entry
+ pCKeyEntry = FindCKeyEntry_CKey(hs, (LPBYTE)pvFileName);
+ break;
-#ifdef CASCLIB_TEST
-// if(phFile[0] != NULL && pRootEntryMndx != NULL)
-// {
-// ((TCascFile *)(phFile[0]))->FileSize_RootEntry = pRootEntryMndx->FileSize;
-// }
-#endif
+ case CASC_OPEN_BY_EKEY:
- if(nError != ERROR_SUCCESS)
- SetLastError(nError);
- return (nError == ERROR_SUCCESS);
-}
+ // The 'pvFileName' must be a pointer to 16-byte CKey or EKey
+ if(pvFileName == NULL)
+ {
+ SetLastError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
-DWORD WINAPI CascGetFileId(HANDLE hStorage, const char * szFileName)
-{
- TCascStorage * hs;
+ // Search the CKey map in order to find the CKey entry
+ pCKeyEntry = FindCKeyEntry_EKey(hs, (LPBYTE)pvFileName);
+ break;
- // Validate the storage handle
- hs = IsValidStorageHandle(hStorage);
- if (hs == NULL)
- {
- SetLastError(ERROR_INVALID_HANDLE);
- return false;
- }
+ case CASC_OPEN_BY_FILEID:
- // Validate the other parameters
- if (szFileName == NULL || szFileName[0] == 0)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return false;
+ // Retrieve the file CKey/EKey
+ pCKeyEntry = hs->pRootHandler->GetFile(hs, CASC_FILE_DATA_ID_FROM_STRING(pvFileName));
+ break;
+
+ default:
+
+ // Unknown open mode
+ nError = ERROR_INVALID_PARAMETER;
+ break;
}
- return RootHandler_GetFileId(hs->pRootHandler, szFileName);
+ // Perform the open operation
+ return OpenFileByCKeyEntry(hs, pCKeyEntry, dwOpenFlags, PtrFileHandle);
}
bool WINAPI CascCloseFile(HANDLE hFile)
{
TCascFile * hf;
- hf = IsValidFileHandle(hFile);
- if(hf != NULL)
+ hf = TCascFile::IsValid(hFile);
+ if (hf != NULL)
{
- // Close (dereference) the archive handle
- if(hf->hs != NULL)
- CascCloseStorage((HANDLE)hf->hs);
- hf->hs = NULL;
-
- // Free the file cache and frame array
- if(hf->pbFileCache != NULL)
- CASC_FREE(hf->pbFileCache);
- if(hf->pFrames != NULL)
- CASC_FREE(hf->pFrames);
-
- // Free the structure itself
- hf->szClassName = NULL;
- CASC_FREE(hf);
+ delete hf;
return true;
}