diff options
| author | Shauren <shauren.trinity@gmail.com> | 2019-08-10 19:01:24 +0200 |
|---|---|---|
| committer | Shauren <shauren.trinity@gmail.com> | 2019-08-10 19:01:24 +0200 |
| commit | cd720efbfa60f434f420ab66e220eca742c48e45 (patch) | |
| tree | 3c960ac5249d0711b71fbfdc62f6c0b665ed85ee /dep/CascLib/src/common | |
| parent | 0d6320dfd3932865edb69c8528327b767bd476ef (diff) | |
Dep/CascLib: Update to ladislav-zezula/CascLib@b91f87c770c78340dcd96df970e55b5c0469e884
Diffstat (limited to 'dep/CascLib/src/common')
| -rw-r--r-- | dep/CascLib/src/common/Array.h | 18 | ||||
| -rw-r--r-- | dep/CascLib/src/common/Common.cpp | 184 | ||||
| -rw-r--r-- | dep/CascLib/src/common/Common.h | 99 | ||||
| -rw-r--r-- | dep/CascLib/src/common/Csv.cpp | 18 | ||||
| -rw-r--r-- | dep/CascLib/src/common/Csv.h | 4 | ||||
| -rw-r--r-- | dep/CascLib/src/common/FileStream.cpp | 50 | ||||
| -rw-r--r-- | dep/CascLib/src/common/FileStream.h | 6 | ||||
| -rw-r--r-- | dep/CascLib/src/common/FileTree.cpp | 162 | ||||
| -rw-r--r-- | dep/CascLib/src/common/FileTree.h | 17 | ||||
| -rw-r--r-- | dep/CascLib/src/common/ListFile.cpp | 16 | ||||
| -rw-r--r-- | dep/CascLib/src/common/Map.h | 9 | ||||
| -rw-r--r-- | dep/CascLib/src/common/Path.h | 182 | ||||
| -rw-r--r-- | dep/CascLib/src/common/RootHandler.cpp | 4 |
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; } |
