aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dep/CascLib/src/CascCommon.h3
-rw-r--r--dep/CascLib/src/CascDecrypt.cpp450
-rw-r--r--dep/CascLib/src/CascFiles.cpp14
-rw-r--r--dep/CascLib/src/CascFindFile.cpp10
-rw-r--r--dep/CascLib/src/CascIndexFiles.cpp18
-rw-r--r--dep/CascLib/src/CascLib.h12
-rw-r--r--dep/CascLib/src/CascOpenFile.cpp22
-rw-r--r--dep/CascLib/src/CascOpenStorage.cpp26
-rw-r--r--dep/CascLib/src/CascPort.h33
-rw-r--r--dep/CascLib/src/CascReadFile.cpp44
-rw-r--r--dep/CascLib/src/CascRootFile_OW.cpp2
-rw-r--r--dep/CascLib/src/CascRootFile_Text.cpp2
-rw-r--r--dep/CascLib/src/CascRootFile_WoW.cpp4
-rw-r--r--dep/CascLib/src/DllMain.def (renamed from dep/CascLib/src/CascLib.def)0
-rw-r--r--dep/CascLib/src/DllMain.rc20
-rw-r--r--dep/CascLib/src/common/Common.cpp129
-rw-r--r--dep/CascLib/src/common/Common.h82
-rw-r--r--dep/CascLib/src/common/Csv.cpp2
-rw-r--r--dep/CascLib/src/common/FileStream.cpp94
-rw-r--r--dep/CascLib/src/common/ListFile.cpp6
-rw-r--r--dep/CascLib/src/common/Map.h23
-rw-r--r--dep/PackageList.txt2
-rw-r--r--src/tools/extractor_common/CascHandles.cpp12
-rw-r--r--src/tools/map_extractor/System.cpp8
-rw-r--r--src/tools/vmap4_extractor/cascfile.cpp12
-rw-r--r--src/tools/vmap4_extractor/vmapexport.cpp2
26 files changed, 597 insertions, 435 deletions
diff --git a/dep/CascLib/src/CascCommon.h b/dep/CascLib/src/CascCommon.h
index 8ef9d557a51..aa0aff876ce 100644
--- a/dep/CascLib/src/CascCommon.h
+++ b/dep/CascLib/src/CascCommon.h
@@ -329,8 +329,7 @@ struct TCascStorage
size_t EKeyLength; // EKey length from the index files
DWORD FileOffsetBits; // Number of bits in the storage offset which mean data segent offset
- CASC_ARRAY ExtraKeysList; // List additional encryption keys
- CASC_MAP EncryptionKeys; // Map of encryption keys
+ CASC_KEY_MAP KeyMap; // Growable map of encryption keys
ULONGLONG LastFailKeyName; // The value of the encryption key that recently was NOT found.
};
diff --git a/dep/CascLib/src/CascDecrypt.cpp b/dep/CascLib/src/CascDecrypt.cpp
index ccce1fc0a5b..3dbb5ce31a6 100644
--- a/dep/CascLib/src/CascDecrypt.cpp
+++ b/dep/CascLib/src/CascDecrypt.cpp
@@ -15,14 +15,7 @@
//-----------------------------------------------------------------------------
// Local structures
-#define CASC_EXTRA_KEYS 0x80
-
-typedef struct _CASC_ENCRYPTION_KEY
-{
- ULONGLONG KeyName; // "Name" of the key
- BYTE Key[CASC_KEY_LENGTH]; // The key itself
-} CASC_ENCRYPTION_KEY, *PCASC_ENCRYPTION_KEY;
-
+// For Salsa20 decryption process
typedef struct _CASC_SALSA20
{
DWORD Key[CASC_KEY_LENGTH];
@@ -30,26 +23,40 @@ typedef struct _CASC_SALSA20
} CASC_SALSA20, *PCASC_SALSA20;
+// For static-stored keys
+struct CASC_ENCRYPTION_KEY
+{
+ ULONGLONG KeyName; // "Name" of the key
+ BYTE Key[CASC_KEY_LENGTH]; // The key itself
+};
+
+// For keys inside the key map
+struct CASC_ENCRYPTION_KEY2 : public CASC_ENCRYPTION_KEY
+{
+ CASC_ENCRYPTION_KEY2 * pNext; // Pointer to the next key wihh the same hash
+};
+typedef CASC_ENCRYPTION_KEY2 * PCASC_ENCRYPTION_KEY2;
+
//-----------------------------------------------------------------------------
// Known encryption keys. See https://wowdev.wiki/CASC for updates
static const char * szKeyConstant16 = "expand 16-byte k";
static const char * szKeyConstant32 = "expand 32-byte k";
-static CASC_ENCRYPTION_KEY CascKeys[] =
+static CASC_ENCRYPTION_KEY StaticCascKeys[] =
{
// Key Name Encryption key Seen in
- // ---------------------- ------------------------------------------------------------------------------------------------ -----------
+ // ---------------------- --------------------------------------------------------------------------------------------------- -----------
// Battle.net app
{ 0x2C547F26A2613E01ULL, { 0x37, 0xC5, 0x0C, 0x10, 0x2D, 0x4C, 0x9E, 0x3A, 0x5A, 0xC0, 0x69, 0xF0, 0x72, 0xB1, 0x41, 0x7D } }, // Battle.net App Alpha 1.5.0
// Starcraft
-// { 0xD0CAE11366CEEA83ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? }}, // 1.12.3.2609 (build 45364)
+// { 0xD0CAE11366CEEA83ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 1.12.3.2609 (build 45364)
// Warcraft III Reforged beta (build)
- { 0x6E4296823E7D561EULL, { 0xC0, 0xBF, 0xA2, 0x94, 0x3A, 0xC3, 0xE9, 0x22, 0x86, 0xE4, 0x44, 0x3E, 0xE3, 0x56, 0x0D, 0x65 }}, // 1.32.0.13369 Base content (Beta Week 0)
- { 0xE04D60E31DDEBF63ULL, { 0x26, 0x3D, 0xB5, 0xC4, 0x02, 0xDA, 0x8D, 0x4D, 0x68, 0x63, 0x09, 0xCB, 0x2E, 0x32, 0x54, 0xD0 }}, // 1.32.0.13445 Base content (Beta Week 1)
+ { 0x6E4296823E7D561EULL, { 0xC0, 0xBF, 0xA2, 0x94, 0x3A, 0xC3, 0xE9, 0x22, 0x86, 0xE4, 0x44, 0x3E, 0xE3, 0x56, 0x0D, 0x65 } }, // 1.32.0.13369 Base content (Beta Week 0)
+ { 0xE04D60E31DDEBF63ULL, { 0x26, 0x3D, 0xB5, 0xC4, 0x02, 0xDA, 0x8D, 0x4D, 0x68, 0x63, 0x09, 0xCB, 0x2E, 0x32, 0x54, 0xD0 } }, // 1.32.0.13445 Base content (Beta Week 1)
// Overwatch
{ 0xFB680CB6A8BF81F3ULL, { 0x62, 0xD9, 0x0E, 0xFA, 0x7F, 0x36, 0xD7, 0x1C, 0x39, 0x8A, 0xE2, 0xF1, 0xFE, 0x37, 0xBD, 0xB9 } }, // 0.8.0.24919_retailx64 (hardcoded)
@@ -644,12 +651,98 @@ static int Decrypt_Salsa20(LPBYTE pbOutBuffer, LPBYTE pbInBuffer, size_t cbInBuf
return Decrypt(&SalsaState, pbOutBuffer, pbInBuffer, cbInBuffer);
}
-static LPBYTE CascFindKey(TCascStorage * hs, ULONGLONG KeyName)
+//-----------------------------------------------------------------------------
+// Key map implementation
+
+static PCASC_ENCRYPTION_KEY2 CreateKeyItem(ULONGLONG KeyName, LPBYTE Key)
+{
+ PCASC_ENCRYPTION_KEY2 pNewItem;
+
+ if((pNewItem = new CASC_ENCRYPTION_KEY2) != NULL)
+ {
+ memset(pNewItem, 0, sizeof(CASC_ENCRYPTION_KEY2));
+ pNewItem->KeyName = KeyName;
+ memcpy(pNewItem->Key, Key, CASC_KEY_LENGTH);
+ }
+
+ return pNewItem;
+}
+
+CASC_KEY_MAP::CASC_KEY_MAP()
+{
+ memset(HashTable, 0, sizeof(HashTable));
+}
+
+CASC_KEY_MAP::~CASC_KEY_MAP()
+{
+ PCASC_ENCRYPTION_KEY2 pNextItem;
+ PCASC_ENCRYPTION_KEY2 pKeyItem;
+
+ for(size_t i = 0; i < CASC_KEY_TABLE_SIZE; i++)
+ {
+ if((pKeyItem = (PCASC_ENCRYPTION_KEY2)HashTable[i]) != NULL)
+ {
+ while(pKeyItem != NULL)
+ {
+ pNextItem = pKeyItem->pNext;
+ delete pKeyItem;
+ pKeyItem = pNextItem;
+ }
+ }
+ }
+}
+
+LPBYTE CASC_KEY_MAP::FindKey(ULONGLONG KeyName)
{
- PCASC_ENCRYPTION_KEY pKey;
+ PCASC_ENCRYPTION_KEY2 pKeyItem = NULL;
+ size_t HashIndex = (size_t)(KeyName & CASC_KEY_TABLE_MASK);
+
+ // Check the key chain beginning at the hash table
+ pKeyItem = (PCASC_ENCRYPTION_KEY2)HashTable[HashIndex];
+ while(pKeyItem != NULL)
+ {
+ if(pKeyItem->KeyName == KeyName)
+ return pKeyItem->Key;
+ pKeyItem = pKeyItem->pNext;
+ }
- pKey = (PCASC_ENCRYPTION_KEY)hs->EncryptionKeys.FindObject(&KeyName);
- return (pKey != NULL) ? pKey->Key : NULL;
+ // Not found
+ return NULL;
+}
+
+bool CASC_KEY_MAP::AddKey(ULONGLONG KeyName, LPBYTE Key)
+{
+ PCASC_ENCRYPTION_KEY2 pKeyItem;
+ PCASC_ENCRYPTION_KEY2 pNewItem;
+ size_t HashIndex = (size_t)(KeyName & CASC_KEY_TABLE_MASK);
+
+ // Is the key already there?
+ if(FindKey(KeyName) == NULL)
+ {
+ // Create new key item
+ if((pNewItem = CreateKeyItem(KeyName, Key)) == NULL)
+ return false;
+
+ if(HashTable[HashIndex] != NULL)
+ {
+ // Get the last-in-chain key item
+ pKeyItem = (PCASC_ENCRYPTION_KEY2)(HashTable[HashIndex]);
+ while(pKeyItem->pNext != NULL)
+ pKeyItem = pKeyItem->pNext;
+
+ // Insert the key to the chain
+ pKeyItem->pNext = pNewItem;
+ return true;
+ }
+ else
+ {
+ HashTable[HashIndex] = pNewItem;
+ return true;
+ }
+ }
+
+ // Already exists, it's OK
+ return true;
}
//-----------------------------------------------------------------------------
@@ -657,22 +750,197 @@ static LPBYTE CascFindKey(TCascStorage * hs, ULONGLONG KeyName)
DWORD CascLoadEncryptionKeys(TCascStorage * hs)
{
- size_t nKeyCount = (sizeof(CascKeys) / sizeof(CASC_ENCRYPTION_KEY));
- size_t nMaxItems = nKeyCount + CASC_EXTRA_KEYS;
- DWORD dwErrCode;
+ for(size_t i = 0; i < _countof(StaticCascKeys); i++)
+ {
+ if(!hs->KeyMap.AddKey(StaticCascKeys[i].KeyName, StaticCascKeys[i].Key))
+ {
+ return ERROR_NOT_ENOUGH_MEMORY;
+ }
+ }
+
+ return ERROR_SUCCESS;
+}
+
+bool WINAPI CascAddEncryptionKey(HANDLE hStorage, ULONGLONG KeyName, LPBYTE Key)
+{
+ TCascStorage * hs;
+
+ // Validate the storage handle
+ hs = TCascStorage::IsValid(hStorage);
+ if (hs == NULL)
+ {
+ SetCascError(ERROR_INVALID_HANDLE);
+ return false;
+ }
+
+ // Add the key to the map and return result
+ return hs->KeyMap.AddKey(KeyName, Key);
+}
+
+bool WINAPI CascAddStringEncryptionKey(HANDLE hStorage, ULONGLONG KeyName, LPCSTR szKey)
+{
+ BYTE Key[CASC_KEY_LENGTH];
+
+ // Check the length of the string key
+ if(strlen(szKey) != CASC_KEY_LENGTH * 2)
+ {
+ SetCascError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+
+ // Convert the string key to the binary array
+ if(BinaryFromString(szKey, CASC_KEY_LENGTH * 2, Key) != ERROR_SUCCESS)
+ {
+ SetCascError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+
+ return CascAddEncryptionKey(hStorage, KeyName, Key);
+}
- // Create fast map of KeyName -> Key
- dwErrCode = hs->EncryptionKeys.Create(nMaxItems, sizeof(ULONGLONG), FIELD_OFFSET(CASC_ENCRYPTION_KEY, KeyName));
- if(dwErrCode != ERROR_SUCCESS)
- return dwErrCode;
+LPBYTE WINAPI CascFindEncryptionKey(HANDLE hStorage, ULONGLONG KeyName)
+{
+ TCascStorage * hs;
- // Insert all static keys
- for (size_t i = 0; i < nKeyCount; i++)
- hs->EncryptionKeys.InsertObject(&CascKeys[i], &CascKeys[i].KeyName);
+ // Validate the storage handle
+ hs = TCascStorage::IsValid(hStorage);
+ if (hs == NULL)
+ {
+ SetCascError(ERROR_INVALID_HANDLE);
+ return NULL;
+ }
- // Create array for extra keys
- dwErrCode = hs->ExtraKeysList.Create<CASC_ENCRYPTION_KEY>(CASC_EXTRA_KEYS);
- return dwErrCode;
+ // Return the result from the map's search function
+ return hs->KeyMap.FindKey(KeyName);
+}
+
+bool WINAPI CascGetNotFoundEncryptionKey(HANDLE hStorage, ULONGLONG * KeyName)
+{
+ TCascStorage * hs;
+
+ // Validate the storage handle
+ if ((hs = TCascStorage::IsValid(hStorage)) == NULL)
+ {
+ SetCascError(ERROR_INVALID_HANDLE);
+ return false;
+ }
+
+ // If there was no decryption key error, just return false with ERROR_SUCCESS
+ if(hs->LastFailKeyName == 0)
+ {
+ SetCascError(ERROR_SUCCESS);
+ return false;
+ }
+
+ // Give the name of the key that failed most recently
+ KeyName[0] = hs->LastFailKeyName;
+ return true;
+}
+
+bool WINAPI CascImportKeysFromString(HANDLE hStorage, LPCSTR szKeyList)
+{
+ // Verify parameters
+ if(TCascStorage::IsValid(hStorage) == NULL || szKeyList == NULL || szKeyList[0] == 0)
+ {
+ SetCascError(ERROR_INVALID_PARAMETER);
+ return false;
+ }
+
+ // Parse text file
+ while(szKeyList[0])
+ {
+ ULONGLONG KeyName = 0;
+ DWORD dwErrCode;
+ BYTE KeyValue[CASC_KEY_LENGTH];
+
+ // Capture key name
+ dwErrCode = ConvertStringToInt(szKeyList, 0, KeyName, &szKeyList);
+ if(dwErrCode != ERROR_SUCCESS)
+ {
+ SetCascError(dwErrCode);
+ return false;
+ }
+
+ // TACT key list downloaded from https://wow.tools/api.php?type=tactkeys ends with a single zero
+ if(KeyName == 0)
+ break;
+
+ // We only expect spaces and tabs at this point. Anything else will lead
+ // to end of the loop.
+ while(szKeyList[0] == 0x09 || szKeyList[0] == 0x20)
+ szKeyList++;
+ if(szKeyList[0] == 0x0A || szKeyList[0] == 0x0D)
+ break;
+
+ // Convert the string to binary
+ dwErrCode = BinaryFromString(szKeyList, CASC_KEY_LENGTH * 2, KeyValue);
+ if(dwErrCode != ERROR_SUCCESS)
+ {
+ SetCascError(dwErrCode);
+ return false;
+ }
+
+ // Add the encryption key. Note that if the key already exists with the same value,
+ // CascAddEncryptionKey will consider it success.
+ if(!CascAddEncryptionKey(hStorage, KeyName, KeyValue))
+ return false;
+
+ // Move to the next key
+ while(szKeyList[0] != 0 && szKeyList[0] != 0x0A && szKeyList[0] != 0x0D)
+ szKeyList++;
+ while(szKeyList[0] == 0x0A || szKeyList[0] == 0x0D)
+ szKeyList++;
+ }
+
+ return true;
+}
+
+bool WINAPI CascImportKeysFromFile(HANDLE hStorage, LPCTSTR szFileName)
+{
+ TFileStream * pFileStream;
+ ULONGLONG FileSize = 0;
+ LPSTR szKeyList;
+ bool bResult = false;
+
+ // Open the file
+ if((pFileStream = FileStream_OpenFile(szFileName, STREAM_FLAG_READ_ONLY)) != NULL)
+ {
+ // Load the entire file to memory, up to 10 MB
+ if(FileStream_GetSize(pFileStream, &FileSize) && FileSize < 0xA00000)
+ {
+ DWORD FileSize32 = (DWORD)FileSize;
+
+ // Allocate buffer for the key stream
+ if((szKeyList = CASC_ALLOC<char>(FileSize32 + 1)) != NULL)
+ {
+ // Read the entire file and terminate it with zero
+ FileStream_Read(pFileStream, NULL, szKeyList, FileSize32);
+ szKeyList[FileSize] = 0;
+
+ // Import the buffer
+ bResult = CascImportKeysFromString(hStorage, szKeyList);
+ CASC_FREE(szKeyList);
+ }
+ }
+ else
+ SetCascError(ERROR_FILE_TOO_LARGE);
+
+ FileStream_Close(pFileStream);
+ }
+
+ return bResult;
+}
+
+DWORD CascDirectCopy(LPBYTE pbOutBuffer, PDWORD pcbOutBuffer, LPBYTE pbInBuffer, DWORD cbInBuffer)
+{
+ // Check the buffer size
+ if((cbInBuffer - 1) > pcbOutBuffer[0])
+ return ERROR_INSUFFICIENT_BUFFER;
+
+ // Copy the data
+ memcpy(pbOutBuffer, pbInBuffer, cbInBuffer);
+ pcbOutBuffer[0] = cbInBuffer;
+ return ERROR_SUCCESS;
}
DWORD CascDecrypt(TCascStorage * hs, LPBYTE pbOutBuffer, PDWORD pcbOutBuffer, LPBYTE pbInBuffer, DWORD cbInBuffer, DWORD dwFrameIndex)
@@ -726,7 +994,7 @@ DWORD CascDecrypt(TCascStorage * hs, LPBYTE pbOutBuffer, PDWORD pcbOutBuffer, LP
return ERROR_INSUFFICIENT_BUFFER;
// Check if we know the key
- pbKey = CascFindKey(hs, KeyName);
+ pbKey = hs->KeyMap.FindKey(KeyName);
if(pbKey == NULL)
{
hs->LastFailKeyName = KeyName;
@@ -754,126 +1022,10 @@ DWORD CascDecrypt(TCascStorage * hs, LPBYTE pbOutBuffer, PDWORD pcbOutBuffer, LP
pcbOutBuffer[0] = (DWORD)(pbBufferEnd - pbInBuffer);
return ERROR_SUCCESS;
-// case 'A':
-// return ERROR_NOT_SUPPORTED;
+ // case 'A':
+ // return ERROR_NOT_SUPPORTED;
}
assert(false);
return ERROR_NOT_SUPPORTED;
}
-
-DWORD CascDirectCopy(LPBYTE pbOutBuffer, PDWORD pcbOutBuffer, LPBYTE pbInBuffer, DWORD cbInBuffer)
-{
- // Check the buffer size
- if((cbInBuffer - 1) > pcbOutBuffer[0])
- return ERROR_INSUFFICIENT_BUFFER;
-
- // Copy the data
- memcpy(pbOutBuffer, pbInBuffer, cbInBuffer);
- pcbOutBuffer[0] = cbInBuffer;
- return ERROR_SUCCESS;
-}
-
-//-----------------------------------------------------------------------------
-// Public functions
-
-bool WINAPI CascAddEncryptionKey(HANDLE hStorage, ULONGLONG KeyName, LPBYTE Key)
-{
- PCASC_ENCRYPTION_KEY pEncKey;
- TCascStorage * hs;
-
- // Validate the storage handle
- hs = TCascStorage::IsValid(hStorage);
- if (hs == NULL)
- {
- SetLastError(ERROR_INVALID_HANDLE);
- return false;
- }
-
- // Don't allow more than CASC_EXTRA_KEYS keys
- if (hs->ExtraKeysList.ItemCount() >= CASC_EXTRA_KEYS)
- {
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
- return false;
- }
-
- // Insert the key to the array
- pEncKey = (PCASC_ENCRYPTION_KEY)hs->ExtraKeysList.Insert(1);
- if (pEncKey == NULL)
- {
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- return false;
- }
-
- // Fill the key
- memcpy(pEncKey->Key, Key, sizeof(pEncKey->Key));
- pEncKey->KeyName = KeyName;
-
- // Also insert the key to the map
- if (!hs->EncryptionKeys.InsertObject(pEncKey, &pEncKey->KeyName))
- {
- SetLastError(ERROR_ALREADY_EXISTS);
- return false;
- }
-
- return true;
-}
-
-bool WINAPI CascAddStringEncryptionKey(HANDLE hStorage, ULONGLONG KeyName, LPCSTR szKey)
-{
- BYTE Key[CASC_KEY_LENGTH];
-
- // Check the length of the string key
- if(strlen(szKey) != CASC_KEY_LENGTH * 2)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return false;
- }
-
- // Convert the string key to the binary array
- if(ConvertStringToBinary(szKey, CASC_KEY_LENGTH * 2, Key) != ERROR_SUCCESS)
- {
- SetLastError(ERROR_INVALID_PARAMETER);
- return false;
- }
-
- return CascAddEncryptionKey(hStorage, KeyName, Key);
-}
-
-LPBYTE WINAPI CascFindEncryptionKey(HANDLE hStorage, ULONGLONG KeyName)
-{
- TCascStorage * hs;
-
- // Validate the storage handle
- hs = TCascStorage::IsValid(hStorage);
- if (hs == NULL)
- {
- SetLastError(ERROR_INVALID_HANDLE);
- return NULL;
- }
-
- return CascFindKey(hs, KeyName);
-}
-
-bool WINAPI CascGetNotFoundEncryptionKey(HANDLE hStorage, ULONGLONG * KeyName)
-{
- TCascStorage * hs;
-
- // Validate the storage handle
- if ((hs = TCascStorage::IsValid(hStorage)) == NULL)
- {
- SetLastError(ERROR_INVALID_HANDLE);
- return false;
- }
-
- // If there was no decryption key error, just return false with ERROR_SUCCESS
- if(hs->LastFailKeyName == 0)
- {
- SetLastError(ERROR_SUCCESS);
- return false;
- }
-
- // Give the name of the key that failed most recently
- KeyName[0] = hs->LastFailKeyName;
- return true;
-}
diff --git a/dep/CascLib/src/CascFiles.cpp b/dep/CascLib/src/CascFiles.cpp
index c1a9e648c72..596a07d3362 100644
--- a/dep/CascLib/src/CascFiles.cpp
+++ b/dep/CascLib/src/CascFiles.cpp
@@ -153,7 +153,7 @@ static const char * CaptureSingleHash(const char * szDataPtr, const char * szDat
return NULL;
// Give the values
- ConvertStringToBinary(szHashString, HashStringLength, HashValue);
+ BinaryFromString(szHashString, HashStringLength, HashValue);
return szDataPtr;
}
@@ -717,7 +717,7 @@ static DWORD ParseFile_VersionsDb(TCascStorage * hs, CASC_CSV & Csv)
{
// If we have manually given build key, override the value
if(hs->szBuildKey != NULL)
- dwErrCode = ConvertStringToBinary(hs->szBuildKey, MD5_STRING_SIZE, hs->CdnBuildKey.pbData);
+ dwErrCode = BinaryFromString(hs->szBuildKey, MD5_STRING_SIZE, hs->CdnBuildKey.pbData);
return dwErrCode;
}
@@ -1113,7 +1113,7 @@ static DWORD DownloadFile(
}
else
{
- dwErrCode = GetLastError();
+ dwErrCode = GetCascError();
}
return dwErrCode;
@@ -1489,7 +1489,7 @@ LPBYTE LoadInternalFileToMemory(TCascStorage * hs, PCASC_CKEY_ENTRY pCKeyEntry,
}
else
{
- dwErrCode = GetLastError();
+ dwErrCode = GetCascError();
}
// Handle errors
@@ -1500,7 +1500,7 @@ LPBYTE LoadInternalFileToMemory(TCascStorage * hs, PCASC_CKEY_ENTRY pCKeyEntry,
cbFileData = 0;
// Set the last error
- SetLastError(dwErrCode);
+ SetCascError(dwErrCode);
}
// Give the loaded file length
@@ -1540,13 +1540,13 @@ LPBYTE LoadFileToMemory(LPCTSTR szFileName, DWORD * pcbFileData)
}
else
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ SetCascError(ERROR_NOT_ENOUGH_MEMORY);
cbFileData = 0;
}
}
else
{
- SetLastError(ERROR_BAD_FORMAT);
+ SetCascError(ERROR_BAD_FORMAT);
cbFileData = 0;
assert(false);
}
diff --git a/dep/CascLib/src/CascFindFile.cpp b/dep/CascLib/src/CascFindFile.cpp
index 9694ae5e878..76efa12ae43 100644
--- a/dep/CascLib/src/CascFindFile.cpp
+++ b/dep/CascLib/src/CascFindFile.cpp
@@ -206,9 +206,13 @@ HANDLE WINAPI CascFindFirstFile(
// Check parameters
if((hs = TCascStorage::IsValid(hStorage)) == NULL)
dwErrCode = ERROR_INVALID_HANDLE;
- if(szMask == NULL || pFindData == NULL)
+ if(pFindData == NULL)
dwErrCode = ERROR_INVALID_PARAMETER;
+ // Supply default mask, if needed
+ if(szMask == NULL || szMask[0] == 0)
+ szMask = "*";
+
// Init the search structure and search handle
if(dwErrCode == ERROR_SUCCESS)
{
@@ -243,7 +247,7 @@ bool WINAPI CascFindNextFile(
pSearch = TCascSearch::IsValid(hFind);
if(pSearch == NULL || pFindData == NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -258,7 +262,7 @@ bool WINAPI CascFindClose(HANDLE hFind)
pSearch = TCascSearch::IsValid(hFind);
if(pSearch == NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
diff --git a/dep/CascLib/src/CascIndexFiles.cpp b/dep/CascLib/src/CascIndexFiles.cpp
index bfcee15330b..bc50f9f25bb 100644
--- a/dep/CascLib/src/CascIndexFiles.cpp
+++ b/dep/CascLib/src/CascIndexFiles.cpp
@@ -50,8 +50,8 @@ static bool IndexDirectory_OnFileFound(
{
TCascStorage * hs = (TCascStorage *)pvContext;
PCASC_INDEX pIndexFile;
- DWORD IndexValue = 0;
DWORD IndexVersion = 0;
+ DWORD IndexValue = 0;
// Auto-detect the format of the index file name
if(hs->szIndexFormat == NULL)
@@ -71,9 +71,9 @@ static bool IndexDirectory_OnFileFound(
return false;
// Get the main index from the first two digits
- if(ConvertStringToInt32(szFileName, 2, &IndexValue) != ERROR_SUCCESS)
+ if(ConvertStringToInt(szFileName + 0, 2, IndexValue) != ERROR_SUCCESS)
return false;
- if(ConvertStringToInt32(szFileName + 2, 8, &IndexVersion) != ERROR_SUCCESS)
+ if(ConvertStringToInt(szFileName + 2, 8, IndexVersion) != ERROR_SUCCESS)
return false;
}
else if(hs->szIndexFormat == szIndexFormat_V1)
@@ -83,9 +83,9 @@ static bool IndexDirectory_OnFileFound(
return false;
// Get the main index from the first two digits
- if(ConvertDigitToInt32(szFileName + 6, &IndexValue) != ERROR_SUCCESS)
+ if(ConvertStringToInt(szFileName + 6, 1, IndexValue) != ERROR_SUCCESS)
return false;
- if(ConvertDigitToInt32(szFileName + 7, &IndexVersion) != ERROR_SUCCESS)
+ if(ConvertStringToInt(szFileName + 7, 1, IndexVersion) != ERROR_SUCCESS)
return false;
}
else
@@ -316,10 +316,8 @@ static DWORD LoadIndexItems(TCascStorage * hs, CASC_INDEX_HEADER & InHeader, EKE
while((pbEKeyEntry + EntryLength) <= pbEKeyEnd)
{
- // ENCODING, DOWNLOAD, ROOT in Warcraft III Reforged build 14481
- BREAK_ON_XKEY3(pbEKeyEntry, 0xcd, 0x3b, 0xd8);
- BREAK_ON_XKEY3(pbEKeyEntry, 0xdb, 0xfa, 0x35);
- BREAK_ON_XKEY3(pbEKeyEntry, 0x5c, 0xe8, 0x48);
+ // ENCODING for Starcraft II Beta
+ BREAK_ON_XKEY3(pbEKeyEntry, 0x8b, 0x0d, 0x9a);
if(!PfnEKeyEntry(hs, InHeader, pbEKeyEntry))
return ERROR_INDEX_PARSING_DONE;
@@ -581,7 +579,7 @@ static DWORD LoadLocalIndexFiles(TCascStorage * hs)
if((IndexFile.pbFileData = LoadFileToMemory(IndexFile.szFileName, &cbFileData)) == NULL)
{
// Storages downloaded by Blizzget tool don't have all index files present
- if((dwErrCode = GetLastError()) == ERROR_FILE_NOT_FOUND)
+ if((dwErrCode = GetCascError()) == ERROR_FILE_NOT_FOUND)
{
dwErrCode = ERROR_SUCCESS;
break;
diff --git a/dep/CascLib/src/CascLib.h b/dep/CascLib/src/CascLib.h
index b9a3ef7de0d..75f8729e75f 100644
--- a/dep/CascLib/src/CascLib.h
+++ b/dep/CascLib/src/CascLib.h
@@ -369,18 +369,16 @@ bool WINAPI CascFindClose(HANDLE hFind);
bool WINAPI CascAddEncryptionKey(HANDLE hStorage, ULONGLONG KeyName, LPBYTE Key);
bool WINAPI CascAddStringEncryptionKey(HANDLE hStorage, ULONGLONG KeyName, LPCSTR szKey);
+bool WINAPI CascImportKeysFromString(HANDLE hStorage, LPCSTR szKeyList);
+bool WINAPI CascImportKeysFromFile(HANDLE hStorage, LPCTSTR szFileName);
LPBYTE WINAPI CascFindEncryptionKey(HANDLE hStorage, ULONGLONG KeyName);
bool WINAPI CascGetNotFoundEncryptionKey(HANDLE hStorage, ULONGLONG * KeyName);
//-----------------------------------------------------------------------------
-// GetLastError/SetLastError support for non-Windows platform
+// Error code support
-#ifndef PLATFORM_WINDOWS
-
-DWORD GetLastError();
-void SetLastError(DWORD dwErrCode);
-
-#endif // PLATFORM_WINDOWS
+void SetCascError(DWORD dwErrCode);
+DWORD GetCascError();
#ifdef __cplusplus
} // extern "C"
diff --git a/dep/CascLib/src/CascOpenFile.cpp b/dep/CascLib/src/CascOpenFile.cpp
index 8ff9739d6e3..dd1d5407575 100644
--- a/dep/CascLib/src/CascOpenFile.cpp
+++ b/dep/CascLib/src/CascOpenFile.cpp
@@ -85,7 +85,7 @@ DWORD TCascFile::OpenFileSpans(LPCTSTR szSpanList)
pFileSpan[i].pStream = pStream = FileStream_OpenFile(szSpanList, BASE_PROVIDER_FILE | STREAM_PROVIDER_FLAT);
if(pFileSpan[i].pStream == NULL)
{
- dwErrCode = GetLastError();
+ dwErrCode = GetCascError();
break;
}
@@ -215,7 +215,7 @@ bool OpenFileByCKeyEntry(TCascStorage * hs, PCASC_CKEY_ENTRY pCKeyEntry, DWORD d
// Handle last error
if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
+ SetCascError(dwErrCode);
return (dwErrCode == ERROR_SUCCESS);
}
@@ -275,7 +275,7 @@ bool OpenLocalFile(LPCTSTR szFileName, DWORD dwOpenFlags, HANDLE * PtrFileHandle
// Handle last error
if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
+ SetCascError(dwErrCode);
return (dwErrCode == ERROR_SUCCESS);
}
@@ -318,14 +318,14 @@ bool WINAPI CascOpenFile(HANDLE hStorage, const void * pvFileName, DWORD dwLocal
hs = TCascStorage::IsValid(hStorage);
if(hs == NULL)
{
- SetLastError(ERROR_INVALID_HANDLE);
+ SetCascError(ERROR_INVALID_HANDLE);
return false;
}
// Validate the other parameters
if(PtrFileHandle == NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -338,7 +338,7 @@ bool WINAPI CascOpenFile(HANDLE hStorage, const void * pvFileName, DWORD dwLocal
szFileName = (const char *)pvFileName;
if(szFileName == NULL || szFileName[0] == 0)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -367,7 +367,7 @@ bool WINAPI CascOpenFile(HANDLE hStorage, const void * pvFileName, DWORD dwLocal
break;
}
- SetLastError(ERROR_FILE_NOT_FOUND);
+ SetCascError(ERROR_FILE_NOT_FOUND);
return false;
case CASC_OPEN_BY_CKEY:
@@ -375,7 +375,7 @@ bool WINAPI CascOpenFile(HANDLE hStorage, const void * pvFileName, DWORD dwLocal
// The 'pvFileName' must be a pointer to 16-byte CKey or EKey
if(pvFileName == NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -388,7 +388,7 @@ bool WINAPI CascOpenFile(HANDLE hStorage, const void * pvFileName, DWORD dwLocal
// The 'pvFileName' must be a pointer to 16-byte CKey or EKey
if(pvFileName == NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -418,7 +418,7 @@ bool WINAPI CascOpenLocalFile(LPCTSTR szFileName, DWORD dwOpenFlags, HANDLE * Pt
// Verify parameters
if(szFileName == NULL || szFileName[0] == 0 || PtrFileHandle == NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -436,7 +436,7 @@ bool WINAPI CascCloseFile(HANDLE hFile)
return true;
}
- SetLastError(ERROR_INVALID_HANDLE);
+ SetCascError(ERROR_INVALID_HANDLE);
return false;
}
diff --git a/dep/CascLib/src/CascOpenStorage.cpp b/dep/CascLib/src/CascOpenStorage.cpp
index d48ae50342f..00b3797eb68 100644
--- a/dep/CascLib/src/CascOpenStorage.cpp
+++ b/dep/CascLib/src/CascOpenStorage.cpp
@@ -150,7 +150,7 @@ void * ProbeOutputBuffer(void * pvBuffer, size_t cbLength, size_t cbMinLength, s
// Verify the output length
if(cbLength < cbMinLength)
{
- SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ SetCascError(ERROR_INSUFFICIENT_BUFFER);
pvBuffer = NULL;
}
@@ -519,7 +519,7 @@ static int LoadEncodingManifest(TCascStorage * hs)
}
else
{
- dwErrCode = GetLastError();
+ dwErrCode = GetCascError();
}
return dwErrCode;
@@ -810,7 +810,7 @@ static int LoadInstallManifest(TCascStorage * hs)
}
else
{
- dwErrCode = GetLastError();
+ dwErrCode = GetCascError();
}
return dwErrCode;
@@ -929,7 +929,7 @@ static int LoadBuildManifest(TCascStorage * hs, DWORD dwLocaleMask)
}
else
{
- dwErrCode = GetLastError();
+ dwErrCode = GetCascError();
}
return dwErrCode;
@@ -990,7 +990,7 @@ static bool GetStorageTags(TCascStorage * hs, void * pvStorageInfo, size_t cbSto
// Does the storage support tags?
if(hs->TagsArray.IsInitialized() == false)
{
- SetLastError(ERROR_NOT_SUPPORTED);
+ SetCascError(ERROR_NOT_SUPPORTED);
return false;
}
@@ -1274,14 +1274,14 @@ static LPTSTR ParseOpenParams(LPCTSTR szParams, PCASC_OPEN_STORAGE_ARGS pArgs)
// The 'szParams' must not be empty
if(szParams == NULL || pArgs == NULL || szParams[0] == 0)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return NULL;
}
// The 'pArgs' must be valid but must not contain 'szLocalPath', 'szCodeName' or 'szRegion'
if(pArgs->szLocalPath != NULL || pArgs->szCodeName != NULL || pArgs->szRegion != NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return NULL;
}
@@ -1321,7 +1321,7 @@ static LPTSTR ParseOpenParams(LPCTSTR szParams, PCASC_OPEN_STORAGE_ARGS pArgs)
}
else
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ SetCascError(ERROR_NOT_ENOUGH_MEMORY);
}
return szParamsCopy;
@@ -1353,7 +1353,7 @@ bool WINAPI CascOpenStorageEx(LPCTSTR szParams, PCASC_OPEN_STORAGE_ARGS pArgs, b
// The arguments and the local path must be entered
if(pArgs == NULL || pArgs->szLocalPath == NULL || pArgs->szLocalPath[0] == 0)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
}
@@ -1382,7 +1382,7 @@ bool WINAPI CascOpenStorageEx(LPCTSTR szParams, PCASC_OPEN_STORAGE_ARGS pArgs, b
// Return the result
if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
+ SetCascError(dwErrCode);
return (dwErrCode == ERROR_SUCCESS);
}
@@ -1425,7 +1425,7 @@ bool WINAPI CascGetStorageInfo(
hs = TCascStorage::IsValid(hStorage);
if(hs == NULL)
{
- SetLastError(ERROR_INVALID_HANDLE);
+ SetCascError(ERROR_INVALID_HANDLE);
return false;
}
@@ -1460,7 +1460,7 @@ bool WINAPI CascGetStorageInfo(
return GetStoragePathProduct(hs, pvStorageInfo, cbStorageInfo, pcbLengthNeeded);
default:
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -1482,7 +1482,7 @@ bool WINAPI CascCloseStorage(HANDLE hStorage)
hs = TCascStorage::IsValid(hStorage);
if(hs == NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
diff --git a/dep/CascLib/src/CascPort.h b/dep/CascLib/src/CascPort.h
index 8a296505c7e..030d12719f4 100644
--- a/dep/CascLib/src/CascPort.h
+++ b/dep/CascLib/src/CascPort.h
@@ -24,14 +24,8 @@
#if !defined(PLATFORM_DEFINED) && (defined(_WIN32) || defined(_WIN64))
// In MSVC 8.0, there are some functions declared as deprecated.
- #if _MSC_VER >= 1400
- #ifndef _CRT_SECURE_NO_DEPRECATE
- #define _CRT_SECURE_NO_DEPRECATE
- #endif
- #ifndef _CRT_NON_CONFORMING_SWPRINTFS
- #define _CRT_NON_CONFORMING_SWPRINTFS
- #endif
- #endif
+ #define _CRT_SECURE_NO_DEPRECATE
+ #define _CRT_NON_CONFORMING_SWPRINTFS
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
@@ -54,24 +48,14 @@
#include <sys/types.h>
#define PLATFORM_LITTLE_ENDIAN
- #ifdef _WIN64
- #define PLATFORM_64BIT
- #else
- #define PLATFORM_32BIT
- #endif
+ #pragma intrinsic(memset, memcmp, memcpy) // Make these functions intrinsic (inline)
#define URL_SEP_CHAR '/'
#define PATH_SEP_CHAR '\\'
#define PATH_SEP_STRING "\\"
#define PLATFORM_WINDOWS
- #define PLATFORM_DEFINED // The platform is known now
-
-#endif
-
-#if _MSC_VER >= 1500
- #include <intrin.h> // Support for intrinsic functions
- #pragma intrinsic(memcmp, memcpy)
+ #define PLATFORM_DEFINED // The platform is known now
#endif
#ifndef FIELD_OFFSET
@@ -161,11 +145,6 @@
// Definition of Windows-specific types for non-Windows platforms
#ifndef PLATFORM_WINDOWS
- #if __LP64__
- #define PLATFORM_64BIT
- #else
- #define PLATFORM_32BIT
- #endif
// Typedefs for ANSI C
typedef unsigned char BYTE;
@@ -188,7 +167,7 @@
typedef TCHAR * LPTSTR;
typedef const TCHAR * LPCTSTR;
- #ifdef PLATFORM_32BIT
+ #ifndef __LP64__
#define _LZMA_UINT32_IS_ULONG
#endif
@@ -254,6 +233,8 @@
#define ERROR_CAN_NOT_COMPLETE 1003 // No such error code under Linux
#define ERROR_FILE_CORRUPT 1004 // No such error code under Linux
#define ERROR_FILE_ENCRYPTED 1005 // Returned by encrypted stream when can't find file key
+ #define ERROR_FILE_TOO_LARGE 1006 // No such error code under Linux
+ #define ERROR_ARITHMETIC_OVERFLOW 1007 // The string value is too large to fit in the given type
#endif
#ifndef ERROR_FILE_INCOMPLETE
diff --git a/dep/CascLib/src/CascReadFile.cpp b/dep/CascLib/src/CascReadFile.cpp
index 5bfc4f654a0..6078c32fb7f 100644
--- a/dep/CascLib/src/CascReadFile.cpp
+++ b/dep/CascLib/src/CascReadFile.cpp
@@ -419,7 +419,7 @@ static DWORD LoadEncodedHeaderAndSpanFrames(PCASC_FILE_SPAN pFileSpan, PCASC_CKE
{
pbEncodedBuffer = ReadMissingHeaderData(pFileSpan, ReadOffset, pbEncodedBuffer, cbEncodedBuffer, cbTotalHeaderSize);
if (pbEncodedBuffer == NULL)
- dwErrCode = GetLastError();
+ dwErrCode = GetCascError();
cbEncodedBuffer = cbTotalHeaderSize;
}
@@ -673,7 +673,7 @@ static bool GetFileFullInfo(TCascFile * hf, void * pvFileInfo, size_t cbFileInfo
dwErrCode = EnsureFileSpanFramesLoaded(hf);
if(dwErrCode != ERROR_SUCCESS)
{
- SetLastError(dwErrCode);
+ SetCascError(dwErrCode);
return false;
}
@@ -717,7 +717,7 @@ static bool GetFileSpanInfo(TCascFile * hf, void * pvFileInfo, size_t cbFileInfo
dwErrCode = EnsureFileSpanFramesLoaded(hf);
if(dwErrCode != ERROR_SUCCESS)
{
- SetLastError(dwErrCode);
+ SetCascError(dwErrCode);
return false;
}
@@ -793,7 +793,7 @@ static DWORD ReadFile_WholeFile(TCascFile * hf, LPBYTE pbBuffer)
pbEncodedPtr = pbEncoded = CASC_ALLOC<BYTE>(EncodedSize);
if(pbEncoded == NULL)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ SetCascError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
@@ -850,7 +850,7 @@ static DWORD ReadFile_FrameCached(TCascFile * hf, LPBYTE pbBuffer, ULONGLONG Sta
// Check bytes read overflow
if((dwBytesRead + pFileFrame->ContentSize) < dwBytesRead)
{
- SetLastError(ERROR_BUFFER_OVERFLOW);
+ SetCascError(ERROR_BUFFER_OVERFLOW);
return 0;
}
@@ -861,7 +861,7 @@ static DWORD ReadFile_FrameCached(TCascFile * hf, LPBYTE pbBuffer, ULONGLONG Sta
{
if((pbDecoded = CASC_ALLOC<BYTE>(pFileFrame->ContentSize)) == NULL)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ SetCascError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
bNeedFreeDecoded = true;
@@ -876,7 +876,7 @@ static DWORD ReadFile_FrameCached(TCascFile * hf, LPBYTE pbBuffer, ULONGLONG Sta
if((pbEncoded = CASC_ALLOC<BYTE>(pFileFrame->EncodedSize)) == NULL)
{
CASC_FREE(pbDecoded);
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ SetCascError(ERROR_NOT_ENOUGH_MEMORY);
return 0;
}
@@ -933,7 +933,7 @@ static DWORD ReadFile_FrameCached(TCascFile * hf, LPBYTE pbBuffer, ULONGLONG Sta
pbDecoded = NULL;
// Return the number of bytes read. Always set LastError.
- SetLastError(dwErrCode);
+ SetCascError(dwErrCode);
return (DWORD)(pbBuffer - pbSaveBuffer);
}
@@ -968,7 +968,7 @@ bool WINAPI CascGetFileInfo(HANDLE hFile, CASC_FILE_INFO_CLASS InfoClass, void *
// Validate the file handle
if((hf = TCascFile::IsValid(hFile)) == NULL)
{
- SetLastError(ERROR_INVALID_HANDLE);
+ SetCascError(ERROR_INVALID_HANDLE);
return false;
}
@@ -980,7 +980,7 @@ bool WINAPI CascGetFileInfo(HANDLE hFile, CASC_FILE_INFO_CLASS InfoClass, void *
// Do we have content key at all?
if(hf->pCKeyEntry == NULL || (hf->pCKeyEntry->Flags & CASC_CE_HAS_CKEY) == 0)
{
- SetLastError(ERROR_NOT_SUPPORTED);
+ SetCascError(ERROR_NOT_SUPPORTED);
return false;
}
@@ -994,7 +994,7 @@ bool WINAPI CascGetFileInfo(HANDLE hFile, CASC_FILE_INFO_CLASS InfoClass, void *
// Do we have content key at all?
if(hf->pCKeyEntry == NULL || (hf->pCKeyEntry->Flags & CASC_CE_HAS_EKEY) == 0)
{
- SetLastError(ERROR_NOT_SUPPORTED);
+ SetCascError(ERROR_NOT_SUPPORTED);
return false;
}
@@ -1010,7 +1010,7 @@ bool WINAPI CascGetFileInfo(HANDLE hFile, CASC_FILE_INFO_CLASS InfoClass, void *
return GetFileSpanInfo(hf, pvFileInfo, cbFileInfo, pcbLengthNeeded);
default:
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -1050,14 +1050,14 @@ bool WINAPI CascGetFileSize64(HANDLE hFile, PULONGLONG PtrFileSize)
// Validate the file handle
if((hf = TCascFile::IsValid(hFile)) == NULL)
{
- SetLastError(ERROR_INVALID_HANDLE);
+ SetCascError(ERROR_INVALID_HANDLE);
return false;
}
// Validate the file pointer
if(PtrFileSize == NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -1066,7 +1066,7 @@ bool WINAPI CascGetFileSize64(HANDLE hFile, PULONGLONG PtrFileSize)
dwErrCode = EnsureFileSpanFramesLoaded(hf);
if(dwErrCode != ERROR_SUCCESS)
{
- SetLastError(dwErrCode);
+ SetCascError(dwErrCode);
return false;
}
@@ -1098,7 +1098,7 @@ bool WINAPI CascSetFilePointer64(HANDLE hFile, LONGLONG DistanceToMove, PULONGLO
hf = TCascFile::IsValid(hFile);
if(hf == NULL)
{
- SetLastError(ERROR_INVALID_HANDLE);
+ SetCascError(ERROR_INVALID_HANDLE);
return false;
}
@@ -1118,7 +1118,7 @@ bool WINAPI CascSetFilePointer64(HANDLE hFile, LONGLONG DistanceToMove, PULONGLO
break;
default:
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -1128,7 +1128,7 @@ bool WINAPI CascSetFilePointer64(HANDLE hFile, LONGLONG DistanceToMove, PULONGLO
// Do not allow the file pointer to overflow 64-bit range
if((FilePosition + DistanceToMove) < FilePosition)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -1142,7 +1142,7 @@ bool WINAPI CascSetFilePointer64(HANDLE hFile, LONGLONG DistanceToMove, PULONGLO
// Do not allow the file pointer to underflow 64-bit range
if((FilePosition + DistanceToMove) > FilePosition)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
@@ -1190,14 +1190,14 @@ bool WINAPI CascReadFile(HANDLE hFile, void * pvBuffer, DWORD dwBytesToRead, PDW
// The buffer must be valid
if(pvBuffer == NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return false;
}
// Validate the file handle
if((hf = TCascFile::IsValid(hFile)) == NULL)
{
- SetLastError(ERROR_INVALID_HANDLE);
+ SetCascError(ERROR_INVALID_HANDLE);
return false;
}
@@ -1206,7 +1206,7 @@ bool WINAPI CascReadFile(HANDLE hFile, void * pvBuffer, DWORD dwBytesToRead, PDW
dwErrCode = EnsureFileSpanFramesLoaded(hf);
if(dwErrCode != ERROR_SUCCESS)
{
- SetLastError(dwErrCode);
+ SetCascError(dwErrCode);
return false;
}
diff --git a/dep/CascLib/src/CascRootFile_OW.cpp b/dep/CascLib/src/CascRootFile_OW.cpp
index 251a67284cb..b270ec76206 100644
--- a/dep/CascLib/src/CascRootFile_OW.cpp
+++ b/dep/CascLib/src/CascRootFile_OW.cpp
@@ -502,7 +502,7 @@ struct TRootHandler_OW : public TFileTreeRoot
if(FileName.szValue && CKeyStr.szValue && CKeyStr.nLength == MD5_STRING_SIZE)
{
// Convert the string CKey to binary
- if(ConvertStringToBinary(CKeyStr.szValue, MD5_STRING_SIZE, CKey) == ERROR_SUCCESS)
+ if(BinaryFromString(CKeyStr.szValue, MD5_STRING_SIZE, CKey) == ERROR_SUCCESS)
{
// Find the item in the tree
if((pCKeyEntry = FindCKeyEntry_CKey(hs, CKey)) != NULL)
diff --git a/dep/CascLib/src/CascRootFile_Text.cpp b/dep/CascLib/src/CascRootFile_Text.cpp
index 7662f85d86d..655080bd2ee 100644
--- a/dep/CascLib/src/CascRootFile_Text.cpp
+++ b/dep/CascLib/src/CascRootFile_Text.cpp
@@ -67,7 +67,7 @@ struct TRootHandler_SC1 : public TFileTreeRoot
const CASC_CSV_COLUMN & CKeyStr = Csv[CSV_ZERO][1];
// Convert the CKey to binary
- if(ConvertStringToBinary(CKeyStr.szValue, MD5_STRING_SIZE, CKey) == ERROR_SUCCESS)
+ if(BinaryFromString(CKeyStr.szValue, MD5_STRING_SIZE, CKey) == ERROR_SUCCESS)
{
// Verify whether it is a known entry
if((pCKeyEntry = FindCKeyEntry_CKey(hs, CKey)) != NULL)
diff --git a/dep/CascLib/src/CascRootFile_WoW.cpp b/dep/CascLib/src/CascRootFile_WoW.cpp
index 3bbd8b81ef3..dd085b872e7 100644
--- a/dep/CascLib/src/CascRootFile_WoW.cpp
+++ b/dep/CascLib/src/CascRootFile_WoW.cpp
@@ -413,7 +413,7 @@ struct TRootHandler_WoW : public TFileTreeRoot
nLength = ListFile_GetNext(pSearch->pCache, szFileName, _countof(szFileName), &FileDataId);
if(nLength == 0)
{
- if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ if(GetCascError() == ERROR_INSUFFICIENT_BUFFER)
continue;
break;
}
@@ -435,7 +435,7 @@ struct TRootHandler_WoW : public TFileTreeRoot
nLength = ListFile_GetNextLine(pSearch->pCache, szFileName, _countof(szFileName));
if(nLength == 0)
{
- if(GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+ if(GetCascError() == ERROR_INSUFFICIENT_BUFFER)
continue;
break;
}
diff --git a/dep/CascLib/src/CascLib.def b/dep/CascLib/src/DllMain.def
index 9442184946f..9442184946f 100644
--- a/dep/CascLib/src/CascLib.def
+++ b/dep/CascLib/src/DllMain.def
diff --git a/dep/CascLib/src/DllMain.rc b/dep/CascLib/src/DllMain.rc
index 7007a24ab65..4241c2687de 100644
--- a/dep/CascLib/src/DllMain.rc
+++ b/dep/CascLib/src/DllMain.rc
@@ -1,4 +1,6 @@
// Microsoft Visual C++ generated resource script.
+//
+#include "resource.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
@@ -25,8 +27,8 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,50,0,197
- PRODUCTVERSION 1,50,0,197
+ FILEVERSION 1,50,0,204
+ PRODUCTVERSION 1,50,0,204
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -41,13 +43,14 @@ BEGIN
BEGIN
BLOCK "040504b0"
BEGIN
+ VALUE "Comments", "http://www.zezula.net/casc.html"
VALUE "FileDescription", "CascLib library for reading Blizzard CASC storages"
- VALUE "FileVersion", "1, 50, 0, 197\0"
+ VALUE "FileVersion", "1, 50, 0, 204\0"
VALUE "InternalName", "CascLib"
VALUE "LegalCopyright", "Copyright (c) 2014 - 2019 Ladislav Zezula"
VALUE "OriginalFilename", "CascLib.dll"
VALUE "ProductName", "CascLib"
- VALUE "ProductVersion", "1, 50, 0, 197\0"
+ VALUE "ProductVersion", "1, 50, 0, 204\0"
END
END
BLOCK "VarFileInfo"
@@ -75,18 +78,23 @@ LANGUAGE LANG_CZECH, SUBLANG_DEFAULT
// TEXTINCLUDE
//
-2 TEXTINCLUDE
+2 TEXTINCLUDE
BEGIN
"#include ""afxres.h""\r\n"
"\0"
END
-3 TEXTINCLUDE
+3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END
+1 TEXTINCLUDE
+BEGIN
+ "resource.h\0"
+END
+
#endif // APSTUDIO_INVOKED
#endif // Czech resources
diff --git a/dep/CascLib/src/common/Common.cpp b/dep/CascLib/src/common/Common.cpp
index c16323e0f5e..7bec2b14a6a 100644
--- a/dep/CascLib/src/common/Common.cpp
+++ b/dep/CascLib/src/common/Common.cpp
@@ -59,24 +59,42 @@ unsigned char AsciiToUpperTable_BkSlash[256] =
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
};
+// Converts ASCII characters to hexa digit
+unsigned char AsciiToHexTable[128] =
+{
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+};
+
unsigned char IntToHexChar[] = "0123456789abcdef";
//-----------------------------------------------------------------------------
-// GetLastError/SetLastError support for non-Windows platform
+// GetCascError/SetCascError support for non-Windows platform
-#ifndef PLATFORM_WINDOWS
static DWORD dwLastError = ERROR_SUCCESS;
-DWORD GetLastError()
+DWORD GetCascError()
{
+#ifdef PLATFORM_WINDOWS
+ return GetLastError();
+#else
return dwLastError;
+#endif
}
-void SetLastError(DWORD dwErrCode)
+void SetCascError(DWORD dwErrCode)
{
+#ifdef PLATFORM_WINDOWS
+ SetLastError(dwErrCode);
+#endif
dwLastError = dwErrCode;
}
-#endif
//-----------------------------------------------------------------------------
// Linear data stream manipulation
@@ -520,103 +538,6 @@ ULONGLONG CalcFileNameHash(const char * szFileName)
return CalcNormNameHash(szNormName, nLength);
}
-DWORD ConvertDigitToInt32(LPCTSTR szString, PDWORD PtrValue)
-{
- BYTE Digit;
-
- Digit = (BYTE)(AsciiToUpperTable_BkSlash[szString[0]] - _T('0'));
- if(Digit > 9)
- Digit -= 'A' - '9' - 1;
-
- PtrValue[0] = Digit;
- return (Digit > 0x0F) ? ERROR_BAD_FORMAT : ERROR_SUCCESS;
-}
-
-DWORD ConvertStringToInt08(LPCSTR szString, PDWORD PtrValue)
-{
- BYTE DigitOne = AsciiToUpperTable_BkSlash[szString[0]] - '0';
- BYTE DigitTwo = AsciiToUpperTable_BkSlash[szString[1]] - '0';
-
- // Fix the digits
- if(DigitOne > 9)
- DigitOne -= 'A' - '9' - 1;
- if(DigitTwo > 9)
- DigitTwo -= 'A' - '9' - 1;
-
- // Combine them into a value
- PtrValue[0] = (DigitOne << 0x04) | DigitTwo;
- return (DigitOne <= 0x0F && DigitTwo <= 0x0F) ? ERROR_SUCCESS : ERROR_BAD_FORMAT;
-}
-
-DWORD ConvertStringToInt32(LPCTSTR szString, size_t nMaxDigits, PDWORD PtrValue)
-{
- // The number of digits must be even
- assert((nMaxDigits & 0x01) == 0);
- assert(nMaxDigits <= 8);
-
- // Prepare the variables
- PtrValue[0] = 0;
- nMaxDigits >>= 1;
-
- // Convert the string up to the number of digits
- for(size_t i = 0; i < nMaxDigits; i++)
- {
- BYTE DigitOne;
- BYTE DigitTwo;
-
- DigitOne = (BYTE)(AsciiToUpperTable_BkSlash[szString[0]] - _T('0'));
- if(DigitOne > 9)
- DigitOne -= 'A' - '9' - 1;
-
- DigitTwo = (BYTE)(AsciiToUpperTable_BkSlash[szString[1]] - _T('0'));
- if(DigitTwo > 9)
- DigitTwo -= 'A' - '9' - 1;
-
- if(DigitOne > 0x0F || DigitTwo > 0x0F)
- return ERROR_BAD_FORMAT;
-
- PtrValue[0] = (PtrValue[0] << 0x08) | (DigitOne << 0x04) | DigitTwo;
- szString += 2;
- }
-
- return ERROR_SUCCESS;
-}
-
-// Converts string blob to binary blob.
-DWORD ConvertStringToBinary(
- LPCSTR szString,
- size_t nMaxDigits,
- LPBYTE pbBinary)
-{
- const char * szStringEnd = szString + nMaxDigits;
- DWORD dwCounter = 0;
- BYTE DigitValue;
- BYTE ByteValue = 0;
-
- // Convert the string
- while(szString < szStringEnd)
- {
- // Retrieve the digit converted to hexa
- DigitValue = (BYTE)(AsciiToUpperTable_BkSlash[szString[0]] - '0');
- if(DigitValue > 9)
- DigitValue -= 'A' - '9' - 1;
- if(DigitValue > 0x0F)
- return ERROR_BAD_FORMAT;
-
- // Insert the digit to the binary buffer
- ByteValue = (ByteValue << 0x04) | DigitValue;
- dwCounter++;
-
- // If we reached the second digit, it means that we need
- // to flush the byte value and move on
- if((dwCounter & 0x01) == 0)
- *pbBinary++ = ByteValue;
- szString++;
- }
-
- return ERROR_SUCCESS;
-}
-
//-----------------------------------------------------------------------------
// File name utilities
@@ -648,7 +569,7 @@ bool IsFileDataIdName(const char * szFileName, DWORD & FileDataId)
if(!strncmp(szFileName, "FILE", 4) && strlen(szFileName) >= 0x0C)
{
// Convert the hexadecimal number to integer
- if(ConvertStringToBinary(szFileName+4, 8, BinaryValue) == ERROR_SUCCESS)
+ if(BinaryFromString(szFileName+4, 8, BinaryValue) == ERROR_SUCCESS)
{
// Must be followed by an extension or end-of-string
if(szFileName[0x0C] == 0 || szFileName[0x0C] == '.')
@@ -668,7 +589,7 @@ bool IsFileCKeyEKeyName(const char * szFileName, LPBYTE PtrKeyBuffer)
if(nLength == MD5_STRING_SIZE)
{
- if(ConvertStringToBinary(szFileName, MD5_STRING_SIZE, PtrKeyBuffer) == ERROR_SUCCESS)
+ if(BinaryFromString(szFileName, MD5_STRING_SIZE, PtrKeyBuffer) == ERROR_SUCCESS)
{
return true;
}
diff --git a/dep/CascLib/src/common/Common.h b/dep/CascLib/src/common/Common.h
index 0037293f53d..46b23adb6ae 100644
--- a/dep/CascLib/src/common/Common.h
+++ b/dep/CascLib/src/common/Common.h
@@ -124,6 +124,7 @@ typedef CASC_CKEY_ENTRY *PCASC_CKEY_ENTRY;
extern unsigned char AsciiToLowerTable_Slash[256];
extern unsigned char AsciiToUpperTable_BkSlash[256];
+extern unsigned char AsciiToHexTable[0x80];
extern unsigned char IntToHexChar[];
//-----------------------------------------------------------------------------
@@ -339,15 +340,82 @@ size_t NormalizeFileName_LowerSlash(char * szNormName, const char * szFileName,
ULONGLONG CalcNormNameHash(const char * szNormName, size_t nLength);
ULONGLONG CalcFileNameHash(const char * szFileName);
-DWORD ConvertDigitToInt32(LPCTSTR szString, PDWORD PtrValue);
-DWORD ConvertStringToInt08(LPCSTR szString, PDWORD PtrValue);
-DWORD ConvertStringToInt32(LPCTSTR szString, size_t nMaxDigits, PDWORD PtrValue);
-DWORD ConvertStringToBinary(LPCSTR szString, size_t nMaxDigits, LPBYTE pbBinary);
-
//-----------------------------------------------------------------------------
-// Conversion from binary array to string. The caller must ensure that
-// the buffer has at least ((cbBinary * 2) + 1) characters
+// String conversion functions
+
+template <typename xchar, typename INTXX>
+DWORD ConvertStringToInt(const xchar * szString, size_t nMaxDigits, INTXX & RefValue, const xchar ** PtrStringEnd = NULL)
+{
+ INTXX MaxValueMask = (INTXX)0x0F << ((sizeof(INTXX) * 8) - 4);
+ INTXX Accumulator = 0;
+ BYTE DigitOne;
+
+ // Set default value
+ if(nMaxDigits == 0)
+ nMaxDigits = sizeof(INTXX) * 2;
+
+ // Convert the string up to the number of digits
+ for(size_t i = 0; i < nMaxDigits; i++, szString++)
+ {
+ // Check for the end of the string
+ if(szString[0] > sizeof(AsciiToHexTable))
+ return ERROR_BAD_FORMAT;
+ if(szString[0] <= 0x20)
+ break;
+
+ // Extract the next digit
+ DigitOne = AsciiToHexTable[szString[0]];
+ if(DigitOne == 0xFF)
+ return ERROR_BAD_FORMAT;
+
+ // Check overflow. If OK, shift the value by 4 to the left
+ if(Accumulator & MaxValueMask)
+ return ERROR_ARITHMETIC_OVERFLOW;
+ Accumulator = (Accumulator << 4) | DigitOne;
+ }
+
+ // Give the results
+ if(PtrStringEnd != NULL)
+ PtrStringEnd[0] = szString;
+ RefValue = Accumulator;
+ return ERROR_SUCCESS;
+}
+
+// Converts string blob to binary blob
+template <typename xchar>
+DWORD BinaryFromString(const xchar * szString, size_t nMaxDigits, LPBYTE pbBinary)
+{
+ const xchar * szStringEnd = szString + nMaxDigits;
+ DWORD dwCounter = 0;
+ BYTE DigitValue;
+ BYTE ByteValue = 0;
+
+ // Convert the string
+ while(szString < szStringEnd)
+ {
+ // Retrieve the digit converted to hexa
+ DigitValue = (BYTE)(AsciiToUpperTable_BkSlash[szString[0]] - '0');
+ if(DigitValue > 9)
+ DigitValue -= 'A' - '9' - 1;
+ if(DigitValue > 0x0F)
+ return ERROR_BAD_FORMAT;
+
+ // Insert the digit to the binary buffer
+ ByteValue = (ByteValue << 0x04) | DigitValue;
+ dwCounter++;
+
+ // If we reached the second digit, it means that we need
+ // to flush the byte value and move on
+ if((dwCounter & 0x01) == 0)
+ *pbBinary++ = ByteValue;
+ szString++;
+ }
+
+ return ERROR_SUCCESS;
+}
+// Converts binary array to string.
+// The caller must ensure that the buffer has at least ((cbBinary * 2) + 1) characters
template <typename xchar>
xchar * StringFromBinary(LPBYTE pbBinary, size_t cbBinary, xchar * szBuffer)
{
diff --git a/dep/CascLib/src/common/Csv.cpp b/dep/CascLib/src/common/Csv.cpp
index 818973e9603..40a50ec723b 100644
--- a/dep/CascLib/src/common/Csv.cpp
+++ b/dep/CascLib/src/common/Csv.cpp
@@ -203,7 +203,7 @@ DWORD CASC_CSV::Load(LPCTSTR szFileName)
}
else
{
- dwErrCode = GetLastError();
+ dwErrCode = GetCascError();
}
return dwErrCode;
diff --git a/dep/CascLib/src/common/FileStream.cpp b/dep/CascLib/src/common/FileStream.cpp
index 350b0540cf4..cb0090f8dfb 100644
--- a/dep/CascLib/src/common/FileStream.cpp
+++ b/dep/CascLib/src/common/FileStream.cpp
@@ -75,7 +75,7 @@ static bool BaseFile_Create(TFileStream * pStream)
if(handle == -1)
{
pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
- SetLastError(errno);
+ SetCascError(errno);
return false;
}
@@ -128,14 +128,14 @@ static bool BaseFile_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStr
handle = open(szFileName, oflag | O_LARGEFILE);
if(handle == -1)
{
- SetLastError(errno);
+ SetCascError(errno);
return false;
}
// Get the file size
if(fstat64(handle, &fileinfo) == -1)
{
- SetLastError(errno);
+ SetCascError(errno);
close(handle);
return false;
}
@@ -185,8 +185,11 @@ static bool BaseFile_Read(
Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
Overlapped.Offset = (DWORD)ByteOffset;
Overlapped.hEvent = NULL;
- if (!ReadFile(pStream->Base.File.hFile, pvBuffer, dwBytesToRead, &dwBytesRead, &Overlapped))
+ if(!ReadFile(pStream->Base.File.hFile, pvBuffer, dwBytesToRead, &dwBytesRead, &Overlapped))
+ {
+ CascUnlock(pStream->Lock);
return false;
+ }
}
}
#endif
@@ -201,7 +204,8 @@ static bool BaseFile_Read(
{
if (lseek64((intptr_t)pStream->Base.File.hFile, (off64_t)(ByteOffset), SEEK_SET) == (off64_t)-1)
{
- SetLastError(errno);
+ CascUnlock(pStream->Lock);
+ SetCascError(errno);
return false;
}
pStream->Base.File.FilePos = ByteOffset;
@@ -213,7 +217,8 @@ static bool BaseFile_Read(
bytes_read = read((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToRead);
if (bytes_read == -1)
{
- SetLastError(errno);
+ CascUnlock(pStream->Lock);
+ SetCascError(errno);
return false;
}
@@ -239,7 +244,7 @@ static bool BaseFile_Read(
}
else
{
- SetLastError(ERROR_HANDLE_EOF);
+ SetCascError(ERROR_HANDLE_EOF);
}
}
@@ -280,8 +285,11 @@ static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const
Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
Overlapped.Offset = (DWORD)ByteOffset;
Overlapped.hEvent = NULL;
- if (!WriteFile(pStream->Base.File.hFile, pvBuffer, dwBytesToWrite, &dwBytesWritten, &Overlapped))
+ if(!WriteFile(pStream->Base.File.hFile, pvBuffer, dwBytesToWrite, &dwBytesWritten, &Overlapped))
+ {
+ CascUnlock(pStream->Lock);
return false;
+ }
}
}
#endif
@@ -296,7 +304,8 @@ static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const
{
if (lseek64((intptr_t)pStream->Base.File.hFile, (off64_t)(ByteOffset), SEEK_SET) == (off64_t)-1)
{
- SetLastError(errno);
+ CascUnlock(pStream->Lock);
+ SetCascError(errno);
return false;
}
pStream->Base.File.FilePos = ByteOffset;
@@ -306,7 +315,8 @@ static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const
bytes_written = write((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToWrite);
if (bytes_written == -1)
{
- SetLastError(errno);
+ CascUnlock(pStream->Lock);
+ SetCascError(errno);
return false;
}
@@ -324,7 +334,7 @@ static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const
CascUnlock(pStream->Lock);
if(dwBytesWritten != dwBytesToWrite)
- SetLastError(ERROR_DISK_FULL);
+ SetCascError(ERROR_DISK_FULL);
return (dwBytesWritten == dwBytesToWrite);
}
@@ -343,7 +353,7 @@ static bool BaseFile_Resize(TFileStream * pStream, ULONGLONG NewFileSize)
// Set the position at the new file size
dwNewPos = SetFilePointer(pStream->Base.File.hFile, (LONG)NewFileSize, &FileSizeHi, FILE_BEGIN);
- if(dwNewPos == INVALID_SET_FILE_POINTER && GetLastError() != ERROR_SUCCESS)
+ if(dwNewPos == INVALID_SET_FILE_POINTER && GetCascError() != ERROR_SUCCESS)
return false;
// Set the current file pointer as the end of the file
@@ -363,7 +373,7 @@ static bool BaseFile_Resize(TFileStream * pStream, ULONGLONG NewFileSize)
{
if(ftruncate64((intptr_t)pStream->Base.File.hFile, (off64_t)NewFileSize) == -1)
{
- SetLastError(errno);
+ SetCascError(errno);
return false;
}
@@ -403,7 +413,7 @@ static bool BaseFile_Replace(TFileStream * pStream, TFileStream * pNewStream)
// "rename" on Linux also works if the target file exists
if(rename(pNewStream->szFileName, pStream->szFileName) == -1)
{
- SetLastError(errno);
+ SetCascError(errno);
return false;
}
@@ -533,7 +543,7 @@ static bool BaseMap_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStre
// Did the mapping fail?
if(bResult == false)
{
- SetLastError(errno);
+ SetCascError(errno);
return false;
}
#endif
@@ -638,7 +648,7 @@ static bool BaseHttp_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStr
// Don't download if we are not connected to the internet
if(!InternetGetConnectedState(&dwTemp, 0))
- dwErrCode = GetLastError();
+ dwErrCode = GetCascError();
// Initiate the connection to the internet
if(dwErrCode == ERROR_SUCCESS)
@@ -649,7 +659,7 @@ static bool BaseHttp_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStr
NULL,
0);
if(pStream->Base.Http.hInternet == NULL)
- dwErrCode = GetLastError();
+ dwErrCode = GetCascError();
}
// Connect to the server
@@ -669,7 +679,7 @@ static bool BaseHttp_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStr
dwFlags,
0);
if(pStream->Base.Http.hConnect == NULL)
- dwErrCode = GetLastError();
+ dwErrCode = GetCascError();
}
// Now try to query the file size
@@ -727,7 +737,7 @@ static bool BaseHttp_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStr
if(bFileAvailable == false)
{
pStream->BaseClose(pStream);
- SetLastError(dwErrCode);
+ SetCascError(dwErrCode);
return false;
}
@@ -736,7 +746,7 @@ static bool BaseHttp_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStr
#else
// Not supported
- SetLastError(ERROR_NOT_SUPPORTED);
+ SetCascError(ERROR_NOT_SUPPORTED);
pStream = pStream;
return false;
@@ -804,7 +814,7 @@ static bool BaseHttp_Read(
// If the number of bytes read doesn't match the required amount, return false
if(dwTotalBytesRead != dwBytesToRead)
- SetLastError(ERROR_HANDLE_EOF);
+ SetCascError(ERROR_HANDLE_EOF);
return (dwTotalBytesRead == dwBytesToRead);
#else
@@ -814,7 +824,7 @@ static bool BaseHttp_Read(
pByteOffset = pByteOffset;
pvBuffer = pvBuffer;
dwBytesToRead = dwBytesToRead;
- SetLastError(ERROR_NOT_SUPPORTED);
+ SetCascError(ERROR_NOT_SUPPORTED);
return false;
#endif
@@ -888,7 +898,7 @@ static bool BlockStream_Read(
EndOffset = ByteOffset + dwBytesToRead;
if(EndOffset > pStream->StreamSize)
{
- SetLastError(ERROR_HANDLE_EOF);
+ SetCascError(ERROR_HANDLE_EOF);
return false;
}
@@ -905,7 +915,7 @@ static bool BlockStream_Read(
TransferBuffer = BlockBuffer = CASC_ALLOC<BYTE>(BlockCount * BlockSize);
if(TransferBuffer == NULL)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ SetCascError(ERROR_NOT_ENOUGH_MEMORY);
return false;
}
@@ -983,7 +993,7 @@ static bool BlockStream_Read(
else
{
// If the block read failed, set the last error
- SetLastError(ERROR_FILE_INCOMPLETE);
+ SetCascError(ERROR_FILE_INCOMPLETE);
}
// Call the callback to indicate we are done
@@ -1058,7 +1068,7 @@ static TFileStream * AllocateFileStream(
// Don't allow another master file in the string
if(_tcschr(szNextFile + 1, _T('*')) != NULL)
{
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return NULL;
}
@@ -1392,7 +1402,7 @@ static TFileStream * FlatStream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
pStream = (TBlockStream *)AllocateFileStream(szFileName, sizeof(TBlockStream), dwStreamFlags);
if(pStream == NULL)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ SetCascError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
@@ -1402,7 +1412,7 @@ static TFileStream * FlatStream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
if(!FlatStream_CreateMirror(pStream))
{
FileStream_Close(pStream);
- SetLastError(ERROR_FILE_NOT_FOUND);
+ SetCascError(ERROR_FILE_NOT_FOUND);
return NULL;
}
}
@@ -1819,7 +1829,7 @@ static TFileStream * PartStream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
if(!PartStream_CreateMirror(pStream))
{
FileStream_Close(pStream);
- SetLastError(ERROR_FILE_NOT_FOUND);
+ SetCascError(ERROR_FILE_NOT_FOUND);
return NULL;
}
}
@@ -1836,7 +1846,7 @@ static TFileStream * PartStream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
if(!PartStream_LoadBitmap(pStream))
{
FileStream_Close(pStream);
- SetLastError(ERROR_BAD_FORMAT);
+ SetCascError(ERROR_BAD_FORMAT);
return NULL;
}
}
@@ -2149,7 +2159,7 @@ static TFileStream * EncrStream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
// Cleanup the stream and return
FileStream_Close(pStream);
- SetLastError(ERROR_FILE_ENCRYPTED);
+ SetCascError(ERROR_FILE_ENCRYPTED);
return NULL;
}
@@ -2293,7 +2303,7 @@ static TFileStream * Block4Stream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
NewBaseArray = CASC_ALLOC<TBaseProviderData>(dwBaseFiles + 1);
if(NewBaseArray == NULL)
{
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ SetCascError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
@@ -2348,7 +2358,7 @@ static TFileStream * Block4Stream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
if(dwBaseFiles == 0)
{
FileStream_Close(pStream);
- SetLastError(ERROR_FILE_NOT_FOUND);
+ SetCascError(ERROR_FILE_NOT_FOUND);
pStream = NULL;
}
@@ -2384,7 +2394,7 @@ TFileStream * FileStream_CreateFile(
// We only support creation of flat, local file
if((dwStreamFlags & (STREAM_PROVIDERS_MASK)) != (STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE))
{
- SetLastError(ERROR_NOT_SUPPORTED);
+ SetCascError(ERROR_NOT_SUPPORTED);
return NULL;
}
@@ -2457,7 +2467,7 @@ TFileStream * FileStream_OpenFile(
return Block4Stream_Open(szFileName, dwStreamFlags);
default:
- SetLastError(ERROR_INVALID_PARAMETER);
+ SetCascError(ERROR_INVALID_PARAMETER);
return NULL;
}
}
@@ -2569,7 +2579,7 @@ bool FileStream_SetCallback(TFileStream * pStream, STREAM_DOWNLOAD_CALLBACK pfnC
if(pStream->BlockRead == NULL)
{
- SetLastError(ERROR_NOT_SUPPORTED);
+ SetCascError(ERROR_NOT_SUPPORTED);
return false;
}
@@ -2594,8 +2604,8 @@ bool FileStream_SetCallback(TFileStream * pStream, STREAM_DOWNLOAD_CALLBACK pfnC
*
* \returns
* - If the function reads the required amount of bytes, it returns true.
- * - If the function reads less than required bytes, it returns false and GetLastError() returns ERROR_HANDLE_EOF
- * - If the function fails, it reads false and GetLastError() returns an error code different from ERROR_HANDLE_EOF
+ * - If the function reads less than required bytes, it returns false and GetCascError() returns ERROR_HANDLE_EOF
+ * - If the function fails, it reads false and GetCascError() returns an error code different from ERROR_HANDLE_EOF
*/
bool FileStream_Read(TFileStream * pStream, ULONGLONG * pByteOffset, void * pvBuffer, DWORD dwBytesToRead)
{
@@ -2619,7 +2629,7 @@ bool FileStream_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void
{
if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
{
- SetLastError(ERROR_ACCESS_DENIED);
+ SetCascError(ERROR_ACCESS_DENIED);
return false;
}
@@ -2649,7 +2659,7 @@ bool FileStream_SetSize(TFileStream * pStream, ULONGLONG NewFileSize)
{
if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
{
- SetLastError(ERROR_ACCESS_DENIED);
+ SetCascError(ERROR_ACCESS_DENIED);
return false;
}
@@ -2709,14 +2719,14 @@ bool FileStream_Replace(TFileStream * pStream, TFileStream * pNewStream)
// Only supported on flat files
if((pStream->dwFlags & STREAM_PROVIDERS_MASK) != (STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE))
{
- SetLastError(ERROR_NOT_SUPPORTED);
+ SetCascError(ERROR_NOT_SUPPORTED);
return false;
}
// Not supported on read-only streams
if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
{
- SetLastError(ERROR_ACCESS_DENIED);
+ SetCascError(ERROR_ACCESS_DENIED);
return false;
}
diff --git a/dep/CascLib/src/common/ListFile.cpp b/dep/CascLib/src/common/ListFile.cpp
index a284ef2db10..a91922cd9b1 100644
--- a/dep/CascLib/src/common/ListFile.cpp
+++ b/dep/CascLib/src/common/ListFile.cpp
@@ -245,7 +245,7 @@ size_t ListFile_GetNextLine(void * pvListFile, char * szBuffer, size_t nMaxChars
// If we didn't read anything, set the error code
if(nLength == 0)
- SetLastError(dwErrCode);
+ SetCascError(dwErrCode);
return nLength;
}
@@ -282,7 +282,7 @@ size_t ListFile_GetNext(void * pvListFile, char * szBuffer, size_t nMaxChars, PD
nLength = ListFile_GetNextLine(pvListFile, szBuffer, nMaxChars);
if(nLength == 0)
{
- dwErrCode = GetLastError();
+ dwErrCode = GetCascError();
break;
}
@@ -292,7 +292,7 @@ size_t ListFile_GetNext(void * pvListFile, char * szBuffer, size_t nMaxChars, PD
}
if(dwErrCode != ERROR_SUCCESS)
- SetLastError(dwErrCode);
+ SetCascError(dwErrCode);
return nLength;
}
diff --git a/dep/CascLib/src/common/Map.h b/dep/CascLib/src/common/Map.h
index 4b277cb73a8..54dda5baed8 100644
--- a/dep/CascLib/src/common/Map.h
+++ b/dep/CascLib/src/common/Map.h
@@ -354,4 +354,27 @@ class CASC_MAP
// Will improve performance, as we will not hash a hash :-)
};
+//-----------------------------------------------------------------------------
+// Key map interface
+
+// Maximum length of encryption key
+#define CASC_KEY_LENGTH 0x10
+#define CASC_KEY_TABLE_SIZE 0x100
+#define CASC_KEY_TABLE_MASK (CASC_KEY_TABLE_SIZE - 1)
+
+class CASC_KEY_MAP
+{
+ public:
+
+ CASC_KEY_MAP();
+ ~CASC_KEY_MAP();
+
+ LPBYTE FindKey(ULONGLONG KeyName);
+ bool AddKey(ULONGLONG KeyName, LPBYTE Key);
+
+ protected:
+
+ void * HashTable[CASC_KEY_TABLE_SIZE];
+};
+
#endif // __CASC_MAP_H__
diff --git a/dep/PackageList.txt b/dep/PackageList.txt
index 9b7d738eb54..be68715e586 100644
--- a/dep/PackageList.txt
+++ b/dep/PackageList.txt
@@ -62,7 +62,7 @@ recastnavigation (Recast is state of the art navigation mesh construction toolse
CascLib (An open-source implementation of library for reading CASC storage from Blizzard games since 2014)
https://github.com/ladislav-zezula/CascLib
- Version: 0a05c59eb8a3eab1bc5471f43934cd5f992f0aca
+ Version: 737a8705b5b8f7ce3917f5d5ff9767b18de1285e
rapidjson (A fast JSON parser/generator for C++ with both SAX/DOM style API http://rapidjson.org/)
https://github.com/miloyip/rapidjson
diff --git a/src/tools/extractor_common/CascHandles.cpp b/src/tools/extractor_common/CascHandles.cpp
index d4d1cd28da6..868c4af27c5 100644
--- a/src/tools/extractor_common/CascHandles.cpp
+++ b/src/tools/extractor_common/CascHandles.cpp
@@ -63,10 +63,10 @@ CASC::Storage* CASC::Storage::Open(boost::filesystem::path const& path, uint32 l
HANDLE handle = nullptr;
if (!::CascOpenStorageEx(nullptr, &args, false, &handle))
{
- DWORD lastError = GetLastError(); // support checking error set by *Open* call, not the next *Close*
+ DWORD lastError = GetCascError(); // support checking error set by *Open* call, not the next *Close*
printf("Error opening casc storage '%s': %s\n", path.string().c_str(), HumanReadableCASCError(lastError));
CascCloseStorage(handle);
- SetLastError(lastError);
+ SetCascError(lastError);
return nullptr;
}
@@ -116,12 +116,12 @@ CASC::File* CASC::Storage::OpenFile(char const* fileName, uint32 localeMask, boo
HANDLE handle = nullptr;
if (!::CascOpenFile(_handle, fileName, localeMask, openFlags, &handle))
{
- DWORD lastError = GetLastError(); // support checking error set by *Open* call, not the next *Close*
+ DWORD lastError = GetCascError(); // support checking error set by *Open* call, not the next *Close*
if (printErrors)
fprintf(stderr, "Failed to open '%s' in CASC storage: %s\n", fileName, HumanReadableCASCError(lastError));
CascCloseFile(handle);
- SetLastError(lastError);
+ SetCascError(lastError);
return nullptr;
}
@@ -137,12 +137,12 @@ CASC::File* CASC::Storage::OpenFile(uint32 fileDataId, uint32 localeMask, bool p
HANDLE handle = nullptr;
if (!::CascOpenFile(_handle, CASC_FILE_DATA_ID(fileDataId), localeMask, openFlags, &handle))
{
- DWORD lastError = GetLastError(); // support checking error set by *Open* call, not the next *Close*
+ DWORD lastError = GetCascError(); // support checking error set by *Open* call, not the next *Close*
if (printErrors)
fprintf(stderr, "Failed to open 'FileDataId %u' in CASC storage: %s\n", fileDataId, HumanReadableCASCError(lastError));
CascCloseFile(handle);
- SetLastError(lastError);
+ SetCascError(lastError);
return nullptr;
}
diff --git a/src/tools/map_extractor/System.cpp b/src/tools/map_extractor/System.cpp
index 2378e1d72c2..74e3c604b8b 100644
--- a/src/tools/map_extractor/System.cpp
+++ b/src/tools/map_extractor/System.cpp
@@ -235,7 +235,7 @@ void TryLoadDB2(char const* name, DB2CascFileSource* source, DB2FileLoader* db2,
}
catch (std::exception const& e)
{
- printf("Fatal error: Invalid %s file format! %s\n%s\n", name, CASC::HumanReadableCASCError(GetLastError()), e.what());
+ printf("Fatal error: Invalid %s file format! %s\n%s\n", name, CASC::HumanReadableCASCError(GetCascError()), e.what());
exit(1);
}
}
@@ -1215,7 +1215,7 @@ bool ExtractDB2File(uint32 fileDataId, char const* cascFileName, int locale, boo
DB2CascFileSource source(CascStorage, fileDataId, false);
if (!source.IsOpen())
{
- printf("Unable to open file %s in the archive for locale %s: %s\n", cascFileName, localeNames[locale], CASC::HumanReadableCASCError(GetLastError()));
+ printf("Unable to open file %s in the archive for locale %s: %s\n", cascFileName, localeNames[locale], CASC::HumanReadableCASCError(GetCascError()));
return false;
}
@@ -1351,7 +1351,7 @@ void ExtractCameraFiles()
++count;
}
else
- printf("Unable to open file %u in the archive: %s\n", cameraFileDataId, CASC::HumanReadableCASCError(GetLastError()));
+ printf("Unable to open file %u in the archive: %s\n", cameraFileDataId, CASC::HumanReadableCASCError(GetCascError()));
}
printf("Extracted %u camera files\n", count);
@@ -1407,7 +1407,7 @@ void ExtractGameTables()
++count;
}
else
- printf("Unable to open file %s in the archive: %s\n", gt.Name, CASC::HumanReadableCASCError(GetLastError()));
+ printf("Unable to open file %s in the archive: %s\n", gt.Name, CASC::HumanReadableCASCError(GetCascError()));
}
printf("Extracted %u files\n\n", count);
diff --git a/src/tools/vmap4_extractor/cascfile.cpp b/src/tools/vmap4_extractor/cascfile.cpp
index 2b1bb31cba7..35be390b397 100644
--- a/src/tools/vmap4_extractor/cascfile.cpp
+++ b/src/tools/vmap4_extractor/cascfile.cpp
@@ -28,8 +28,8 @@ CASCFile::CASCFile(std::shared_ptr<CASC::Storage const> casc, const char* filena
std::unique_ptr<CASC::File> file(casc->OpenFile(filename, CASC_LOCALE_ALL_WOW, false));
if (!file)
{
- if (warnNoExist || GetLastError() != ERROR_FILE_NOT_FOUND)
- fprintf(stderr, "Can't open %s: %s\n", filename, CASC::HumanReadableCASCError(GetLastError()));
+ if (warnNoExist || GetCascError() != ERROR_FILE_NOT_FOUND)
+ fprintf(stderr, "Can't open %s: %s\n", filename, CASC::HumanReadableCASCError(GetCascError()));
eof = true;
return;
}
@@ -46,8 +46,8 @@ CASCFile::CASCFile(std::shared_ptr<CASC::Storage const> casc, uint32 fileDataId,
std::unique_ptr<CASC::File> file(casc->OpenFile(fileDataId, CASC_LOCALE_ALL_WOW, false));
if (!file)
{
- if (warnNoExist || GetLastError() != ERROR_FILE_NOT_FOUND)
- fprintf(stderr, "Can't open %s: %s\n", description.c_str(), CASC::HumanReadableCASCError(GetLastError()));
+ if (warnNoExist || GetCascError() != ERROR_FILE_NOT_FOUND)
+ fprintf(stderr, "Can't open %s: %s\n", description.c_str(), CASC::HumanReadableCASCError(GetCascError()));
eof = true;
return;
}
@@ -60,7 +60,7 @@ void CASCFile::init(CASC::File* file, const char* description)
int64 fileSize = file->GetSize();
if (fileSize == -1)
{
- fprintf(stderr, "Can't open %s, failed to get size: %s!\n", description, CASC::HumanReadableCASCError(GetLastError()));
+ fprintf(stderr, "Can't open %s, failed to get size: %s!\n", description, CASC::HumanReadableCASCError(GetCascError()));
eof = true;
return;
}
@@ -71,7 +71,7 @@ void CASCFile::init(CASC::File* file, const char* description)
buffer = new char[size];
if (!file->ReadFile(buffer, size, &read) || size != read)
{
- fprintf(stderr, "Can't read %s, size=%u read=%u: %s\n", description, uint32(size), uint32(read), CASC::HumanReadableCASCError(GetLastError()));
+ fprintf(stderr, "Can't read %s, size=%u read=%u: %s\n", description, uint32(size), uint32(read), CASC::HumanReadableCASCError(GetCascError()));
eof = true;
return;
}
diff --git a/src/tools/vmap4_extractor/vmapexport.cpp b/src/tools/vmap4_extractor/vmapexport.cpp
index f633347f387..d3407beb895 100644
--- a/src/tools/vmap4_extractor/vmapexport.cpp
+++ b/src/tools/vmap4_extractor/vmapexport.cpp
@@ -484,7 +484,7 @@ int main(int argc, char ** argv)
}
catch (std::exception const& e)
{
- printf("Fatal error: Invalid Map.db2 file format! %s\n%s\n", CASC::HumanReadableCASCError(GetLastError()), e.what());
+ printf("Fatal error: Invalid Map.db2 file format! %s\n%s\n", CASC::HumanReadableCASCError(GetCascError()), e.what());
exit(1);
}