aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib/src/common
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2019-08-10 19:01:24 +0200
committerShauren <shauren.trinity@gmail.com>2019-08-10 19:01:24 +0200
commitcd720efbfa60f434f420ab66e220eca742c48e45 (patch)
tree3c960ac5249d0711b71fbfdc62f6c0b665ed85ee /dep/CascLib/src/common
parent0d6320dfd3932865edb69c8528327b767bd476ef (diff)
Dep/CascLib: Update to ladislav-zezula/CascLib@b91f87c770c78340dcd96df970e55b5c0469e884
Diffstat (limited to 'dep/CascLib/src/common')
-rw-r--r--dep/CascLib/src/common/Array.h18
-rw-r--r--dep/CascLib/src/common/Common.cpp184
-rw-r--r--dep/CascLib/src/common/Common.h99
-rw-r--r--dep/CascLib/src/common/Csv.cpp18
-rw-r--r--dep/CascLib/src/common/Csv.h4
-rw-r--r--dep/CascLib/src/common/FileStream.cpp50
-rw-r--r--dep/CascLib/src/common/FileStream.h6
-rw-r--r--dep/CascLib/src/common/FileTree.cpp162
-rw-r--r--dep/CascLib/src/common/FileTree.h17
-rw-r--r--dep/CascLib/src/common/ListFile.cpp16
-rw-r--r--dep/CascLib/src/common/Map.h9
-rw-r--r--dep/CascLib/src/common/Path.h182
-rw-r--r--dep/CascLib/src/common/RootHandler.cpp4
13 files changed, 516 insertions, 253 deletions
diff --git a/dep/CascLib/src/common/Array.h b/dep/CascLib/src/common/Array.h
index 1dc96b7be8e..ea99d10fe22 100644
--- a/dep/CascLib/src/common/Array.h
+++ b/dep/CascLib/src/common/Array.h
@@ -43,7 +43,7 @@ class CASC_ARRAY
int Create(size_t ItemSize, size_t ItemCountMax)
{
// Create the array
- if ((m_pItemArray = CASC_ALLOC(BYTE, ItemSize * ItemCountMax)) == NULL)
+ if ((m_pItemArray = CASC_ALLOC<BYTE>(ItemSize * ItemCountMax)) == NULL)
return ERROR_NOT_ENOUGH_MEMORY;
m_ItemCountMax = ItemCountMax;
@@ -53,12 +53,12 @@ class CASC_ARRAY
}
// Inserts one or more items; returns pointer to the first inserted item
- void * Insert(size_t NewItemCount)
+ void * Insert(size_t NewItemCount, bool bEnlargeAllowed = true)
{
void * pNewItems;
// Try to enlarge the buffer, if needed
- if (!EnlargeArray(m_ItemCount + NewItemCount))
+ if (!EnlargeArray(m_ItemCount + NewItemCount, bEnlargeAllowed))
return NULL;
pNewItems = m_pItemArray + (m_ItemCount * m_ItemSize);
@@ -70,9 +70,9 @@ class CASC_ARRAY
}
// Inserts one or more items; returns pointer to the first inserted item
- void * Insert(const void * NewItems, size_t NewItemCount)
+ void * Insert(const void * NewItems, size_t NewItemCount, bool bEnlargeAllowed = true)
{
- void * pNewItem = Insert(NewItemCount);
+ void * pNewItem = Insert(NewItemCount, bEnlargeAllowed);
// Copy the item(s) to the array, if any
if (pNewItem && NewItems)
@@ -99,7 +99,7 @@ class CASC_ARRAY
LPBYTE pbNewItem;
// Make sure we have array large enough
- if(!EnlargeArray(ItemIndex + 1))
+ if(!EnlargeArray(ItemIndex + 1, true))
return NULL;
// Get the items range
@@ -169,7 +169,7 @@ class CASC_ARRAY
protected:
- bool EnlargeArray(size_t NewItemCount)
+ bool EnlargeArray(size_t NewItemCount, bool bEnlargeAllowed)
{
LPBYTE NewItemArray;
size_t ItemCountMax;
@@ -181,6 +181,10 @@ class CASC_ARRAY
// Shall we enlarge the table?
if (NewItemCount > m_ItemCountMax)
{
+ // Deny enlarge if not allowed
+ if(bEnlargeAllowed == false)
+ return false;
+
// Calculate new table size
ItemCountMax = m_ItemCountMax;
while (ItemCountMax < NewItemCount)
diff --git a/dep/CascLib/src/common/Common.cpp b/dep/CascLib/src/common/Common.cpp
index 2860671227b..1fc6cc977b4 100644
--- a/dep/CascLib/src/common/Common.cpp
+++ b/dep/CascLib/src/common/Common.cpp
@@ -81,6 +81,19 @@ void SetLastError(DWORD dwErrCode)
//-----------------------------------------------------------------------------
// Linear data stream manipulation
+LPBYTE CaptureInteger16_BE(LPBYTE pbDataPtr, LPBYTE pbDataEnd, PDWORD PtrValue)
+{
+ // Is there enough data?
+ if((pbDataPtr + sizeof(USHORT)) > pbDataEnd)
+ return NULL;
+
+ // Convert data from Little endian to
+ PtrValue[0] = ConvertBytesToInteger_2(pbDataPtr);
+
+ // Return the pointer to data following after the integer
+ return pbDataPtr + sizeof(USHORT);
+}
+
LPBYTE CaptureInteger32(LPBYTE pbDataPtr, LPBYTE pbDataEnd, PDWORD PtrValue)
{
// Is there enough data?
@@ -133,6 +146,49 @@ LPBYTE CaptureContentKey(LPBYTE pbDataPtr, LPBYTE pbDataEnd, PCONTENT_KEY * PtrC
return pbDataPtr + sizeof(CONTENT_KEY);
}
+LPBYTE CaptureEncodedKey(LPBYTE pbEKey, LPBYTE pbData, BYTE EKeyLength)
+{
+ // Two usual lengths of EKey
+ assert(EKeyLength == 0x09 || EKeyLength == 0x10);
+
+ // Copy the first 0x09 bytes
+ if(EKeyLength >= 0x09)
+ {
+ pbEKey[0x00] = pbData[0x00];
+ pbEKey[0x01] = pbData[0x01];
+ pbEKey[0x02] = pbData[0x02];
+ pbEKey[0x03] = pbData[0x03];
+ pbEKey[0x04] = pbData[0x04];
+ pbEKey[0x05] = pbData[0x05];
+ pbEKey[0x06] = pbData[0x06];
+ pbEKey[0x07] = pbData[0x07];
+ pbEKey[0x08] = pbData[0x08];
+
+ if(EKeyLength == 0x10)
+ {
+ pbEKey[0x09] = pbData[0x09];
+ pbEKey[0x0A] = pbData[0x0A];
+ pbEKey[0x0B] = pbData[0x0B];
+ pbEKey[0x0C] = pbData[0x0C];
+ pbEKey[0x0D] = pbData[0x0D];
+ pbEKey[0x0E] = pbData[0x0E];
+ pbEKey[0x0F] = pbData[0x0F];
+ }
+ else
+ {
+ pbEKey[0x09] = 0;
+ pbEKey[0x0A] = 0;
+ pbEKey[0x0B] = 0;
+ pbEKey[0x0C] = 0;
+ pbEKey[0x0D] = 0;
+ pbEKey[0x0E] = 0;
+ pbEKey[0x0F] = 0;
+ }
+ }
+
+ return pbData + EKeyLength;
+}
+
LPBYTE CaptureArray_(LPBYTE pbDataPtr, LPBYTE pbDataEnd, LPBYTE * PtrArray, size_t ItemSize, size_t ItemCount)
{
size_t ArraySize = ItemSize * ItemCount;
@@ -229,6 +285,7 @@ size_t CascStrPrintf(char * buffer, size_t nCount, const char * format, ...)
#ifdef PLATFORM_WINDOWS
StringCchVPrintfExA(buffer, nCount, &buffend, NULL, 0, format, argList);
+// buffend = buffer + vsnprintf(buffer, nCount, format, argList);
#else
buffend = buffer + vsnprintf(buffer, nCount, format, argList);
#endif
@@ -248,6 +305,7 @@ size_t CascStrPrintf(wchar_t * buffer, size_t nCount, const wchar_t * format, ..
#ifdef PLATFORM_WINDOWS
StringCchVPrintfExW(buffer, nCount, &buffend, NULL, 0, format, argList);
+// buffend = buffer + vswprintf(buffer, nCount, format, argList);
#else
buffend = buffer + vswprintf(buffer, nCount, format, argList);
#endif
@@ -268,7 +326,7 @@ char * CascNewStr(const char * szString, size_t nCharsToReserve)
if(szString != NULL)
{
nLength = strlen(szString);
- szNewString = CASC_ALLOC(char, nLength + nCharsToReserve + 1);
+ szNewString = CASC_ALLOC<char>(nLength + nCharsToReserve + 1);
if(szNewString != NULL)
{
memcpy(szNewString, szString, nLength);
@@ -287,7 +345,7 @@ wchar_t * CascNewStr(const wchar_t * szString, size_t nCharsToReserve)
if(szString != NULL)
{
nLength = wcslen(szString);
- szNewString = CASC_ALLOC(wchar_t, nLength + nCharsToReserve + 1);
+ szNewString = CASC_ALLOC<wchar_t>(nLength + nCharsToReserve + 1);
if(szNewString != NULL)
{
memcpy(szNewString, szString, nLength * sizeof(wchar_t));
@@ -298,43 +356,8 @@ wchar_t * CascNewStr(const wchar_t * szString, size_t nCharsToReserve)
return szNewString;
}
-template <typename XCHAR>
-TCHAR * AppendPathFragment(TCHAR * szBuffer, TCHAR * szBufferEnd, const XCHAR * szPath, char chSeparator, bool bFirstFragment = false)
-{
- // The "Path" must not be empty
- if(szPath && szPath[0])
- {
- // Append the path separator after the first fragment
- if(szBuffer < szBufferEnd && bFirstFragment == false)
- {
- if(szBuffer[-1] != chSeparator)
- {
- *szBuffer++ = chSeparator;
- }
- }
-
- // Copy the sub path
- while(szBuffer < szBufferEnd && szPath[0] != 0)
- {
- // If there is a path separator, we skip it (all of them) and put single separator there
- if(szPath[0] == '\\' || szPath[0] == '/')
- {
- while(szPath[0] == '\\' || szPath[0] == '/')
- szPath++;
- *szBuffer++ = chSeparator;
- }
- else
- {
- *szBuffer++ = *szPath++;
- }
- }
-
- // Append end of string
- szBuffer[0] = 0;
- }
-
- return szBuffer;
-}
+//-----------------------------------------------------------------------------
+// String merging
LPTSTR GetLastPathPart(LPTSTR szWorkPath)
{
@@ -377,19 +400,18 @@ bool CutLastPathPart(TCHAR * szWorkPath)
size_t CombinePath(LPTSTR szBuffer, size_t nMaxChars, char chSeparator, va_list argList)
{
- LPTSTR szSaveBuffer = szBuffer;
- LPTSTR szBufferEnd = szBuffer + nMaxChars - 1;
- LPTSTR szFragment;
- bool bFirstFragment = true;
+ CASC_PATH<TCHAR> Path(chSeparator);
+ LPCTSTR szFragment;
+ bool bWithSeparator = false;
// Combine all parts of the path here
while((szFragment = va_arg(argList, LPTSTR)) != NULL)
{
- szBuffer = AppendPathFragment(szBuffer, szBufferEnd, szFragment, chSeparator, bFirstFragment);
- bFirstFragment = false;
+ Path.AppendString(szFragment, bWithSeparator);
+ bWithSeparator = true;
}
- return (szBuffer - szSaveBuffer);
+ return Path.Copy(szBuffer, nMaxChars);
}
size_t CombinePath(LPTSTR szBuffer, size_t nMaxChars, char chSeparator, ...)
@@ -406,40 +428,12 @@ size_t CombinePath(LPTSTR szBuffer, size_t nMaxChars, char chSeparator, ...)
LPTSTR CombinePath(LPCTSTR szDirectory, LPCTSTR szSubDir)
{
- LPTSTR szFullPath;
- size_t nLength = 0;
+ CASC_PATH<TCHAR> Path(PATH_SEP_CHAR);
- // Calculate length
- if(szDirectory != NULL)
- nLength += (_tcslen(szDirectory) + 1);
- if(szSubDir != NULL)
- nLength += (_tcslen(szSubDir) + 1);
-
- // Allocate buffer
- if((szFullPath = CASC_ALLOC(TCHAR, nLength)) != NULL)
- {
- CombinePath(szFullPath, nLength, PATH_SEP_CHAR, szDirectory, szSubDir, NULL);
- }
-
- return szFullPath;
-}
-
-size_t CreateCascSubdirectoryName(LPTSTR szBuffer, size_t nMaxChars, LPCTSTR szSubDir, LPCTSTR szExtension, LPBYTE pbEKey)
-{
- TCHAR * szSaveBuffer = szBuffer;
- TCHAR * szBufferEnd = szBuffer + nMaxChars - 1;
- char szHashSubPath[0x80];
- char szHashText[MD5_STRING_SIZE+1];
-
- // Prepare the subpath
- StringFromBinary(pbEKey, MD5_HASH_SIZE, szHashText);
- CascStrPrintf(szHashSubPath, _countof(szHashSubPath), "%02x/%02x/%s", pbEKey[0], pbEKey[1], szHashText);
-
- // Combine the path together
- szBuffer = AppendPathFragment(szBuffer, szBufferEnd, szSubDir, URL_SEP_CHAR, true);
- szBuffer = AppendPathFragment(szBuffer, szBufferEnd, szHashSubPath, URL_SEP_CHAR);
- szBuffer = AppendPathFragment(szBuffer, szBufferEnd, szExtension, URL_SEP_CHAR, true);
- return (szBuffer - szSaveBuffer);
+ // Merge the path
+ Path.AppendString(szDirectory, false);
+ Path.AppendString(szSubDir, true);
+ return Path.New();
}
size_t NormalizeFileName(const unsigned char * NormTable, char * szNormName, const char * szFileName, size_t cchMaxChars)
@@ -585,32 +579,6 @@ int ConvertStringToBinary(
return ERROR_SUCCESS;
}
-char * StringFromBinary(LPBYTE pbBinary, size_t cbBinary, char * szBuffer)
-{
- char * szSaveBuffer = szBuffer;
-
- // Verify the binary pointer
- if(pbBinary && cbBinary)
- {
- // Convert the string to the array of MD5
- // Copy the blob data as text
- for(size_t i = 0; i < cbBinary; i++)
- {
- *szBuffer++ = IntToHexChar[pbBinary[i] >> 0x04];
- *szBuffer++ = IntToHexChar[pbBinary[i] & 0x0F];
- }
- }
-
- // Terminate the string
- *szBuffer = 0;
- return szSaveBuffer;
-}
-
-char * StringFromMD5(LPBYTE md5, char * szBuffer)
-{
- return StringFromBinary(md5, MD5_HASH_SIZE, szBuffer);
-}
-
//-----------------------------------------------------------------------------
// File name utilities
@@ -693,10 +661,8 @@ bool CascCheckWildCard(const char * szString, const char * szWildCard)
{
if(szWildCardPtr[0] == '*')
{
- szWildCardPtr++;
-
- if(szWildCardPtr[0] == '*')
- continue;
+ while(szWildCardPtr[0] == '*')
+ szWildCardPtr++;
if(szWildCardPtr[0] == 0)
return true;
diff --git a/dep/CascLib/src/common/Common.h b/dep/CascLib/src/common/Common.h
index 45a2ec93e6b..d32202413ba 100644
--- a/dep/CascLib/src/common/Common.h
+++ b/dep/CascLib/src/common/Common.h
@@ -39,13 +39,19 @@ typedef struct _CONTENT_KEY
} CONTENT_KEY, *PCONTENT_KEY, ENCODED_KEY, *PENCODED_KEY;
-// Helper structure for merging file paths
-typedef struct _PATH_BUFFER
+//-----------------------------------------------------------------------------
+// EKey entry, captured from index files of all types. This structure
+// is somewhat less memory consuming than CASC_CKEY_ENTRY
+
+typedef struct _CASC_EKEY_ENTRY
{
- char * szBegin;
- char * szPtr;
- char * szEnd;
-} PATH_BUFFER, *PPATH_BUFFER;
+ BYTE EKey[MD5_HASH_SIZE]; // Encoded key. Length depends on TCascStorage::EKeyLength
+ ULONGLONG StorageOffset; // Offset of the encoded file in archive.
+ // Lower (TCascStorage::FileOffsetBits) bits are archive offset.
+ // Upper bits are archive index
+ DWORD EncodedSize; // Encoded size
+ DWORD Alignment; // Alignment to 8-byte boundary. Reserved for future use
+} CASC_EKEY_ENTRY, *PCASC_EKEY_ENTRY;
//-----------------------------------------------------------------------------
// Basic structure used by all CascLib objects to describe a single entry
@@ -59,7 +65,12 @@ typedef struct _PATH_BUFFER
#define CASC_CE_HAS_EKEY_PARTIAL 0x00000008 // The EKey is only partial, padded by zeros. Always used with CASC_CE_HAS_EKEY
#define CASC_CE_IN_ENCODING 0x00000010 // Present in the ENCODING manifest
#define CASC_CE_IN_DOWNLOAD 0x00000020 // Present in the DOWNLOAD manifest
-#define CASC_CE_FOLDER_ENTRY 0x00000040 // This CKey entry is a folder
+#define CASC_CE_IN_BUILD 0x00000040 // Present in the BUILD (text) manifest
+#define CASC_CE_IN_ARCHIVE 0x00000080 // File is stored in an archive (for online storages)
+#define CASC_CE_FOLDER_ENTRY 0x00000100 // This CKey entry is a folder
+#define CASC_CE_FILE_SPAN 0x00000200 // This CKey entry is a follow-up file span
+#define CASC_CE_FILE_PATCH 0x00000400 // The file is in PATCH subfolder in remote storage
+#define CASC_CE_PLAIN_DATA 0x00000800 // The file data is not BLTE encoded, but in plain format
// In-memory representation of a single entry.
struct CASC_CKEY_ENTRY
@@ -75,19 +86,36 @@ struct CASC_CKEY_ENTRY
StorageOffset = CASC_INVALID_OFFS64;
EncodedSize = CASC_INVALID_SIZE;
ContentSize = CASC_INVALID_SIZE;
+ SpanCount = 1;
+ }
+
+ bool IsFile()
+ {
+ // Must not be a folder entry
+ if((Flags & CASC_CE_FOLDER_ENTRY) == 0)
+ {
+ // There can be entries that are both file span or the standalone file
+ // * zone/zm_red.xpak - { zone/zm_red.xpak_1, zone/zm_red.xpak_2, ..., zone/zm_red.xpak_6 }
+ if(RefCount != 0)
+ return true;
+
+ // To include the file, it must either be present in ENCODING, DOWNLOAD or in BUILD file
+ if(((Flags & CASC_CE_FILE_SPAN) == 0) && (Flags & (CASC_CE_IN_ENCODING | CASC_CE_IN_DOWNLOAD | CASC_CE_IN_BUILD)))
+ return true;
+ }
+ return false;
}
BYTE CKey[MD5_HASH_SIZE]; // Content key of the full length
BYTE EKey[MD5_HASH_SIZE]; // Encoded key of the full length
ULONGLONG StorageOffset; // Linear offset over the entire storage. 0 if not present
ULONGLONG TagBitMask; // Bitmap for the tags. 0 ig tags are not supported
- DWORD EncodedSize; // Encoded size of the file. 0 if not supported
- DWORD ContentSize; // Content size of the file. 0 if not supported
+ DWORD ContentSize; // Content size of the file
+ DWORD EncodedSize; // Encoded size of the file
DWORD Flags; // See CASC_CE_XXX
USHORT RefCount; // This is the number of file names referencing this entry
+ BYTE SpanCount; // Number of spans for the file
BYTE Priority; // Download priority
- BYTE Alignment;
-
};
typedef CASC_CKEY_ENTRY *PCASC_CKEY_ENTRY;
@@ -112,7 +140,22 @@ extern unsigned char IntToHexChar[];
//
#define CASC_REALLOC(type, ptr, count) (type *)realloc(ptr, (count) * sizeof(type))
-#define CASC_ALLOC(type, count) (type *)malloc((count) * sizeof(type))
+
+template <typename T>
+T * CASC_ALLOC(size_t nCount)
+{
+ return (T *)malloc(nCount * sizeof(T));
+}
+
+template <typename T>
+T * CASC_ALLOC_ZERO(size_t nCount)
+{
+ T * ptr = CASC_ALLOC<T>(nCount);
+
+ if(ptr != NULL)
+ memset(ptr, 0, sizeof(T) * nCount);
+ return ptr;
+}
template <typename T>
void CASC_FREE(T *& ptr)
@@ -241,12 +284,14 @@ inline void CopyMemory16(void * Target, void * Source)
}
//-----------------------------------------------------------------------------
-// Linear data stream manipulation
+// Capturing various integral values
+LPBYTE CaptureInteger16_BE(LPBYTE pbDataPtr, LPBYTE pbDataEnd, PDWORD PtrValue);
LPBYTE CaptureInteger32(LPBYTE pbDataPtr, LPBYTE pbDataEnd, PDWORD PtrValue);
LPBYTE CaptureInteger32_BE(LPBYTE pbDataPtr, LPBYTE pbDataEnd, PDWORD PtrValue);
LPBYTE CaptureByteArray(LPBYTE pbDataPtr, LPBYTE pbDataEnd, size_t nLength, LPBYTE pbOutput);
LPBYTE CaptureContentKey(LPBYTE pbDataPtr, LPBYTE pbDataEnd, PCONTENT_KEY * PtrCKey);
+LPBYTE CaptureEncodedKey(LPBYTE pbEKey, LPBYTE pbData, BYTE EKeyLength);
LPBYTE CaptureArray_(LPBYTE pbDataPtr, LPBYTE pbDataEnd, LPBYTE * PtrArray, size_t ItemSize, size_t ItemCount);
#define CaptureArray(pbDataPtr, pbDataEnd, PtrArray, type, count) CaptureArray_(pbDataPtr, pbDataEnd, PtrArray, sizeof(type), count)
@@ -277,7 +322,6 @@ LPTSTR CombinePath(LPCTSTR szPath, LPCTSTR szSubDir);
LPTSTR GetLastPathPart(LPTSTR szWorkPath);
bool CutLastPathPart(TCHAR * szWorkPath);
-size_t CreateCascSubdirectoryName(TCHAR * szBuffer, size_t nMaxChars, const TCHAR * szSubDir, const TCHAR * szExtension, LPBYTE pbEKey);
size_t NormalizeFileName_UpperBkSlash(char * szNormName, const char * szFileName, size_t cchMaxChars);
size_t NormalizeFileName_LowerSlash(char * szNormName, const char * szFileName, size_t cchMaxChars);
@@ -288,8 +332,31 @@ int ConvertDigitToInt32(const TCHAR * szString, PDWORD PtrValue);
int ConvertStringToInt08(const char * szString, PDWORD PtrValue);
int ConvertStringToInt32(const TCHAR * szString, size_t nMaxDigits, PDWORD PtrValue);
int ConvertStringToBinary(const char * szString, size_t nMaxDigits, LPBYTE pbBinary);
-char * StringFromBinary(LPBYTE pbBinary, size_t cbBinary, char * szBuffer);
-char * StringFromMD5(LPBYTE md5, char * szBuffer);
+
+//-----------------------------------------------------------------------------
+// Conversion from 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)
+{
+ xchar * szSaveBuffer = szBuffer;
+
+ // Verify the binary pointer
+ if(pbBinary && cbBinary)
+ {
+ // Convert the bytes to string array
+ for(size_t i = 0; i < cbBinary; i++)
+ {
+ *szBuffer++ = IntToHexChar[pbBinary[i] >> 0x04];
+ *szBuffer++ = IntToHexChar[pbBinary[i] & 0x0F];
+ }
+ }
+
+ // Terminate the string
+ *szBuffer = 0;
+ return szSaveBuffer;
+}
//-----------------------------------------------------------------------------
// Structure query key
diff --git a/dep/CascLib/src/common/Csv.cpp b/dep/CascLib/src/common/Csv.cpp
index 24b654daa86..c665fc00c4c 100644
--- a/dep/CascLib/src/common/Csv.cpp
+++ b/dep/CascLib/src/common/Csv.cpp
@@ -185,10 +185,10 @@ CASC_CSV::~CASC_CSV()
m_szCsvFile = NULL;
}
-int CASC_CSV::Load(const TCHAR * szFileName)
+DWORD CASC_CSV::Load(const TCHAR * szFileName)
{
DWORD cbFileData = 0;
- int nError = ERROR_SUCCESS;
+ DWORD dwErrCode = ERROR_SUCCESS;
m_szCsvFile = (char *)LoadFileToMemory(szFileName, &cbFileData);
if (m_szCsvFile != NULL)
@@ -199,19 +199,19 @@ int CASC_CSV::Load(const TCHAR * szFileName)
m_nCsvFile = cbFileData;
// Parse the data
- nError = ParseCsvData() ? ERROR_SUCCESS : ERROR_BAD_FORMAT;
+ dwErrCode = ParseCsvData() ? ERROR_SUCCESS : ERROR_BAD_FORMAT;
}
else
{
- nError = GetLastError();
+ dwErrCode = GetLastError();
}
- return nError;
+ return dwErrCode;
}
-int CASC_CSV::Load(LPBYTE pbData, size_t cbData)
+DWORD CASC_CSV::Load(LPBYTE pbData, size_t cbData)
{
- int nError = ERROR_NOT_ENOUGH_MEMORY;
+ DWORD dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
m_szCsvFile = new char[cbData + 1];
if (m_szCsvFile != NULL)
@@ -223,10 +223,10 @@ int CASC_CSV::Load(LPBYTE pbData, size_t cbData)
m_nCsvFile = cbData;
// Parse the data
- nError = ParseCsvData() ? ERROR_SUCCESS : ERROR_BAD_FORMAT;
+ dwErrCode = ParseCsvData() ? ERROR_SUCCESS : ERROR_BAD_FORMAT;
}
- return nError;
+ return dwErrCode;
}
bool CASC_CSV::LoadNextLine()
diff --git a/dep/CascLib/src/common/Csv.h b/dep/CascLib/src/common/Csv.h
index bf1a7413e13..394eab1e2f0 100644
--- a/dep/CascLib/src/common/Csv.h
+++ b/dep/CascLib/src/common/Csv.h
@@ -69,8 +69,8 @@ class CASC_CSV
CASC_CSV(size_t nLinesMax, bool bHasHeader);
~CASC_CSV();
- int Load(LPBYTE pbData, size_t cbData);
- int Load(const TCHAR * szFileName);
+ DWORD Load(LPBYTE pbData, size_t cbData);
+ DWORD Load(const TCHAR * szFileName);
bool LoadNextLine();
const CASC_CSV_COLUMN & operator[](const char * szColumnName) const;
diff --git a/dep/CascLib/src/common/FileStream.cpp b/dep/CascLib/src/common/FileStream.cpp
index 845e793a6fa..cd3300a46a7 100644
--- a/dep/CascLib/src/common/FileStream.cpp
+++ b/dep/CascLib/src/common/FileStream.cpp
@@ -615,7 +615,7 @@ static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD
HINTERNET hRequest;
DWORD dwTemp = 0;
bool bFileAvailable = false;
- int nError = ERROR_SUCCESS;
+ DWORD dwErrCode = ERROR_SUCCESS;
// Check alternate ports
if(dwStreamFlags & STREAM_FLAG_USE_PORT_1119)
@@ -625,10 +625,10 @@ static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD
// Don't download if we are not connected to the internet
if(!InternetGetConnectedState(&dwTemp, 0))
- nError = GetLastError();
+ dwErrCode = GetLastError();
// Initiate the connection to the internet
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
pStream->Base.Http.hInternet = InternetOpen(_T("agent/2.17.2.6700"),
INTERNET_OPEN_TYPE_PRECONFIG,
@@ -636,11 +636,11 @@ static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD
NULL,
0);
if(pStream->Base.Http.hInternet == NULL)
- nError = GetLastError();
+ dwErrCode = GetLastError();
}
// Connect to the server
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
TCHAR szServerName[MAX_PATH];
DWORD dwFlags = INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_CACHE_WRITE;
@@ -656,11 +656,11 @@ static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD
dwFlags,
0);
if(pStream->Base.Http.hConnect == NULL)
- nError = GetLastError();
+ dwErrCode = GetLastError();
}
// Now try to query the file size
- if(nError == ERROR_SUCCESS)
+ if(dwErrCode == ERROR_SUCCESS)
{
// Open HTTP request to the file
hRequest = HttpOpenRequest(pStream->Base.Http.hConnect, _T("GET"), szFileName, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
@@ -702,7 +702,7 @@ static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD
}
else
{
- nError = ERROR_FILE_NOT_FOUND;
+ dwErrCode = ERROR_FILE_NOT_FOUND;
}
}
InternetCloseHandle(hRequest);
@@ -714,7 +714,7 @@ static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD
if(bFileAvailable == false)
{
pStream->BaseClose(pStream);
- SetLastError(nError);
+ SetLastError(dwErrCode);
return false;
}
@@ -889,7 +889,7 @@ static bool BlockStream_Read(
BlockBufferOffset = (DWORD)(ByteOffset & (BlockSize - 1));
// Allocate buffer for reading blocks
- TransferBuffer = BlockBuffer = CASC_ALLOC(BYTE, (BlockCount * BlockSize));
+ TransferBuffer = BlockBuffer = CASC_ALLOC<BYTE>(BlockCount * BlockSize);
if(TransferBuffer == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
@@ -1054,7 +1054,7 @@ static TFileStream * AllocateFileStream(
}
// Allocate the stream structure for the given stream type
- pStream = (TFileStream *)CASC_ALLOC(BYTE, StreamSize + FileNameSize + sizeof(TCHAR));
+ pStream = (TFileStream *)CASC_ALLOC<BYTE>(StreamSize + FileNameSize + sizeof(TCHAR));
if(pStream != NULL)
{
// Zero the entire structure
@@ -1137,7 +1137,7 @@ static bool FlatStream_LoadBitmap(TBlockStream * pStream)
if(ByteOffset + BitmapSize + sizeof(FILE_BITMAP_FOOTER) == pStream->Base.File.FileSize)
{
// Allocate space for the bitmap
- FileBitmap = CASC_ALLOC(BYTE, BitmapSize);
+ FileBitmap = CASC_ALLOC<BYTE>(BitmapSize);
if(FileBitmap != NULL)
{
// Load the bitmap bits
@@ -1349,12 +1349,11 @@ static bool FlatStream_CreateMirror(TBlockStream * pStream)
}
// Allocate the bitmap array
- FileBitmap = CASC_ALLOC(BYTE, dwBitmapSize);
+ FileBitmap = CASC_ALLOC_ZERO<BYTE>(dwBitmapSize);
if(FileBitmap == NULL)
return false;
// Initialize the bitmap
- memset(FileBitmap, 0, dwBitmapSize);
pStream->FileBitmap = FileBitmap;
pStream->BitmapSize = dwBitmapSize;
pStream->BlockSize = DEFAULT_BLOCK_SIZE;
@@ -1521,7 +1520,7 @@ static bool PartStream_LoadBitmap(TBlockStream * pStream)
if((ByteOffset + BitmapSize) < pStream->Base.File.FileSize)
{
// Allocate space for the array of PART_FILE_MAP_ENTRY
- FileBitmap = CASC_ALLOC(PART_FILE_MAP_ENTRY, BlockCount);
+ FileBitmap = CASC_ALLOC<PART_FILE_MAP_ENTRY>(BlockCount);
if(FileBitmap != NULL)
{
// Load the block map
@@ -1771,12 +1770,11 @@ static bool PartStream_CreateMirror(TBlockStream * pStream)
}
// Allocate the bitmap array
- FileBitmap = CASC_ALLOC(BYTE, dwBitmapSize);
+ FileBitmap = CASC_ALLOC_ZERO<BYTE>(dwBitmapSize);
if(FileBitmap == NULL)
return false;
// Initialize the bitmap
- memset(FileBitmap, 0, dwBitmapSize);
pStream->FileBitmap = FileBitmap;
pStream->BitmapSize = dwBitmapSize;
pStream->BlockSize = DEFAULT_BLOCK_SIZE;
@@ -2268,7 +2266,7 @@ static TFileStream * Block4Stream_Open(const TCHAR * szFileName, DWORD dwStreamF
pStream->BlockRead = (BLOCK_READ)Block4Stream_BlockRead;
// Allocate work space for numeric names
- szNameBuff = CASC_ALLOC(TCHAR, nNameLength + 4);
+ szNameBuff = CASC_ALLOC<TCHAR>(nNameLength + 4);
if(szNameBuff != NULL)
{
// Set the base flags
@@ -2283,7 +2281,7 @@ static TFileStream * Block4Stream_Open(const TCHAR * szFileName, DWORD dwStreamF
break;
// If the open succeeded, we re-allocate the base provider array
- NewBaseArray = CASC_ALLOC(TBaseProviderData, dwBaseFiles + 1);
+ NewBaseArray = CASC_ALLOC<TBaseProviderData>(dwBaseFiles + 1);
if(NewBaseArray == NULL)
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
@@ -2369,7 +2367,7 @@ static TFileStream * Block4Stream_Open(const TCHAR * szFileName, DWORD dwStreamF
*/
TFileStream * FileStream_CreateFile(
- const TCHAR * szFileName,
+ LPCTSTR szFileName,
DWORD dwStreamFlags)
{
TFileStream * pStream;
@@ -2424,7 +2422,7 @@ TFileStream * FileStream_CreateFile(
*/
TFileStream * FileStream_OpenFile(
- const TCHAR * szFileName,
+ LPCTSTR szFileName,
DWORD dwStreamFlags)
{
DWORD dwProvider = dwStreamFlags & STREAM_PROVIDERS_MASK;
@@ -2473,7 +2471,7 @@ const TCHAR * FileStream_GetFileName(TFileStream * pStream)
* \a pdwStreamProvider Pointer to a DWORD variable that receives stream provider (STREAM_PROVIDER_XXX)
*/
-size_t FileStream_Prefix(const TCHAR * szFileName, DWORD * pdwProvider)
+size_t FileStream_Prefix(LPCTSTR szFileName, DWORD * pdwProvider)
{
size_t nPrefixLength1 = 0;
size_t nPrefixLength2 = 0;
@@ -2592,14 +2590,6 @@ bool FileStream_SetCallback(TFileStream * pStream, STREAM_DOWNLOAD_CALLBACK pfnC
*/
bool FileStream_Read(TFileStream * pStream, ULONGLONG * pByteOffset, void * pvBuffer, DWORD dwBytesToRead)
{
- //FILE * fp = fopen("E:\\Loading.txt", "at");
- //if(fp != NULL)
- //{
- // ULONGLONG ByteOffset = (pByteOffset != NULL) ? pByteOffset[0] : 0;
- // fprintf(fp, "%-32ws\t%08X\t%08X\n", GetPlainFileName(pStream->szFileName), (ULONG)ByteOffset, dwBytesToRead);
- // fclose(fp);
- //}
-
assert(pStream->StreamRead != NULL);
return pStream->StreamRead(pStream, pByteOffset, pvBuffer, dwBytesToRead);
}
diff --git a/dep/CascLib/src/common/FileStream.h b/dep/CascLib/src/common/FileStream.h
index a2b0c5b9f7d..e934cca062f 100644
--- a/dep/CascLib/src/common/FileStream.h
+++ b/dep/CascLib/src/common/FileStream.h
@@ -247,10 +247,10 @@ struct TEncryptedStream : public TBlockStream
//-----------------------------------------------------------------------------
// Public functions for file stream
-TFileStream * FileStream_CreateFile(const TCHAR * szFileName, DWORD dwStreamFlags);
-TFileStream * FileStream_OpenFile(const TCHAR * szFileName, DWORD dwStreamFlags);
+TFileStream * FileStream_CreateFile(LPCTSTR szFileName, DWORD dwStreamFlags);
+TFileStream * FileStream_OpenFile(LPCTSTR szFileName, DWORD dwStreamFlags);
const TCHAR * FileStream_GetFileName(TFileStream * pStream);
-size_t FileStream_Prefix(const TCHAR * szFileName, DWORD * pdwProvider);
+size_t FileStream_Prefix(LPCTSTR szFileName, DWORD * pdwProvider);
bool FileStream_SetCallback(TFileStream * pStream, STREAM_DOWNLOAD_CALLBACK pfnCallback, void * pvUserData);
diff --git a/dep/CascLib/src/common/FileTree.cpp b/dep/CascLib/src/common/FileTree.cpp
index f753c25f263..ceb578cf578 100644
--- a/dep/CascLib/src/common/FileTree.cpp
+++ b/dep/CascLib/src/common/FileTree.cpp
@@ -30,28 +30,7 @@ inline void SET_NODE_INT32(void * node, size_t offset, DWORD value)
PtrValue[0] = value;
}
-/*
-static bool CompareFileNode(void * pvObject, void * pvUserData)
-{
- PCASC_COMPARE_CONTEXT pCtx = (PCASC_COMPARE_CONTEXT)pvUserData;
- PCASC_FILE_TREE pFileTree = (PCASC_FILE_TREE)pCtx->pThis;
- PCASC_FILE_NODE pFileNode = (PCASC_FILE_NODE)pvObject;
- char szFullPath[MAX_PATH];
- // First of all, the name hash must match
- if(pFileNode->FileNameHash == pCtx->FileNameHash)
- {
- // Then also compare the full path name
- pFileTree->PathAt(szFullPath, _countof(szFullPath), pFileNode);
- if(!_stricmp(szFullPath, pCtx->szFileName))
- {
- return true;
- }
- }
-
- return false;
-}
-*/
//-----------------------------------------------------------------------------
// Protected functions
@@ -224,11 +203,11 @@ bool CASC_FILE_TREE::RebuildNameMaps()
//-----------------------------------------------------------------------------
// Public functions
-int CASC_FILE_TREE::Create(DWORD Flags)
+DWORD CASC_FILE_TREE::Create(DWORD Flags)
{
PCASC_FILE_NODE pRootNode;
size_t FileNodeSize = FIELD_OFFSET(CASC_FILE_NODE, ExtraValues);
- int nError;
+ DWORD dwErrCode;
// Initialize the file tree
memset(this, 0, sizeof(CASC_FILE_TREE));
@@ -242,9 +221,9 @@ int CASC_FILE_TREE::Create(DWORD Flags)
FileNodeSize += sizeof(DWORD);
// Create the array for FileDataId -> CASC_FILE_NODE
- nError = FileDataIds.Create<PCASC_FILE_NODE>(START_ITEM_COUNT);
- if(nError != ERROR_SUCCESS)
- return nError;
+ dwErrCode = FileDataIds.Create<PCASC_FILE_NODE>(START_ITEM_COUNT);
+ if(dwErrCode != ERROR_SUCCESS)
+ return dwErrCode;
}
// Shall we use the locale ID in the tree node?
@@ -264,12 +243,12 @@ int CASC_FILE_TREE::Create(DWORD Flags)
FileNodeSize = ALIGN_TO_SIZE(FileNodeSize, 8);
// Initialize the dynamic array
- nError = NodeTable.Create(FileNodeSize, START_ITEM_COUNT);
- if(nError == ERROR_SUCCESS)
+ dwErrCode = NodeTable.Create(FileNodeSize, START_ITEM_COUNT);
+ if(dwErrCode == ERROR_SUCCESS)
{
// Create the dynamic array that will hold the node names
- nError = NameTable.Create<char>(START_ITEM_COUNT);
- if(nError == ERROR_SUCCESS)
+ dwErrCode = NameTable.Create<char>(START_ITEM_COUNT);
+ if(dwErrCode == ERROR_SUCCESS)
{
// Insert the first "root" node, without name
pRootNode = (PCASC_FILE_NODE)NodeTable.Insert(1);
@@ -287,8 +266,8 @@ int CASC_FILE_TREE::Create(DWORD Flags)
// Create both maps
if(!RebuildNameMaps())
- nError = ERROR_NOT_ENOUGH_MEMORY;
- return nError;
+ dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
+ return dwErrCode;
}
void CASC_FILE_TREE::Free()
@@ -307,21 +286,26 @@ void CASC_FILE_TREE::Free()
PCASC_FILE_NODE CASC_FILE_TREE::InsertByName(PCASC_CKEY_ENTRY pCKeyEntry, const char * szFileName, DWORD FileDataId, DWORD LocaleFlags, DWORD ContentFlags)
{
- CASC_COMPARE_CONTEXT CmpCtx;
PCASC_FILE_NODE pFileNode;
+ ULONGLONG FileNameHash;
// Sanity checks
assert(szFileName != NULL && szFileName[0] != 0);
assert(pCKeyEntry != NULL);
+ //char szCKey[MD5_STRING_SIZE+1];
+ //char szEKey[MD5_STRING_SIZE+1];
+ //StringFromBinary(pCKeyEntry->CKey, MD5_HASH_SIZE, szCKey);
+ //StringFromBinary(pCKeyEntry->EKey, MD5_HASH_SIZE, szEKey);
+ //printf("%s\t%s\t%s\n", szCKey, szEKey, szFileName);
+
+ //BREAK_ON_XKEY3(pCKeyEntry->EKey, 0x03, 0xDC, 0x7D);
+
// Calculate the file name hash
- CmpCtx.FileNameHash = CalcFileNameHash(szFileName);
-// CmpCtx.szFileName = szFileName;
-// CmpCtx.pThis = this;
+ FileNameHash = CalcFileNameHash(szFileName);
// Do nothing if the file name is there already.
-// pFileNode = (PCASC_FILE_NODE)NameMap.FindObjectEx(CompareFileNode, &CmpCtx);
- pFileNode = (PCASC_FILE_NODE)NameMap.FindObject(&CmpCtx.FileNameHash);
+ pFileNode = (PCASC_FILE_NODE)NameMap.FindObject(&FileNameHash);
if(pFileNode == NULL)
{
// Insert new item
@@ -329,7 +313,7 @@ PCASC_FILE_NODE CASC_FILE_TREE::InsertByName(PCASC_CKEY_ENTRY pCKeyEntry, const
if(pFileNode != NULL)
{
// Supply the name hash
- pFileNode->FileNameHash = CmpCtx.FileNameHash;
+ pFileNode->FileNameHash = FileNameHash;
// Set the file data id and the extra values
SetExtras(pFileNode, FileDataId, LocaleFlags, ContentFlags);
@@ -340,12 +324,13 @@ PCASC_FILE_NODE CASC_FILE_TREE::InsertByName(PCASC_CKEY_ENTRY pCKeyEntry, const
// Also make sure that it's in the file data id table, if the table is initialized
InsertToIdTable(pFileNode);
- // Set the file name of the new file node. This also increments the number of references
+ // Set the file name of the new file node
SetNodeFileName(pFileNode, szFileName);
// If we created a new node, we need to increment the reference count
assert(pCKeyEntry->RefCount != 0xFFFF);
pCKeyEntry->RefCount++;
+ FileNodes++;
}
}
@@ -492,8 +477,6 @@ PCASC_FILE_NODE CASC_FILE_TREE::Find(const char * szFullPath, DWORD FileDataId,
if(pFileNode != NULL && pFindData != NULL)
{
GetExtras(pFileNode, &pFindData->dwFileDataId, &pFindData->dwLocaleFlags, &pFindData->dwContentFlags);
- pFindData->bCanOpenByName = (pFileNode->FileNameHash != 0);
- pFindData->bCanOpenByDataId = (FileDataIdOffset != 0);
}
return pFileNode;
@@ -543,7 +526,85 @@ bool CASC_FILE_TREE::SetNodeFileName(PCASC_FILE_NODE pFileNode, const char * szF
{
ULONGLONG FileNameHash = 0;
PCASC_FILE_NODE pFolderNode = NULL;
- const char * szNodeBegin = szFileName;
+ CASC_PATH<char> PathBuffer;
+ LPCSTR szNodeBegin = szFileName;
+ size_t nFileNode = NodeTable.IndexOf(pFileNode);
+ size_t i;
+ DWORD Parent = 0;
+
+ // Sanity checks
+ assert(szFileName != NULL && szFileName[0] != 0);
+
+ // Traverse the entire path. For each subfolder, we insert an appropriate fake entry
+ for(i = 0; szFileName[i] != 0; i++)
+ {
+ char chOneChar = szFileName[i];
+
+ // Is there a path separator?
+ // Note: Warcraft III paths may contain "mount points".
+ // Example: "frFR-War3Local.mpq:Maps/FrozenThrone/Campaign/NightElfX06Interlude.w3x:war3map.j"
+ if(chOneChar == '\\' || chOneChar == '/' || chOneChar == ':')
+ {
+ // Calculate hash of the file name up to the end of the node name
+ FileNameHash = CalcNormNameHash(PathBuffer, i);
+
+ // If the entry is not there yet, create new one
+ if((pFolderNode = Find(FileNameHash)) == NULL)
+ {
+ // Insert new entry to the tree
+ pFolderNode = InsertNew();
+ if(pFolderNode == NULL)
+ return false;
+
+ // Populate the file entry
+ pFolderNode->FileNameHash = FileNameHash;
+ pFolderNode->Parent = Parent;
+ pFolderNode->Flags |= (chOneChar == ':') ? (CFN_FLAG_FOLDER | CFN_FLAG_MOUNT_POINT) : CFN_FLAG_FOLDER;
+ FolderNodes++;
+
+ // Set the node sub name to the node
+ SetNodePlainName(pFolderNode, szNodeBegin, szFileName + i);
+
+ // Insert the entry to the name map
+ InsertToHashTable(pFolderNode);
+ }
+
+ // Move the parent to the current node
+ Parent = (DWORD)NodeTable.IndexOf(pFolderNode);
+
+ // Move the begin of the node after the separator
+ szNodeBegin = szFileName + i + 1;
+ }
+
+ // Copy the next character, even if it was slash/backslash before
+ PathBuffer.AppendChar(AsciiToUpperTable_BkSlash[chOneChar]);
+ }
+
+ // If anything left, this is gonna be our node name
+ if(szNodeBegin < szFileName + i)
+ {
+ // We need to reset the file node pointer, as the file node table might have changed
+ pFileNode = (PCASC_FILE_NODE)NodeTable.ItemAt(nFileNode);
+
+ // Write the plain file name to the node
+ SetNodePlainName(pFileNode, szNodeBegin, szFileName + i);
+ pFileNode->Parent = Parent;
+
+ // Also insert the node to the hash table so CascOpenFile can find it
+ if(pFileNode->FileNameHash == 0)
+ {
+ pFileNode->FileNameHash = CalcNormNameHash(PathBuffer, i);
+ InsertToHashTable(pFileNode);
+ }
+ }
+ return true;
+}
+/*
+bool CASC_FILE_TREE::SetNodeFileName(PCASC_FILE_NODE pFileNode, const char * szFileName)
+{
+ ULONGLONG FileNameHash = 0;
+ PCASC_FILE_NODE pFolderNode = NULL;
+ LPCSTR szNodeBegin = szFileName;
char szPathBuffer[MAX_PATH+1];
size_t nFileNode = NodeTable.IndexOf(pFileNode);
size_t i;
@@ -551,7 +612,6 @@ bool CASC_FILE_TREE::SetNodeFileName(PCASC_FILE_NODE pFileNode, const char * szF
// Sanity checks
assert(szFileName != NULL && szFileName[0] != 0);
- assert(pFileNode->pCKeyEntry != NULL);
// Traverse the entire path. For each subfolder, we insert an appropriate fake entry
for(i = 0; szFileName[i] != 0; i++)
@@ -577,8 +637,8 @@ bool CASC_FILE_TREE::SetNodeFileName(PCASC_FILE_NODE pFileNode, const char * szF
// Populate the file entry
pFolderNode->FileNameHash = FileNameHash;
pFolderNode->Parent = Parent;
- pFolderNode->Flags |= (chOneChar == ':') ? CFN_FLAG_MOUNT_POINT : 0;
- pFolderNode->Flags |= CFN_FLAG_FOLDER;
+ pFolderNode->Flags |= (chOneChar == ':') ? (CFN_FLAG_FOLDER | CFN_FLAG_MOUNT_POINT) : CFN_FLAG_FOLDER;
+ FolderNodes++;
// Set the node sub name to the node
SetNodePlainName(pFolderNode, szNodeBegin, szFileName + i);
@@ -604,12 +664,20 @@ bool CASC_FILE_TREE::SetNodeFileName(PCASC_FILE_NODE pFileNode, const char * szF
// We need to reset the file node pointer, as the file node table might have changed
pFileNode = (PCASC_FILE_NODE)NodeTable.ItemAt(nFileNode);
+ // Write the plain file name to the node
SetNodePlainName(pFileNode, szNodeBegin, szFileName + i);
pFileNode->Parent = Parent;
+
+ // Also insert the node to the hash table so CascOpenFile can find it
+ if(pFileNode->FileNameHash == 0)
+ {
+ pFileNode->FileNameHash = CalcNormNameHash(szPathBuffer, i);
+ InsertToHashTable(pFileNode);
+ }
}
return true;
}
-
+*/
size_t CASC_FILE_TREE::GetMaxFileIndex()
{
if(FileDataIds.IsInitialized())
diff --git a/dep/CascLib/src/common/FileTree.h b/dep/CascLib/src/common/FileTree.h
index 904da6c4c46..38bc4e07e9f 100644
--- a/dep/CascLib/src/common/FileTree.h
+++ b/dep/CascLib/src/common/FileTree.h
@@ -25,32 +25,25 @@
typedef struct _CASC_FILE_NODE
{
ULONGLONG FileNameHash; // Jenkins hash of the normalized file name (uppercase, backslashes)
- PCASC_CKEY_ENTRY pCKeyEntry; // Pointer to the CKey entry.
+ PCASC_CKEY_ENTRY pCKeyEntry; // Pointer to the CKey entry
+
DWORD Parent; // The index of a parent directory. If CASC_INVALID_INDEX, then this is the root item
DWORD NameIndex; // Index of the node name. If CASC_INVALID_INDEX, then this node has no name
USHORT NameLength; // Length of the node name (without the zero terminator)
- USHORT Flags; // See CFE_FLAG_XXX
+ USHORT Flags; // See CFN_FLAG_XXX
DWORD ExtraValues[4]; // FileDataId: Only if FTREE_FLAG_USE_DATA_ID specified at create
// LocaleFlags: Only if FTREE_FLAG_USE_LOCALE_FLAGS specified at create
// ContentFlags: Only if FTREE_FLAG_USE_CONTENT_FLAGS specified at create
} CASC_FILE_NODE, *PCASC_FILE_NODE;
-// Common structure for comparing a file node
-typedef struct _CASC_COMPARE_CONTEXT
-{
- ULONGLONG FileNameHash;
- const char * szFileName;
- void * pThis;
-} CASC_COMPARE_CONTEXT, *PCASC_COMPARE_CONTEXT;
-
// Main structure for the file tree
class CASC_FILE_TREE
{
public:
// Initializes/destroys the entire tree
- int Create(DWORD Flags = 0);
+ DWORD Create(DWORD Flags = 0);
void Free();
// Inserts a new node to the tree; either with name or nameless
@@ -108,6 +101,8 @@ class CASC_FILE_TREE
size_t FileDataIdOffset; // If nonzero, this is the offset of the "FileDataId" field in the CASC_FILE_NODE
size_t LocaleFlagsOffset; // If nonzero, this is the offset of the "LocaleFlags" field in the CASC_FILE_NODE
size_t ContentFlagsOffset; // If nonzero, this is the offset of the "ContentFlags" field in the CASC_FILE_NODE
+ size_t FolderNodes; // Number of folder nodes
+ size_t FileNodes; // Number of file nodes
DWORD KeyLength; // Actual length of the key supported by the root handler
};
diff --git a/dep/CascLib/src/common/ListFile.cpp b/dep/CascLib/src/common/ListFile.cpp
index 36607d39186..a2239e18fa3 100644
--- a/dep/CascLib/src/common/ListFile.cpp
+++ b/dep/CascLib/src/common/ListFile.cpp
@@ -36,7 +36,7 @@ static PLISTFILE_CACHE ListFile_CreateCache(DWORD dwFileSize)
PLISTFILE_CACHE pCache;
// Allocate cache for one file block
- pCache = (PLISTFILE_CACHE)CASC_ALLOC(BYTE, sizeof(LISTFILE_CACHE) + dwFileSize);
+ pCache = (PLISTFILE_CACHE)CASC_ALLOC<BYTE>(sizeof(LISTFILE_CACHE) + dwFileSize);
if(pCache != NULL)
{
// Set the initial pointers
@@ -254,7 +254,7 @@ size_t ListFile_GetNext(void * pvListFile, char * szBuffer, size_t nMaxChars, PD
PLISTFILE_CACHE pCache = (PLISTFILE_CACHE)pvListFile;
const char * szTemp;
size_t nLength = 0;
- int nError = ERROR_SUCCESS;
+ DWORD dwErrCode = ERROR_SUCCESS;
// Check for parameters
for(;;)
@@ -266,12 +266,12 @@ size_t ListFile_GetNext(void * pvListFile, char * szBuffer, size_t nMaxChars, PD
if(pCache->Flags & LISTFILE_FLAG_USES_FILEDATAID)
{
// Retrieve the data ID from the current position
- nError = ListFile_GetFileDataId(pCache, &FileDataId);
- if(nError == ERROR_NO_MORE_FILES)
+ dwErrCode = ListFile_GetFileDataId(pCache, &FileDataId);
+ if(dwErrCode == ERROR_NO_MORE_FILES)
break;
// If there was an error, skip the current line
- if(nError != ERROR_SUCCESS || FileDataId == CASC_INVALID_ID)
+ if(dwErrCode != ERROR_SUCCESS || FileDataId == CASC_INVALID_ID)
{
ListFile_GetNextLine(pvListFile, &szTemp, &szTemp);
continue;
@@ -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)
{
- nError = GetLastError();
+ dwErrCode = GetLastError();
break;
}
@@ -291,8 +291,8 @@ size_t ListFile_GetNext(void * pvListFile, char * szBuffer, size_t nMaxChars, PD
return nLength;
}
- if(nError != ERROR_SUCCESS)
- SetLastError(nError);
+ if(dwErrCode != ERROR_SUCCESS)
+ SetLastError(dwErrCode);
return nLength;
}
diff --git a/dep/CascLib/src/common/Map.h b/dep/CascLib/src/common/Map.h
index 13799eb0528..a6eface844d 100644
--- a/dep/CascLib/src/common/Map.h
+++ b/dep/CascLib/src/common/Map.h
@@ -129,13 +129,8 @@ class CASC_MAP
return ERROR_NOT_ENOUGH_MEMORY;
// Allocate new map for the objects
- m_HashTable = (void **)CASC_ALLOC(void *, m_HashTableSize);
- if(m_HashTable == NULL)
- return ERROR_NOT_ENOUGH_MEMORY;
-
- // Initialize the map object
- memset(m_HashTable, 0, m_HashTableSize * sizeof(void *));
- return ERROR_SUCCESS;
+ m_HashTable = (void **)CASC_ALLOC_ZERO<void *>(m_HashTableSize);
+ return (m_HashTable != NULL) ? ERROR_SUCCESS : ERROR_NOT_ENOUGH_MEMORY;
}
void * FindObject(void * pvKey, PDWORD PtrIndex = NULL)
diff --git a/dep/CascLib/src/common/Path.h b/dep/CascLib/src/common/Path.h
new file mode 100644
index 00000000000..b77dde0cc3d
--- /dev/null
+++ b/dep/CascLib/src/common/Path.h
@@ -0,0 +1,182 @@
+/*****************************************************************************/
+/* Path.h Copyright (c) Ladislav Zezula 2019 */
+/*---------------------------------------------------------------------------*/
+/* Global path merger class */
+/*---------------------------------------------------------------------------*/
+/* Date Ver Who Comment */
+/* -------- ---- --- ------- */
+/* 24.07.17 1.00 Lad Created */
+/*****************************************************************************/
+
+#ifndef __CASC_PATH_H__
+#define __CASC_PATH_H__
+
+//-----------------------------------------------------------------------------
+// Structures
+
+template <typename xchar>
+struct CASC_PATH
+{
+ CASC_PATH(xchar chSeparator = PATH_SEP_CHAR)
+ {
+ m_szBufferBegin = m_szBufferPtr = m_Buffer;
+ m_szBufferEnd = m_szBufferBegin + _countof(m_Buffer);
+ m_chSeparator = chSeparator;
+ m_Buffer[0] = 0;
+ }
+
+ ~CASC_PATH()
+ {
+ if(m_szBufferBegin != m_Buffer)
+ {
+ CASC_FREE(m_szBufferBegin);
+ }
+ }
+
+ // LPCTSTR szPath = Path;
+ operator const xchar *()
+ {
+ return m_szBufferBegin;
+ }
+
+ // LPTSTR szPath = Path.New();
+ xchar * New()
+ {
+ xchar * szNewStr;
+
+ if((szNewStr = CASC_ALLOC<xchar>(Length() + 1)) != NULL)
+ {
+ memcpy(szNewStr, m_szBufferBegin, Length() * sizeof(xchar));
+ szNewStr[Length()] = 0;
+ }
+
+ return szNewStr;
+ }
+
+ size_t Save()
+ {
+ return (m_szBufferPtr - m_szBufferBegin);
+ }
+
+ bool Restore(size_t nSavePos)
+ {
+ if((m_szBufferBegin + nSavePos) < m_szBufferEnd)
+ {
+ m_szBufferPtr = m_szBufferBegin + nSavePos;
+ m_szBufferPtr[0] = 0;
+ return true;
+ }
+
+ return false;
+ }
+
+ // Path.Copy(szBuffer, _countof(szBuffer));
+ bool Copy(xchar * szBuffer, size_t cchBuffer)
+ {
+ if((Length() + 1) > cchBuffer)
+ return false;
+
+ memcpy(szBuffer, m_szBufferBegin, Length() * sizeof(xchar));
+ szBuffer[Length()] = 0;
+ return true;
+ }
+
+ size_t Length()
+ {
+ return m_szBufferPtr - m_szBufferBegin;
+ }
+
+ bool SetPathRoot(const xchar * szRoot)
+ {
+ // Make sure that there is no characters
+ m_szBufferPtr = m_szBufferBegin;
+ m_szBufferPtr[0] = 0;
+
+ // Append the root path
+ return AppendString(szRoot, false);
+ }
+
+ bool AppendStringN(const xchar * szString, size_t nMaxchars, bool bWithSeparator)
+ {
+ const xchar * szStringEnd = szString + nMaxchars;
+ xchar chOneChar;
+
+ if(szString && szString[0] && nMaxchars)
+ {
+ // Append separator, if required and not in begin of the string
+ if(m_szBufferPtr > m_szBufferBegin && bWithSeparator)
+ AppendChar(m_chSeparator);
+
+ // Append the characters from the string
+ while(szString[0] && szString < szStringEnd)
+ {
+ // Retrieve the single character
+ chOneChar = *szString++;
+
+ // Normalize the character
+ if(chOneChar == '/' || chOneChar == '\\')
+ chOneChar = m_chSeparator;
+
+ if(!AppendChar(chOneChar))
+ break;
+ }
+ }
+
+ return true;
+ }
+
+ bool AppendString(const xchar * szString, bool bWithSeparator)
+ {
+ return AppendStringN(szString, (0x10000 / sizeof(xchar)), bWithSeparator);
+ }
+
+ bool AppendEKey(LPBYTE pbEKey)
+ {
+ xchar szEKey[MD5_STRING_SIZE + 1];
+
+ StringFromBinary(pbEKey, MD5_HASH_SIZE, szEKey);
+ AppendStringN(szEKey, 2, true);
+ AppendStringN(szEKey+2, 2, true);
+ return AppendString(szEKey, true);
+ }
+
+ bool AppendChar(xchar chOneChar)
+ {
+ // Buffer our of space?
+ if((m_szBufferPtr + 2) >= m_szBufferEnd)
+ {
+ xchar * szOldBuffer = m_szBufferBegin;
+ xchar * szNewBuffer;
+ size_t nToAllocate = (m_szBufferEnd - m_szBufferBegin) * 2;
+ size_t nLength = (m_szBufferPtr - m_szBufferBegin);
+
+ if((szNewBuffer = CASC_ALLOC<xchar>(nToAllocate)) == NULL)
+ return false;
+
+ // Copy the chars
+ memcpy(szNewBuffer, m_szBufferBegin, (m_szBufferPtr - m_szBufferBegin) * sizeof(xchar));
+ m_szBufferBegin = szNewBuffer;
+ m_szBufferPtr = m_szBufferBegin + nLength;
+ m_szBufferEnd = m_szBufferBegin + nToAllocate;
+
+ // Free the old buffer
+ if(szOldBuffer != m_Buffer)
+ CASC_FREE(szOldBuffer);
+ }
+
+ // Append the character
+ *m_szBufferPtr++ = chOneChar;
+ m_szBufferPtr[0] = 0;
+ return true;
+ }
+
+ protected:
+
+ xchar * m_szBufferBegin;
+ xchar * m_szBufferPtr;
+ xchar * m_szBufferEnd;
+ xchar m_Buffer[MAX_PATH];
+ xchar m_chSeparator;
+};
+
+#endif // __CASC_PATH_H__
diff --git a/dep/CascLib/src/common/RootHandler.cpp b/dep/CascLib/src/common/RootHandler.cpp
index 89b693f55cb..b33f96209d9 100644
--- a/dep/CascLib/src/common/RootHandler.cpp
+++ b/dep/CascLib/src/common/RootHandler.cpp
@@ -81,10 +81,6 @@ PCASC_CKEY_ENTRY TFileTreeRoot::Search(TCascSearch * pSearch, PCASC_FIND_DATA pF
// Retrieve the extra values (FileDataId, file size and locale flags)
FileTree.GetExtras(pFileNode, &pFindData->dwFileDataId, &pFindData->dwLocaleFlags, &pFindData->dwContentFlags);
- // Supply the bCanOpenByDataId variable
- pFindData->bCanOpenByName = (pFileNode->FileNameHash != 0);
- pFindData->bCanOpenByDataId = (pFindData->dwFileDataId != CASC_INVALID_ID);
-
// Return the found CKey entry
return pFileNode->pCKeyEntry;
}