mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-16 07:30:42 +01:00
Dep/CascLib: Update to ladislav-zezula/CascLib@ebd79e8fd4
This commit is contained in:
@@ -62,7 +62,7 @@ target_include_directories(casc
|
||||
PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/dep)
|
||||
|
||||
target_compile_definitions(casc PUBLIC -D__SYS_ZLIB -DCASCLIB_NO_AUTO_LINK_LIBRARY)
|
||||
target_compile_definitions(casc PUBLIC -D__SYS_ZLIB -DCASCLIB_NO_AUTO_LINK_LIBRARY -DCASCLIB_NODEBUG)
|
||||
|
||||
target_link_libraries(casc
|
||||
PRIVATE
|
||||
|
||||
@@ -21,6 +21,10 @@
|
||||
#include <zlib.h>
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG) && !defined(CASCLIB_NODEBUG)
|
||||
#define CASCLIB_DEBUG
|
||||
#endif
|
||||
|
||||
#include "CascPort.h"
|
||||
#include "common/Common.h"
|
||||
#include "common/Array.h"
|
||||
@@ -48,7 +52,7 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// CascLib private defines
|
||||
|
||||
#ifdef _DEBUG
|
||||
#if defined(CASCLIB_DEBUG) && defined(CASCLIB_DEV)
|
||||
#define BREAK_ON_XKEY3(CKey, v0, v1, v2) if(CKey[0] == v0 && CKey[1] == v1 && CKey[2] == v2) { __debugbreak(); }
|
||||
#define BREAKIF(condition) if(condition) { __debugbreak(); }
|
||||
#else
|
||||
@@ -60,7 +64,7 @@
|
||||
#define CASC_MAGIC_FILE 0x454C494643534143 // 'CASCFILE'
|
||||
#define CASC_MAGIC_FIND 0x444E494643534143 // 'CASCFIND'
|
||||
|
||||
// The maximum size of an inline file
|
||||
// The maximum size of an online file
|
||||
#define CASC_MAX_ONLINE_FILE_SIZE 0x40000000
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -456,7 +460,7 @@ DWORD GetFileSpanInfo(PCASC_CKEY_ENTRY pCKeyEntry, PULONGLONG PtrContentSize, PU
|
||||
DWORD FetchCascFile(TCascStorage * hs, CPATH_TYPE PathType, LPBYTE pbEKey, LPCTSTR szExtension, CASC_PATH<TCHAR> & LocalPath, PCASC_ARCHIVE_INFO pArchiveInfo = NULL);
|
||||
DWORD CheckCascBuildFileExact(CASC_BUILD_FILE & BuildFile, LPCTSTR szLocalPath);
|
||||
DWORD CheckCascBuildFileDirs(CASC_BUILD_FILE & BuildFile, LPCTSTR szLocalPath);
|
||||
DWORD CheckOnlineStorage(PCASC_OPEN_STORAGE_ARGS pArgs, CASC_BUILD_FILE & BuildFile, DWORD dwFeatures);
|
||||
DWORD CheckOnlineStorage(PCASC_OPEN_STORAGE_ARGS pArgs, CASC_BUILD_FILE & BuildFile, bool bOnlineStorage);
|
||||
DWORD CheckArchiveFilesDirectories(TCascStorage * hs);
|
||||
DWORD CheckDataFilesDirectory(TCascStorage * hs);
|
||||
DWORD LoadMainFile(TCascStorage * hs);
|
||||
@@ -506,7 +510,7 @@ DWORD RootHandler_CreateInstall(TCascStorage * hs, CASC_BLOB & InstallFile);
|
||||
//-----------------------------------------------------------------------------
|
||||
// Dumpers (CascDumpData.cpp)
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef CASCLIB_DEBUG
|
||||
void CascDumpData(LPCSTR szFileName, const void * pvData, size_t cbData);
|
||||
void CascDumpFile(HANDLE hFile, const char * szDumpFile = NULL);
|
||||
void CascDumpStorage(HANDLE hStorage, const char * szDumpFile = NULL);
|
||||
|
||||
@@ -51,8 +51,8 @@ static CASC_ENCRYPTION_KEY StaticCascKeys[] =
|
||||
// Battle.net app
|
||||
{ 0x2C547F26A2613E01ULL, { 0x37, 0xC5, 0x0C, 0x10, 0x2D, 0x4C, 0x9E, 0x3A, 0x5A, 0xC0, 0x69, 0xF0, 0x72, 0xB1, 0x41, 0x7D } }, // Battle.net App Alpha 1.5.0
|
||||
|
||||
// Starcraft
|
||||
// { 0xD0CAE11366CEEA83ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 1.12.3.2609 (build 45364)
|
||||
// StarCraft II
|
||||
{ 0xD0CAE11366CEEA83ULL, { 0x00, 0x41, 0x61, 0x07, 0x8E, 0x5A, 0x61, 0x20, 0x32, 0x1E, 0xA5, 0xFF, 0xE4, 0xDC, 0xD1, 0x26 } }, // Nova Covert Ops Expansion
|
||||
|
||||
// Warcraft III Reforged beta (build)
|
||||
{ 0x6E4296823E7D561EULL, { 0xC0, 0xBF, 0xA2, 0x94, 0x3A, 0xC3, 0xE9, 0x22, 0x86, 0xE4, 0x44, 0x3E, 0xE3, 0x56, 0x0D, 0x65 } }, // 1.32.0.13369 Base content (Beta Week 0)
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
#include "CascLib.h"
|
||||
#include "CascCommon.h"
|
||||
|
||||
#ifdef _DEBUG // The entire feature is only valid for debug purposes
|
||||
#ifdef CASCLIB_DEBUG // The entire feature is only valid for debug purposes
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Forward definitions
|
||||
@@ -78,7 +78,7 @@ static void DumpKey(FILE * fp, const char * szInFormat, LPBYTE pbData, size_t cb
|
||||
// If there will be more lines, then we clear the entire part until "%s"
|
||||
if(szFormatSpec != NULL)
|
||||
memset(szFormat, ' ', (szFormatSpec - szFormat));
|
||||
|
||||
|
||||
// Move pointers
|
||||
pbData += MD5_HASH_SIZE;
|
||||
}
|
||||
@@ -541,9 +541,9 @@ void CascDumpStorage(HANDLE hStorage, const char * szDumpFile)
|
||||
}
|
||||
}
|
||||
|
||||
#else // _DEBUG
|
||||
#else // CASCLIB_DEBUG
|
||||
|
||||
// so linker won't mind this .cpp file is empty in non-DEBUG builds
|
||||
void unused_symbol() { }
|
||||
|
||||
#endif // _DEBUG
|
||||
#endif // CASCLIB_DEBUG
|
||||
|
||||
@@ -1410,6 +1410,23 @@ static LPTSTR CheckForDirectory(LPCTSTR szParentFolder, LPCTSTR szSubFolder)
|
||||
return szLocalPath;
|
||||
}
|
||||
|
||||
static LPTSTR CheckForDirectories(LPCTSTR szParentFolder, ...)
|
||||
{
|
||||
LPCTSTR szSubDir;
|
||||
va_list argList;
|
||||
LPTSTR szFolder = NULL;
|
||||
|
||||
va_start(argList, szParentFolder);
|
||||
while((szSubDir = va_arg(argList, LPCTSTR)) != NULL)
|
||||
{
|
||||
if((szFolder = CheckForDirectory(szParentFolder, szSubDir)) != NULL)
|
||||
break;
|
||||
}
|
||||
va_end(argList);
|
||||
|
||||
return szFolder;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Public functions
|
||||
|
||||
@@ -1522,10 +1539,10 @@ DWORD CheckCascBuildFileDirs(CASC_BUILD_FILE & BuildFile, LPCTSTR szLocalPath)
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
DWORD CheckOnlineStorage(PCASC_OPEN_STORAGE_ARGS pArgs, CASC_BUILD_FILE & BuildFile, DWORD dwFeatures)
|
||||
DWORD CheckOnlineStorage(PCASC_OPEN_STORAGE_ARGS pArgs, CASC_BUILD_FILE & BuildFile, bool bOnlineStorage)
|
||||
{
|
||||
// If the online storage is required, we try to extract the product code
|
||||
if((dwFeatures & CASC_FEATURE_ONLINE) && (pArgs->szCodeName != NULL))
|
||||
if((bOnlineStorage) && (pArgs->szCodeName != NULL))
|
||||
{
|
||||
CASC_PATH<TCHAR> FilePath(pArgs->szLocalPath, _T("versions"), NULL);
|
||||
|
||||
@@ -1554,31 +1571,22 @@ DWORD CheckArchiveFilesDirectories(TCascStorage * hs)
|
||||
{
|
||||
if((szDataPath = CheckForDirectory(hs->szRootPath, DataDirs[i])) != NULL)
|
||||
{
|
||||
// If we found the data path, we also need to initialize the index path
|
||||
|
||||
// Check the config folder
|
||||
if((szConfigPath = CheckForDirectory(szDataPath, _T("config"))) != NULL)
|
||||
{
|
||||
// First, check for more common "data" subdirectory
|
||||
if((szIndexPath = CheckForDirectory(szDataPath, _T("data"))) == NULL)
|
||||
{
|
||||
// Second, try the "darch" subdirectory (older builds of HOTS - Alpha)
|
||||
szIndexPath = CheckForDirectory(szDataPath, _T("darch"));
|
||||
}
|
||||
|
||||
if(szIndexPath != NULL)
|
||||
// Second, try the "darch" subdirectory (older builds of HOTS - Alpha)
|
||||
if((szIndexPath = CheckForDirectories(szDataPath, _T("data"), _T("darch"), NULL)) != NULL)
|
||||
{
|
||||
hs->szDataPath = szDataPath;
|
||||
hs->szConfigPath = szConfigPath;
|
||||
hs->szIndexPath = szIndexPath;
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
CASC_FREE(szConfigPath);
|
||||
}
|
||||
CASC_FREE(szDataPath);
|
||||
}
|
||||
|
||||
CASC_FREE(szDataPath);
|
||||
CASC_FREE(szConfigPath);
|
||||
CASC_FREE(szIndexPath);
|
||||
}
|
||||
|
||||
// One of the paths was not found
|
||||
|
||||
@@ -38,7 +38,7 @@ static void SupplyFakeFileName(PCASC_FIND_DATA pFindData, PCASC_CKEY_ENTRY pCKey
|
||||
// If there is a file data ID, create fake file name
|
||||
if(pFindData->dwFileDataId != CASC_INVALID_ID)
|
||||
{
|
||||
CascStrPrintf(pFindData->szFileName, _countof(pFindData->szFileName), "FILE%08X.dat", pFindData->dwFileDataId);
|
||||
CascStrPrintf(pFindData->szFileName, _countof(pFindData->szFileName), CASC_FILEID_FORMAT, pFindData->dwFileDataId);
|
||||
pFindData->NameType = CascNameDataId;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ extern "C" {
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
// Version information
|
||||
#define CASCLIB_VERSION 0x0300 // CascLib version - integral (3.0)
|
||||
#define CASCLIB_VERSION_STRING "3.0" // CascLib version - string
|
||||
|
||||
@@ -110,11 +111,18 @@ extern "C" {
|
||||
#define CASC_LOCALE_PTPT 0x00010000
|
||||
|
||||
// Content flags on WoW
|
||||
#define CASC_CFLAG_INSTALL 0x04
|
||||
#define CASC_CFLAG_LOAD_ON_WINDOWS 0x08
|
||||
#define CASC_CFLAG_LOAD_ON_MAC 0x10
|
||||
#define CASC_CFLAG_X86_32 0x20
|
||||
#define CASC_CFLAG_X86_64 0x40
|
||||
#define CASC_CFLAG_LOW_VIOLENCE 0x80
|
||||
#define CASC_CFLAG_DONT_LOAD 0x100
|
||||
#define CASC_CFLAG_UPDATE_PLUGIN 0x800
|
||||
#define CASC_CFLAG_ARM64 0x8000
|
||||
#define CASC_CFLAG_ENCRYPTED 0x8000000
|
||||
#define CASC_CFLAG_NO_NAME_HASH 0x10000000
|
||||
#define CASC_CFLAG_UNCMN_RESOLUTION 0x20000000 // Uncommon resolution
|
||||
#define CASC_CFLAG_BUNDLE 0x40000000
|
||||
#define CASC_CFLAG_NO_COMPRESSION 0x80000000
|
||||
|
||||
@@ -153,6 +161,9 @@ extern "C" {
|
||||
// Maximum length of encryption key
|
||||
#define CASC_KEY_LENGTH 0x10
|
||||
|
||||
// Default format string for the file ID
|
||||
#define CASC_FILEID_FORMAT "FILE%08X.dat"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Structures
|
||||
|
||||
@@ -191,7 +202,7 @@ typedef enum _CASC_FILE_INFO_CLASS
|
||||
typedef enum _CASC_NAME_TYPE
|
||||
{
|
||||
CascNameFull, // Fully qualified file name
|
||||
CascNameDataId, // Name created from file data id (FILE%08X.dat)
|
||||
CascNameDataId, // Name created from file data id (CASC_FILEID_FORMAT)
|
||||
CascNameCKey, // Name created as string representation of CKey
|
||||
CascNameEKey // Name created as string representation of EKey
|
||||
} CASC_NAME_TYPE, *PCASC_NAME_TYPE;
|
||||
@@ -363,6 +374,7 @@ bool WINAPI CascCloseStorage(HANDLE hStorage);
|
||||
bool WINAPI CascOpenFile(HANDLE hStorage, const void * pvFileName, DWORD dwLocaleFlags, DWORD dwOpenFlags, HANDLE * PtrFileHandle);
|
||||
bool WINAPI CascOpenLocalFile(LPCTSTR szFileName, DWORD dwOpenFlags, HANDLE * PtrFileHandle);
|
||||
bool WINAPI CascGetFileInfo(HANDLE hFile, CASC_FILE_INFO_CLASS InfoClass, void * pvFileInfo, size_t cbFileInfo, size_t * pcbLengthNeeded);
|
||||
bool WINAPI CascSetFileFlags(HANDLE hFile, DWORD dwOpenFlags);
|
||||
bool WINAPI CascGetFileSize64(HANDLE hFile, PULONGLONG PtrFileSize);
|
||||
bool WINAPI CascSetFilePointer64(HANDLE hFile, LONGLONG DistanceToMove, PULONGLONG PtrNewPos, DWORD dwMoveMethod);
|
||||
bool WINAPI CascReadFile(HANDLE hFile, void * lpBuffer, DWORD dwToRead, PDWORD pdwRead);
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
#define CHECKED_KEY {0x00, 0x00, 0x0F, 0x84}
|
||||
|
||||
#if defined(_DEBUG) && defined(CHECKED_KEY)
|
||||
#if defined(CASCLIB_DEBUG) && defined(CHECKED_KEY)
|
||||
|
||||
inline bool CheckForXKey(LPBYTE XKey)
|
||||
{
|
||||
@@ -117,7 +117,7 @@ TCascStorage::~TCascStorage()
|
||||
// Free the blobs
|
||||
FreeCascBlob(&CdnConfigKey);
|
||||
FreeCascBlob(&CdnBuildKey);
|
||||
|
||||
|
||||
FreeCascBlob(&ArchiveGroup);
|
||||
FreeCascBlob(&ArchivesKey);
|
||||
FreeCascBlob(&PatchArchivesKey);
|
||||
@@ -423,8 +423,8 @@ static int LoadEncodingCKeyPage(TCascStorage * hs, CASC_ENCODING_HEADER & EnHead
|
||||
if(pFileEntry->EKeyCount == 0)
|
||||
break;
|
||||
|
||||
// Example of a file entry with multiple EKeys:
|
||||
// Overwatch build 24919, CKey: 0e 90 94 fa d2 cb 85 ac d0 7c ea 09 f9 c5 ba 00
|
||||
// Example of a file entry with multiple EKeys:
|
||||
// Overwatch build 24919, CKey: 0e 90 94 fa d2 cb 85 ac d0 7c ea 09 f9 c5 ba 00
|
||||
// BREAKIF(pFileEntry->EKeyCount > 1);
|
||||
// BREAK_ON_XKEY3(pFileEntry->CKey, 0x34, 0x82, 0x1f);
|
||||
|
||||
@@ -613,7 +613,7 @@ int CaptureDownloadTag(CASC_DOWNLOAD_HEADER & DlHeader, CASC_TAG_ENTRY1 & DlTag,
|
||||
pbFilePtr++;
|
||||
if(pbFilePtr >= pbFileEnd)
|
||||
return ERROR_BAD_FORMAT;
|
||||
|
||||
|
||||
// Save the length of the tag name
|
||||
DlTag.NameLength = (pbFilePtr - pbSaveFilePtr);
|
||||
pbFilePtr++;
|
||||
@@ -630,7 +630,7 @@ int CaptureDownloadTag(CASC_DOWNLOAD_HEADER & DlHeader, CASC_TAG_ENTRY1 & DlTag,
|
||||
// Get the bitmap length.
|
||||
// If the bitmap is last in the list and it's shorter than declared, we make it shorter
|
||||
DlTag.BitmapLength = GetTagBitmapLength(pbFilePtr, pbFileEnd, DlHeader.EntryCount);
|
||||
|
||||
|
||||
// Get the entry length
|
||||
DlTag.TagLength = (pbFilePtr - pbSaveFilePtr) + DlTag.BitmapLength;
|
||||
return ERROR_SUCCESS;
|
||||
@@ -769,7 +769,7 @@ static int LoadDownloadManifest(TCascStorage * hs)
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
{
|
||||
// Parse the entire download manifest
|
||||
dwErrCode = LoadDownloadManifest(hs, DlHeader, DownloadFile.pbData, DownloadFile.pbData + DownloadFile.cbData);
|
||||
dwErrCode = LoadDownloadManifest(hs, DlHeader, DownloadFile.pbData, DownloadFile.pbData + DownloadFile.cbData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1122,6 +1122,7 @@ static DWORD LoadCascStorage(TCascStorage * hs, PCASC_OPEN_STORAGE_ARGS pArgs, L
|
||||
// Merge features
|
||||
hs->dwFeatures |= (dwFeatures & (CASC_FEATURE_DATA_ARCHIVES | CASC_FEATURE_DATA_FILES | CASC_FEATURE_ONLINE));
|
||||
hs->dwFeatures |= (pArgs->dwFlags & CASC_FEATURE_FORCE_DOWNLOAD);
|
||||
hs->dwFeatures |= (BuildFileType == CascVersions) ? CASC_FEATURE_ONLINE : 0;
|
||||
hs->BuildFileType = BuildFileType;
|
||||
|
||||
// Copy the name of the build file
|
||||
@@ -1390,24 +1391,23 @@ bool WINAPI CascOpenStorageEx(LPCTSTR szParams, PCASC_OPEN_STORAGE_ARGS pArgs, b
|
||||
if((hs = new TCascStorage()) != NULL)
|
||||
{
|
||||
CASC_BUILD_FILE BuildFile = {NULL};
|
||||
DWORD dwFeatures = bOnlineStorage ? CASC_FEATURE_ONLINE : 0;
|
||||
|
||||
|
||||
// Check for one of the supported main files (.build.info, .build.db, versions)
|
||||
if((dwErrCode = CheckCascBuildFileExact(BuildFile, pArgs->szLocalPath)) == ERROR_SUCCESS)
|
||||
{
|
||||
dwErrCode = LoadCascStorage(hs, pArgs, BuildFile.szFullPath, BuildFile.BuildFileType, dwFeatures | CASC_FEATURE_DATA_ARCHIVES | CASC_FEATURE_DATA_FILES);
|
||||
dwErrCode = LoadCascStorage(hs, pArgs, BuildFile.szFullPath, BuildFile.BuildFileType, CASC_FEATURE_DATA_ARCHIVES | CASC_FEATURE_DATA_FILES);
|
||||
}
|
||||
|
||||
// Search the folder and upper folders for the build file
|
||||
else if((dwErrCode = CheckCascBuildFileDirs(BuildFile, pArgs->szLocalPath)) == ERROR_SUCCESS)
|
||||
{
|
||||
dwErrCode = LoadCascStorage(hs, pArgs, BuildFile.szFullPath, BuildFile.BuildFileType, dwFeatures | CASC_FEATURE_DATA_ARCHIVES | CASC_FEATURE_DATA_FILES);
|
||||
dwErrCode = LoadCascStorage(hs, pArgs, BuildFile.szFullPath, BuildFile.BuildFileType, CASC_FEATURE_DATA_ARCHIVES | CASC_FEATURE_DATA_FILES);
|
||||
}
|
||||
|
||||
// If the caller requested an online storage, we must have the code name
|
||||
else if((dwErrCode = CheckOnlineStorage(pArgs, BuildFile, dwFeatures)) == ERROR_SUCCESS)
|
||||
else if((dwErrCode = CheckOnlineStorage(pArgs, BuildFile, bOnlineStorage)) == ERROR_SUCCESS)
|
||||
{
|
||||
dwErrCode = LoadCascStorage(hs, pArgs, BuildFile.szFullPath, BuildFile.BuildFileType, dwFeatures | CASC_FEATURE_DATA_FILES);
|
||||
dwErrCode = LoadCascStorage(hs, pArgs, BuildFile.szFullPath, BuildFile.BuildFileType, CASC_FEATURE_DATA_FILES);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1426,7 +1426,7 @@ bool WINAPI CascOpenStorageEx(LPCTSTR szParams, PCASC_OPEN_STORAGE_ARGS pArgs, b
|
||||
}
|
||||
|
||||
//
|
||||
// Opens a local CASC storage
|
||||
// Opens a local CASC storage
|
||||
//
|
||||
// szParams: "local_path:code_name", like "C:\\Games\\World of Warcraft:wowt"
|
||||
//
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
#define __CASCPORT_H__
|
||||
|
||||
#ifndef __cplusplus
|
||||
#include <stdbool.h>
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -30,6 +30,7 @@
|
||||
#define _CRT_SECURE_NO_DEPRECATE
|
||||
#define _CRT_NON_CONFORMING_SWPRINTFS
|
||||
|
||||
// Prevent duplicate symbols defined by Windows headers
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#endif
|
||||
@@ -46,7 +47,6 @@
|
||||
#include <direct.h>
|
||||
#include <malloc.h>
|
||||
#include <windows.h>
|
||||
#include <ws2tcpip.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#define CASCLIB_PLATFORM_LITTLE_ENDIAN
|
||||
|
||||
@@ -116,7 +116,7 @@ static DWORD OpenDataStream(TCascFile * hf, PCASC_FILE_SPAN pFileSpan, PCASC_CKE
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef CASCLIB_DEBUG
|
||||
static unsigned int table_16C57A8[0x10] =
|
||||
{
|
||||
0x049396B8, 0x72A82A9B, 0xEE626CCA, 0x9917754F,
|
||||
@@ -182,7 +182,7 @@ static DWORD ParseBlteHeader(PCASC_FILE_SPAN pFileSpan, PCASC_CKEY_ENTRY pCKeyEn
|
||||
if(pEncodedHeader->EncodedSize != pCKeyEntry->EncodedSize)
|
||||
return ERROR_BAD_FORMAT;
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef CASCLIB_DEBUG
|
||||
// Not really needed, it's here just for explanation of what the values mean
|
||||
//assert(memcmp(pCKeyEntry->EKey, pEncodedHeader->EKey.Value, MD5_HASH_SIZE) == 0);
|
||||
VerifyHeaderSpan(pEncodedHeader, HeaderOffset);
|
||||
@@ -203,7 +203,7 @@ static DWORD ParseBlteHeader(PCASC_FILE_SPAN pFileSpan, PCASC_CKEY_ENTRY pCKeyEn
|
||||
{
|
||||
if(pBlteHeader->MustBe0F != 0x0F)
|
||||
return ERROR_BAD_FORMAT;
|
||||
|
||||
|
||||
// Verify the header size
|
||||
FrameCount = ConvertBytesToInteger_3(pBlteHeader->FrameCount);
|
||||
ExpectedHeaderSize = 0x0C + FrameCount * sizeof(BLTE_FRAME);
|
||||
@@ -587,7 +587,7 @@ static DWORD DecodeFileFrame(
|
||||
switch(pbEncoded[0])
|
||||
{
|
||||
case 'E': // Encrypted files
|
||||
|
||||
|
||||
// The work buffer should not have been allocated by any step
|
||||
assert(pbWorkBuffer == NULL && cbWorkBuffer == 0);
|
||||
|
||||
@@ -613,7 +613,7 @@ static DWORD DecodeFileFrame(
|
||||
break;
|
||||
|
||||
case 'Z': // ZLIB compressed files
|
||||
|
||||
|
||||
// If we decompressed less than expected, we simply fill the rest with zeros
|
||||
// Example: INSTALL file from the TACT CASC storage
|
||||
cbDecodedExpected = cbDecoded;
|
||||
@@ -784,7 +784,7 @@ static DWORD ReadFile_WholeFile(TCascFile * hf, LPBYTE pbBuffer)
|
||||
ULONGLONG ByteOffset = pFileSpan->ArchiveOffs + pFileSpan->HeaderSize;
|
||||
DWORD EncodedSize = pCKeyEntry->EncodedSize - pFileSpan->HeaderSize;
|
||||
|
||||
// Allocate the buffer for the entire encoded span
|
||||
// Allocate the buffer for the entire encoded span
|
||||
pbEncodedPtr = pbEncoded = CASC_ALLOC<BYTE>(EncodedSize);
|
||||
if(pbEncoded == NULL)
|
||||
{
|
||||
@@ -1020,6 +1020,29 @@ bool WINAPI CascGetFileInfo(HANDLE hFile, CASC_FILE_INFO_CLASS InfoClass, void *
|
||||
return (pbOutputValue != NULL);
|
||||
}
|
||||
|
||||
bool WINAPI CascSetFileFlags(HANDLE hFile, DWORD dwOpenFlags)
|
||||
{
|
||||
TCascFile * hf;
|
||||
|
||||
// Validate the file handle
|
||||
if((hf = TCascFile::IsValid(hFile)) == NULL)
|
||||
{
|
||||
SetCascError(ERROR_INVALID_HANDLE);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Currently, only CASC_OVERCOME_ENCRYPTED can be changed
|
||||
if(dwOpenFlags & ~CASC_OVERCOME_ENCRYPTED)
|
||||
{
|
||||
SetCascError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set "overcome encrypted" flag. Will apply on next CascReadFile
|
||||
hf->bOvercomeEncrypted = (dwOpenFlags & CASC_OVERCOME_ENCRYPTED) != 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
//
|
||||
// THE FILE SIZE PROBLEM
|
||||
//
|
||||
@@ -1031,7 +1054,7 @@ bool WINAPI CascGetFileInfo(HANDLE hFile, CASC_FILE_INFO_CLASS InfoClass, void *
|
||||
// HotS(29049) ENCODING 0x0024BA45 - 0x0024b98a 0x0024BA45 n/a 0x0024BA45 n/a
|
||||
// HotS(29049) ROOT 0x00193340 - 0x00193340 0x0010db65 0x00193340 0x0010db65 n/a
|
||||
// HotS(29049) (other) 0x00001080 - 0x00001080 0x000008eb 0x00001080 0x000008eb 0x00001080
|
||||
//
|
||||
//
|
||||
// WoW(18888) ENCODING 0x030d487b - 0x030dee79 0x030d487b n/a 0x030d487b n/a
|
||||
// WoW(18888) ROOT 0x016a9800 - n/a 0x0131313d 0x016a9800 0x0131313d n/a
|
||||
// WoW(18888) (other) 0x000007d0 - 0x000007d0 0x00000397 0x000007d0 0x00000397 n/a
|
||||
@@ -1042,6 +1065,13 @@ bool WINAPI CascGetFileSize64(HANDLE hFile, PULONGLONG PtrFileSize)
|
||||
TCascFile * hf;
|
||||
DWORD dwErrCode;
|
||||
|
||||
// Validate the file pointer
|
||||
if(PtrFileSize == NULL)
|
||||
{
|
||||
SetCascError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate the file handle
|
||||
if((hf = TCascFile::IsValid(hFile)) == NULL)
|
||||
{
|
||||
@@ -1049,11 +1079,11 @@ bool WINAPI CascGetFileSize64(HANDLE hFile, PULONGLONG PtrFileSize)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Validate the file pointer
|
||||
if(PtrFileSize == NULL)
|
||||
// If the content key is zeros, we treat the file as a file with size of 0
|
||||
if(hf->ContentSize == 0)
|
||||
{
|
||||
SetCascError(ERROR_INVALID_PARAMETER);
|
||||
return false;
|
||||
PtrFileSize[0] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// ENCODING on older storages: Content size is not present in the BUILD file
|
||||
@@ -1157,7 +1187,7 @@ DWORD WINAPI CascSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * PtrFilePosHi
|
||||
{
|
||||
ULONGLONG NewPos = 0;
|
||||
LONGLONG DistanceToMove;
|
||||
|
||||
|
||||
// Assemble the 64-bit distance to move
|
||||
DistanceToMove = (PtrFilePosHigh != NULL) ? MAKE_OFFSET64(PtrFilePosHigh[0], lFilePos) : (LONGLONG)(LONG)lFilePos;
|
||||
|
||||
@@ -1196,6 +1226,13 @@ bool WINAPI CascReadFile(HANDLE hFile, void * pvBuffer, DWORD dwBytesToRead, PDW
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check files with zero size
|
||||
if(hf->ContentSize == 0)
|
||||
{
|
||||
PtrBytesRead[0] = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
// If we don't have file frames loaded, we need to do it now.
|
||||
// Need to do it before file range check, as the file size may be unknown at this point
|
||||
dwErrCode = EnsureFileSpanFramesLoaded(hf);
|
||||
@@ -1242,7 +1279,7 @@ bool WINAPI CascReadFile(HANDLE hFile, void * pvBuffer, DWORD dwBytesToRead, PDW
|
||||
{
|
||||
// No caching at all. The entire file will be read directly to the user buffer
|
||||
// Used for loading internal files, where we need to read the whole file
|
||||
case CascCacheNothing:
|
||||
case CascCacheNothing:
|
||||
dwBytesRead2 = ReadFile_NonCached(hf, pbBuffer, StartOffset, EndOffset);
|
||||
break;
|
||||
|
||||
@@ -1268,7 +1305,7 @@ bool WINAPI CascReadFile(HANDLE hFile, void * pvBuffer, DWORD dwBytesToRead, PDW
|
||||
if(PtrBytesRead != NULL)
|
||||
PtrBytesRead[0] = 0;
|
||||
hf->FilePointer = SaveFilePointer;
|
||||
|
||||
|
||||
// If 0 bytes were requested, it's actually a success
|
||||
return (dwBytesToRead == 0);
|
||||
}
|
||||
|
||||
@@ -660,7 +660,7 @@ class TBitEntryArray : public TGenericArray<DWORD>
|
||||
#define INDEX_TO_GROUP(val) (val >> 9)
|
||||
#define GROUP_TO_INDEX(grp) (grp << 9)
|
||||
|
||||
// For each 0x200-th bit, this contains information about amount of "1" bits
|
||||
// For each 0x200-th bit, this contains information about amount of "1" bits
|
||||
typedef struct _BASEVALS
|
||||
{
|
||||
DWORD BaseValue200; // Item value of every 0x200-th item
|
||||
@@ -791,7 +791,7 @@ class TSparseArray
|
||||
if(index & 0x20)
|
||||
IntValue += GetNumberOfSetBits32(ItemBits[(index >> 0x05) - 1]);
|
||||
|
||||
// 4) Count the bits in the current DWORD (masked by bit index mask)
|
||||
// 4) Count the bits in the current DWORD (masked by bit index mask)
|
||||
BitMask = (1 << (index & 0x1F)) - 1;
|
||||
return IntValue + GetNumberOfSetBits32(ItemBits[index >> 0x05] & BitMask);
|
||||
}
|
||||
@@ -888,7 +888,7 @@ class TSparseArray
|
||||
DWORD bitGroup;
|
||||
DWORD edx = index;
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef CASCLIB_DEBUG
|
||||
//if(TotalItemCount > 0x200)
|
||||
//{
|
||||
// FILE * fp = fopen("e:\\Ladik\\Appdir\\CascLib\\doc\\mndx-sparse-array.txt", "wt");
|
||||
@@ -1177,7 +1177,7 @@ class TSparseArray
|
||||
return table_1BA1818[bitGroup + distFromBase] + itemIndex;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef CASCLIB_DEBUG
|
||||
void Dump(FILE * fp)
|
||||
{
|
||||
size_t * ArrayNormal;
|
||||
@@ -1868,7 +1868,7 @@ class TFileNameDatabase
|
||||
// Get the hasn table item
|
||||
pHashEntry = &HashTable[TableIndex & HashTableMask];
|
||||
|
||||
//
|
||||
//
|
||||
if(TableIndex == pHashEntry->NextIndex)
|
||||
{
|
||||
// HOTS: 01957BB4
|
||||
@@ -2467,7 +2467,7 @@ class TFileNameDatabase
|
||||
|
||||
TSparseArray CollisionTable; // Table of valid collisions, indexed by NodeIndex
|
||||
TSparseArray FileNameIndexes; // Array of file name indexes
|
||||
TSparseArray CollisionHiBitsIndexes; // Table of indexes of high bits (above 8 bits) for collisions
|
||||
TSparseArray CollisionHiBitsIndexes; // Table of indexes of high bits (above 8 bits) for collisions
|
||||
|
||||
// This pair of arrays serves for fast conversion from node index to FragmentOffset / FragmentChar
|
||||
TGenericArray<BYTE> LoBitsTable; // Array of lower 8 bits of name fragment offset
|
||||
|
||||
@@ -105,8 +105,8 @@ struct TVFS_DIRECTORY_HEADER
|
||||
// In-memory layout of the path table entry
|
||||
typedef struct _TVFS_PATH_TABLE_ENTRY
|
||||
{
|
||||
LPBYTE pbNamePtr; // Pointer to the begin of the node name
|
||||
LPBYTE pbNameEnd; // Pointer to the end of the file name
|
||||
char * m_pNamePtr; // Pointer to the begin of the node name
|
||||
char * m_pNameEnd; // Pointer to the end of the file name
|
||||
DWORD NodeFlags; // TVFS_PTE_XXX
|
||||
DWORD NodeValue; // Node value
|
||||
} TVFS_PATH_TABLE_ENTRY, *PTVFS_PATH_TABLE_ENTRY;
|
||||
@@ -156,8 +156,8 @@ struct TRootHandler_TVFS : public TFileTreeRoot
|
||||
PathBuffer.AppendChar('/');
|
||||
|
||||
// Append the name fragment, if any
|
||||
if(PathEntry.pbNameEnd > PathEntry.pbNamePtr)
|
||||
PathBuffer.AppendStringN((const char *)PathEntry.pbNamePtr, (PathEntry.pbNameEnd - PathEntry.pbNamePtr), false);
|
||||
if(PathEntry.m_pNameEnd > PathEntry.m_pNamePtr)
|
||||
PathBuffer.AppendStringN(PathEntry.m_pNamePtr, (PathEntry.m_pNameEnd - PathEntry.m_pNamePtr), false);
|
||||
|
||||
// Append the postfix separator, if needed
|
||||
if(PathEntry.NodeFlags & TVFS_PTE_PATH_SEPARATOR_POST)
|
||||
@@ -312,8 +312,8 @@ struct TRootHandler_TVFS : public TFileTreeRoot
|
||||
LPBYTE CapturePathEntry(TVFS_PATH_TABLE_ENTRY & PathEntry, LPBYTE pbPathTablePtr, LPBYTE pbPathTableEnd)
|
||||
{
|
||||
// Reset the path entry structure
|
||||
PathEntry.pbNamePtr = pbPathTablePtr;
|
||||
PathEntry.pbNameEnd = pbPathTablePtr;
|
||||
PathEntry.m_pNamePtr = (char *)(pbPathTablePtr);
|
||||
PathEntry.m_pNameEnd = (char *)(pbPathTablePtr);
|
||||
PathEntry.NodeFlags = 0;
|
||||
PathEntry.NodeValue = 0;
|
||||
|
||||
@@ -332,8 +332,8 @@ struct TRootHandler_TVFS : public TFileTreeRoot
|
||||
|
||||
if((pbPathTablePtr + nLength) > pbPathTableEnd)
|
||||
return NULL;
|
||||
PathEntry.pbNamePtr = pbPathTablePtr;
|
||||
PathEntry.pbNameEnd = pbPathTablePtr + nLength;
|
||||
PathEntry.m_pNamePtr = (char *)(pbPathTablePtr);
|
||||
PathEntry.m_pNameEnd = (char *)(pbPathTablePtr + nLength);
|
||||
pbPathTablePtr += nLength;
|
||||
}
|
||||
|
||||
@@ -536,6 +536,11 @@ struct TRootHandler_TVFS : public TFileTreeRoot
|
||||
}
|
||||
}
|
||||
|
||||
//BREAKIF(strcmp((const char *)PathBuffer, "Base") == 0);
|
||||
//BREAKIF(strcmp((const char *)PathBuffer, "base") == 0);
|
||||
//BREAKIF(strcmp((const char *)PathBuffer, "base:ComplexTypeDescriptorSizes.dat") == 0);
|
||||
//BREAKIF(strcmp((const char *)PathBuffer, "DivideAndConquer.w3m:war3map.doo") == 0);
|
||||
|
||||
// We need to check whether this is another TVFS directory file
|
||||
if(IsVfsSubDirectory(hs, DirHeader, SubHeader, SpanEntry.EKey, SpanEntry.ContentSize) == ERROR_SUCCESS)
|
||||
{
|
||||
|
||||
@@ -78,6 +78,31 @@ typedef struct _FILE_ROOT_GROUP
|
||||
|
||||
} FILE_ROOT_GROUP, *PFILE_ROOT_GROUP;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Debug local stuff
|
||||
|
||||
#if defined(_MSC_VER) && defined(CASCLIB_DEBUG)
|
||||
static FILE * fp = NULL;
|
||||
static bool bLogEntries = true;
|
||||
|
||||
static void LogEntry(DWORD FileDataId, PCONTENT_KEY pCKey)
|
||||
{
|
||||
if(fp && bLogEntries)
|
||||
{
|
||||
char szCKey[MD5_STRING_SIZE + 1];
|
||||
|
||||
if(FileDataId == 1260179)
|
||||
{
|
||||
bLogEntries = false;
|
||||
__debugbreak();
|
||||
}
|
||||
|
||||
StringFromBinary(pCKey->Value, MD5_HASH_SIZE, szCKey);
|
||||
fprintf(fp, "File Data ID: %u, CKey = %s\n", FileDataId, szCKey);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// TRootHandler_WoW interface / implementation
|
||||
|
||||
@@ -89,7 +114,7 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
|
||||
TRootHandler_WoW(ROOT_FORMAT RFormat, DWORD HashlessFileCount) : TFileTreeRoot(FTREE_FLAGS_WOW)
|
||||
{
|
||||
// Turn off the "we know file names" bit
|
||||
// Turn off the "we know file names" bit
|
||||
FileCounterHashless = HashlessFileCount;
|
||||
FileCounter = 0;
|
||||
RootFormat = RFormat;
|
||||
@@ -155,7 +180,7 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
return pbRootPtr + (sizeof(FILE_ROOT_ENTRY) * RootGroup.Header.NumberOfFiles);
|
||||
|
||||
case RootFormatWoW82:
|
||||
|
||||
|
||||
// Verify the position of array of CONTENT_KEY
|
||||
if((pbRootPtr + (sizeof(CONTENT_KEY) * RootGroup.Header.NumberOfFiles)) > pbRootEnd)
|
||||
return NULL;
|
||||
@@ -229,7 +254,6 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
{
|
||||
// Set the file data ID
|
||||
FileDataId = FileDataId + RootGroup.FileDataIds[i];
|
||||
//printf("File Data ID: %u\n", FileDataId);
|
||||
|
||||
// Find the item in the central storage. Insert it to the tree
|
||||
if((pCKeyEntry = FindCKeyEntry_CKey(hs, pCKey->Value)) != NULL)
|
||||
@@ -357,7 +381,7 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
*/
|
||||
|
||||
DWORD ParseWowRootFile_Level1(
|
||||
TCascStorage * hs,
|
||||
TCascStorage * hs,
|
||||
LPBYTE pbRootPtr,
|
||||
LPBYTE pbRootEnd,
|
||||
DWORD dwLocaleMask,
|
||||
@@ -389,7 +413,7 @@ struct TRootHandler_WoW : public TFileTreeRoot
|
||||
if(dwErrCode == ERROR_SUCCESS)
|
||||
dwErrCode = ParseWowRootFile_Level1(hs, pbRootPtr, pbRootEnd, dwLocaleMask, 1);
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef CASCLIB_DEBUG
|
||||
// Dump the array of the file data IDs
|
||||
//FileTree.DumpFileDataIds("e:\\file-data-ids.bin");
|
||||
#endif
|
||||
@@ -494,6 +518,8 @@ DWORD RootHandler_CreateWoW(TCascStorage * hs, CASC_BLOB & RootFile, DWORD dwLoc
|
||||
pRootHandler = new TRootHandler_WoW(RootFormat, FileCounterHashless);
|
||||
if(pRootHandler != NULL)
|
||||
{
|
||||
//fp = fopen("E:\\file-data-ids2.txt", "wt");
|
||||
|
||||
// Load the root directory. If load failed, we free the object
|
||||
dwErrCode = pRootHandler->Load(hs, pbRootFile, pbRootEnd, dwLocaleMask);
|
||||
if(dwErrCode != ERROR_SUCCESS)
|
||||
@@ -501,6 +527,8 @@ DWORD RootHandler_CreateWoW(TCascStorage * hs, CASC_BLOB & RootFile, DWORD dwLoc
|
||||
delete pRootHandler;
|
||||
pRootHandler = NULL;
|
||||
}
|
||||
|
||||
//fclose(fp);
|
||||
}
|
||||
|
||||
// Assign the root directory (or NULL) and return error
|
||||
|
||||
@@ -17,6 +17,7 @@ EXPORTS
|
||||
CascOpenFile
|
||||
CascOpenLocalFile
|
||||
CascGetFileInfo
|
||||
CascSetFileFlags
|
||||
CascGetFileSize
|
||||
CascGetFileSize64
|
||||
CascSetFilePointer
|
||||
|
||||
@@ -104,7 +104,7 @@ class CASC_ARRAY
|
||||
// Make sure we have array large enough
|
||||
if(!EnlargeArray(ItemIndex + 1, true))
|
||||
return NULL;
|
||||
|
||||
|
||||
// Get the items range
|
||||
pbLastItem = m_pItemArray + (m_ItemCount * m_ItemSize);
|
||||
pbNewItem = m_pItemArray + (ItemIndex * m_ItemSize);
|
||||
@@ -170,7 +170,7 @@ class CASC_ARRAY
|
||||
m_ItemCountMax = m_ItemCount = m_ItemSize = 0;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef CASCLIB_DEBUG
|
||||
size_t BytesAllocated()
|
||||
{
|
||||
return m_ItemCountMax * m_ItemSize;
|
||||
|
||||
@@ -229,7 +229,7 @@ class CASC_SPARSE_ARRAY
|
||||
return (m_pLevel0 != NULL);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef CASCLIB_DEBUG
|
||||
size_t BytesAllocated()
|
||||
{
|
||||
return m_LevelsAllocated * sizeof(CASC_ARRAY_256);
|
||||
|
||||
@@ -13,7 +13,22 @@
|
||||
#include "../CascCommon.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local defines
|
||||
// Local arrays
|
||||
|
||||
static BYTE PathSeparators[256] =
|
||||
{
|
||||
/* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x10 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x20 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
/* 0x30 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x40 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x50 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00
|
||||
|
||||
// Filled by zeros up to 256 bytes
|
||||
};
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local functions
|
||||
|
||||
#define START_ITEM_COUNT 0x4000
|
||||
|
||||
@@ -31,6 +46,28 @@ inline void SET_NODE_INT32(void * node, size_t offset, DWORD value)
|
||||
PtrValue[0] = value;
|
||||
}
|
||||
|
||||
#ifdef CASCLIB_DEV
|
||||
//static DWORD dwFileCount = 0;
|
||||
//
|
||||
//static void WatchFileNode(PCASC_FILE_NODE pFileNode, const char * szFileName, bool bNewNodeInserted)
|
||||
//{
|
||||
// const char * szSuffix = bNewNodeInserted ? "NEW" : "EXISTING";
|
||||
// const char * szFormat = "FileNode %p: CKey: %s, NameHash: %I64x (\"%s\") - %s\n";
|
||||
// char szBuffer[MD5_STRING_SIZE + 1];
|
||||
//
|
||||
// // Selected nodes only
|
||||
// if(dwFileCount < 10 && !_strnicmp(szFileName, "base", 4))
|
||||
// {
|
||||
// printf(szFormat, pFileNode,
|
||||
// StringFromBinary(pFileNode->pCKeyEntry->CKey, MD5_HASH_SIZE, szBuffer),
|
||||
// pFileNode->FileNameHash,
|
||||
// szFileName,
|
||||
// szSuffix);
|
||||
// dwFileCount++;
|
||||
// }
|
||||
//}
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Protected functions
|
||||
|
||||
@@ -91,7 +128,7 @@ PCASC_FILE_NODE CASC_FILE_TREE::InsertNew()
|
||||
}
|
||||
|
||||
// Insert the node to the map of FileNameHash -> CASC_FILE_NODE
|
||||
bool CASC_FILE_TREE::InsertToHashTable(PCASC_FILE_NODE pFileNode)
|
||||
bool CASC_FILE_TREE::InsertToNameMap(PCASC_FILE_NODE pFileNode)
|
||||
{
|
||||
bool bResult = false;
|
||||
|
||||
@@ -189,7 +226,7 @@ bool CASC_FILE_TREE::RebuildNameMaps()
|
||||
{
|
||||
// Insert it to the map "FileNameHash -> CASC_FILE_NODE"
|
||||
if(pFileNode->FileNameHash != 0)
|
||||
InsertToHashTable(pFileNode);
|
||||
InsertToNameMap(pFileNode);
|
||||
|
||||
// Insert it to the array "FileDataId -> CASC_FILE_NODE"
|
||||
if(FileDataIds.IsInitialized())
|
||||
@@ -288,13 +325,12 @@ PCASC_FILE_NODE CASC_FILE_TREE::InsertByName(PCASC_CKEY_ENTRY pCKeyEntry, const
|
||||
{
|
||||
PCASC_FILE_NODE pFileNode;
|
||||
ULONGLONG FileNameHash;
|
||||
//bool bNewNodeInserted = false;
|
||||
|
||||
// Sanity checks
|
||||
assert(szFileName != NULL && szFileName[0] != 0);
|
||||
assert(pCKeyEntry != NULL);
|
||||
|
||||
//BREAK_ON_XKEY3(pCKeyEntry->EKey, 0x00, 0x00, 0x0F);
|
||||
|
||||
// Calculate the file name hash
|
||||
FileNameHash = CalcFileNameHash(szFileName);
|
||||
|
||||
@@ -313,7 +349,7 @@ PCASC_FILE_NODE CASC_FILE_TREE::InsertByName(PCASC_CKEY_ENTRY pCKeyEntry, const
|
||||
SetExtras(pFileNode, FileDataId, LocaleFlags, ContentFlags);
|
||||
|
||||
// Insert the file node to the hash map
|
||||
InsertToHashTable(pFileNode);
|
||||
InsertToNameMap(pFileNode);
|
||||
|
||||
// Also make sure that it's in the file data id table, if the table is initialized
|
||||
InsertToIdTable(pFileNode);
|
||||
@@ -323,11 +359,16 @@ PCASC_FILE_NODE CASC_FILE_TREE::InsertByName(PCASC_CKEY_ENTRY pCKeyEntry, const
|
||||
|
||||
// If we created a new node, we need to increment the reference count
|
||||
assert(pCKeyEntry->RefCount != 0xFFFF);
|
||||
//bNewNodeInserted = true;
|
||||
pCKeyEntry->RefCount++;
|
||||
FileNodes++;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CASCLIB_DEV
|
||||
//WatchFileNode(pFileNode, szFileName, bNewNodeInserted);
|
||||
#endif
|
||||
|
||||
return pFileNode;
|
||||
}
|
||||
|
||||
@@ -349,7 +390,7 @@ PCASC_FILE_NODE CASC_FILE_TREE::InsertByHash(PCASC_CKEY_ENTRY pCKeyEntry, ULONGL
|
||||
pFileNode->FileNameHash = FileNameHash;
|
||||
|
||||
// Insert the file node to the hash map
|
||||
InsertToHashTable(pFileNode);
|
||||
InsertToNameMap(pFileNode);
|
||||
}
|
||||
|
||||
return pFileNode;
|
||||
@@ -543,13 +584,21 @@ bool CASC_FILE_TREE::SetNodeFileName(PCASC_FILE_NODE pFileNode, const char * szF
|
||||
{
|
||||
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 == ':')
|
||||
// Is there a path separator, such as '\\' or '/'?
|
||||
// Also support TVFS "mount points", like "DivideAndConquer.w3m:war3map.doo"
|
||||
if(PathSeparators[chOneChar])
|
||||
{
|
||||
size_t nHashLength = i;
|
||||
|
||||
// If there is a reparse point mark (':'), we need to include it as part of the name
|
||||
if(PathSeparators[chOneChar] == 0x02)
|
||||
{
|
||||
PathBuffer.AppendChar(chOneChar);
|
||||
nHashLength++;
|
||||
}
|
||||
|
||||
// Calculate hash of the file name up to the end of the node name
|
||||
FileNameHash = CalcNormNameHash(PathBuffer, i);
|
||||
FileNameHash = CalcNormNameHash(PathBuffer, nHashLength);
|
||||
|
||||
// If the entry is not there yet, create new one
|
||||
if((pFolderNode = Find(FileNameHash)) == NULL)
|
||||
@@ -559,17 +608,36 @@ bool CASC_FILE_TREE::SetNodeFileName(PCASC_FILE_NODE pFileNode, const char * szF
|
||||
if(pFolderNode == NULL)
|
||||
return false;
|
||||
|
||||
// Populate the file entry
|
||||
// Fill-in flags, name hash and parent
|
||||
pFolderNode->Flags |= (chOneChar == ':') ? (CFN_FLAG_FOLDER | CFN_FLAG_MOUNT_POINT) : CFN_FLAG_FOLDER;
|
||||
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);
|
||||
InsertToNameMap(pFolderNode);
|
||||
}
|
||||
|
||||
// In case we're in the middle a mount point construction (called by CASC_FILE_TREE::InsertByName()),
|
||||
// then we can get into situation where the call to Find() found the newly constructed item.
|
||||
// In that case, we just set the name and bail out
|
||||
else if(pFolderNode == pFileNode)
|
||||
{
|
||||
// The item must be a mount point, with name hash already set.
|
||||
assert(pFolderNode->FileNameHash == FileNameHash);
|
||||
assert(szFileName[i + 1] == 0);
|
||||
|
||||
// Fill-in the flags and parent
|
||||
pFolderNode->Flags |= (CFN_FLAG_FOLDER | CFN_FLAG_MOUNT_POINT);
|
||||
pFolderNode->Parent = Parent;
|
||||
FolderNodes++;
|
||||
|
||||
// Set the node sub name to the node
|
||||
SetNodePlainName(pFolderNode, szNodeBegin, szFileName + i);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Move the parent to the current node
|
||||
@@ -577,9 +645,15 @@ bool CASC_FILE_TREE::SetNodeFileName(PCASC_FILE_NODE pFileNode, const char * szF
|
||||
|
||||
// Move the begin of the node after the separator
|
||||
szNodeBegin = szFileName + i + 1;
|
||||
|
||||
// If the separator character was already appended, skip the rest of the loop
|
||||
if(PathSeparators[chOneChar] == 0x02)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the next character, even if it was slash/backslash before
|
||||
// Append the character, if not appended yet
|
||||
PathBuffer.AppendChar(AsciiToUpperTable_BkSlash[chOneChar]);
|
||||
}
|
||||
|
||||
@@ -597,90 +671,12 @@ bool CASC_FILE_TREE::SetNodeFileName(PCASC_FILE_NODE pFileNode, const char * szF
|
||||
if(pFileNode->FileNameHash == 0)
|
||||
{
|
||||
pFileNode->FileNameHash = CalcNormNameHash(PathBuffer, i);
|
||||
InsertToHashTable(pFileNode);
|
||||
InsertToNameMap(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;
|
||||
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(szPathBuffer, 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
|
||||
szPathBuffer[i] = 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(szPathBuffer, i);
|
||||
InsertToHashTable(pFileNode);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
size_t CASC_FILE_TREE::GetMaxFileIndex()
|
||||
{
|
||||
if(FileDataIds.IsInitialized())
|
||||
|
||||
@@ -82,7 +82,7 @@ class CASC_FILE_TREE
|
||||
// Retrieve the maximum FileDataId ever inserted
|
||||
DWORD GetNextFileDataId();
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef CASCLIB_DEBUG
|
||||
void DumpFileDataIds(const char * szFileName)
|
||||
{
|
||||
FileDataIds.Dump(szFileName);
|
||||
@@ -93,7 +93,7 @@ class CASC_FILE_TREE
|
||||
|
||||
PCASC_FILE_NODE InsertNew(PCASC_CKEY_ENTRY pCKeyEntry);
|
||||
PCASC_FILE_NODE InsertNew();
|
||||
bool InsertToHashTable(PCASC_FILE_NODE pFileNode);
|
||||
bool InsertToNameMap(PCASC_FILE_NODE pFileNode);
|
||||
bool InsertToIdTable(PCASC_FILE_NODE pFileNode);
|
||||
|
||||
bool SetNodePlainName(PCASC_FILE_NODE pFileNode, const char * szPlainName, const char * szPlainNameEnd);
|
||||
|
||||
@@ -62,14 +62,16 @@ static char * ListFile_SkipSpaces(PLISTFILE_CACHE pCache)
|
||||
|
||||
static void ListFile_CheckFormat(PLISTFILE_CACHE pCache)
|
||||
{
|
||||
// Only if the listfile is greatger than 2 MB
|
||||
if((pCache->pEnd - pCache->pBegin) > 0x100000)
|
||||
const size_t nSizeLimit = 0x20;
|
||||
|
||||
// Only if the listfile is greater than 2 MB
|
||||
if((pCache->pEnd - pCache->pBegin) > nSizeLimit)
|
||||
{
|
||||
char * szPtr = pCache->pBegin;
|
||||
size_t nDigitCount = 0;
|
||||
|
||||
// Calculate the amount of digits
|
||||
while(nDigitCount <= 20 && '0' <= szPtr[nDigitCount] && szPtr[nDigitCount] <= '9')
|
||||
while(nDigitCount <= nSizeLimit && '0' <= szPtr[nDigitCount] && szPtr[nDigitCount] <= '9')
|
||||
nDigitCount++;
|
||||
|
||||
// There must be a semicolon after
|
||||
|
||||
@@ -331,7 +331,7 @@ DWORD CASC_MIME_ELEMENT::Load(char * mime_data_begin, char * mime_data_end, cons
|
||||
// Otherwise, we decode the data to the end of the document
|
||||
if(boundary_ptr != NULL)
|
||||
{
|
||||
// Find the end of the current data by the boundary. It is 2 characters before the next boundary
|
||||
// Find the end of the current data by the boundary. It is 2 characters before the next boundary
|
||||
content.end = strstr(content.ptr, boundary_ptr);
|
||||
if(content.end == NULL)
|
||||
return ERROR_BAD_FORMAT;
|
||||
@@ -362,7 +362,7 @@ DWORD CASC_MIME_ELEMENT::Load(char * mime_data_begin, char * mime_data_end, cons
|
||||
case MimeEncodingBase64:
|
||||
dwErrCode = DecodeBase64(content.ptr, content.end, data);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
dwErrCode = ERROR_NOT_SUPPORTED;
|
||||
assert(false);
|
||||
@@ -379,7 +379,7 @@ DWORD CASC_MIME_ELEMENT::Load(char * mime_data_begin, char * mime_data_end, cons
|
||||
return dwErrCode;
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef CASCLIB_DEBUG
|
||||
#define MAX_LEVEL 0x10
|
||||
void CASC_MIME_ELEMENT::Print(size_t nLevel, size_t nIndex)
|
||||
{
|
||||
@@ -473,7 +473,7 @@ bool CASC_MIME_ELEMENT::ExtractBoundary(const char * line)
|
||||
{
|
||||
// Set begin of the boundary
|
||||
begin = begin + 10;
|
||||
|
||||
|
||||
// Is there also end?
|
||||
if((end = strchr(begin, '\"')) != NULL)
|
||||
{
|
||||
@@ -647,7 +647,7 @@ DWORD CASC_MIME::Load(char * data, CASC_MIME_RESPONSE & MimeResponse)
|
||||
return ERROR_BAD_FORMAT;
|
||||
|
||||
// Debug: dump the MIME data to file
|
||||
#ifdef _DEBUG
|
||||
#ifdef CASCLIB_DEBUG
|
||||
//CascDumpData("E:\\mime_raw_data.txt", data, MimeResponse.response_length);
|
||||
#endif
|
||||
|
||||
@@ -667,7 +667,7 @@ DWORD CASC_MIME::Load(char * data, CASC_MIME_RESPONSE & MimeResponse)
|
||||
return root.Load(data, data + MimeResponse.response_length);
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef CASCLIB_DEBUG
|
||||
void CASC_MIME::Print()
|
||||
{
|
||||
root.Print(0, 0);
|
||||
|
||||
@@ -92,7 +92,7 @@ class CASC_MIME_ELEMENT
|
||||
|
||||
CASC_MIME_ELEMENT * GetChild() { return folder.pChild; }
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef CASCLIB_DEBUG
|
||||
void Print(size_t nLevel, size_t nIndex);
|
||||
#endif
|
||||
|
||||
@@ -127,7 +127,7 @@ class CASC_MIME
|
||||
|
||||
DWORD Load(char * data, CASC_MIME_RESPONSE & MimeResponse);
|
||||
|
||||
#ifdef _DEBUG
|
||||
#ifdef CASCLIB_DEBUG
|
||||
void Print();
|
||||
#endif
|
||||
|
||||
|
||||
@@ -83,8 +83,8 @@ PCASC_CKEY_ENTRY TFileTreeRoot::Search(TCascSearch * pSearch, PCASC_FIND_DATA pF
|
||||
pFileNode = FileTree.PathAt(pFindData->szFileName, MAX_PATH, pSearch->nFileIndex++);
|
||||
if(pFileNode != NULL)
|
||||
{
|
||||
// Ignore folders and mount points
|
||||
if(!(pFileNode->Flags & CFN_FLAG_FOLDER))
|
||||
// Ignore folders, but report mount points. These can and should be able to open and read
|
||||
if((pFileNode->Flags & (CFN_FLAG_FOLDER | CFN_FLAG_MOUNT_POINT)) != CFN_FLAG_FOLDER)
|
||||
{
|
||||
// Check the wildcard
|
||||
if(CascCheckWildCard(pFindData->szFileName, pSearch->szMask))
|
||||
|
||||
@@ -13,13 +13,34 @@
|
||||
#include "../CascLib.h"
|
||||
#include "../CascCommon.h"
|
||||
|
||||
#ifdef CASCLIB_PLATFORM_WINDOWS
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Local variables
|
||||
|
||||
#define BUFFER_INITIAL_SIZE 0x8000
|
||||
|
||||
#ifndef INVALID_SOCKET
|
||||
#define INVALID_SOCKET (SOCKET)(-1) // Not defined in Linux
|
||||
#endif
|
||||
|
||||
CASC_SOCKET_CACHE SocketCache;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Conversion functions
|
||||
|
||||
static SOCKET inline HandleToSocket(HANDLE sock)
|
||||
{
|
||||
return (SOCKET)(intptr_t)(sock);
|
||||
}
|
||||
|
||||
static HANDLE inline SocketToHandle(SOCKET sock)
|
||||
{
|
||||
return (HANDLE)(intptr_t)(sock);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// CASC_SOCKET functions
|
||||
|
||||
@@ -42,10 +63,10 @@ char * CASC_SOCKET::ReadResponse(const char * request, size_t request_length, CA
|
||||
|
||||
// Send the request to the remote host. On Linux, this call may send signal(SIGPIPE),
|
||||
// we need to prevend that by using the MSG_NOSIGNAL flag. On Windows, it fails normally.
|
||||
while(send(sock, request, (int)request_length, MSG_NOSIGNAL) == SOCKET_ERROR)
|
||||
while(send(HandleToSocket(sock), request, (int)request_length, MSG_NOSIGNAL) == SOCKET_ERROR)
|
||||
{
|
||||
// If the connection was closed by the remote host, we try to reconnect
|
||||
if(ReconnectAfterShutdown(sock, remoteItem) == INVALID_SOCKET)
|
||||
if(ReconnectAfterShutdown(sock, remoteItem) == SocketToHandle(INVALID_SOCKET))
|
||||
{
|
||||
SetCascError(ERROR_NETWORK_NOT_AVAILABLE);
|
||||
CascUnlock(Lock);
|
||||
@@ -74,7 +95,7 @@ char * CASC_SOCKET::ReadResponse(const char * request, size_t request_length, CA
|
||||
|
||||
// Receive the next part of the response, up to buffer size
|
||||
// Return value 0 means "connection closed", -1 means an error
|
||||
bytes_received = recv(sock, server_response + total_received, (int)(buffer_length - total_received), 0);
|
||||
bytes_received = recv(HandleToSocket(sock), server_response + total_received, (int)(buffer_length - total_received), 0);
|
||||
if(bytes_received <= 0)
|
||||
{
|
||||
MimeResponse.ParseResponse(server_response, total_received, true);
|
||||
@@ -192,28 +213,28 @@ DWORD CASC_SOCKET::GetAddrInfoWrapper(const char * hostName, unsigned portNum, P
|
||||
}
|
||||
}
|
||||
|
||||
SOCKET CASC_SOCKET::CreateAndConnect(addrinfo * remoteItem)
|
||||
HANDLE CASC_SOCKET::CreateAndConnect(PADDRINFO remoteItem)
|
||||
{
|
||||
SOCKET sock;
|
||||
|
||||
// Create new socket
|
||||
// On error, returns returns INVALID_SOCKET (-1) on Windows, -1 on Linux
|
||||
// On error, returns returns INVALID_SOCKET (0 on Windows, -1 on Linux)
|
||||
if((sock = socket(remoteItem->ai_family, remoteItem->ai_socktype, remoteItem->ai_protocol)) > 0)
|
||||
{
|
||||
// Connect to the remote host
|
||||
// On error, returns SOCKET_ERROR (-1) on Windows, -1 on Linux
|
||||
if(connect(sock, remoteItem->ai_addr, (int)remoteItem->ai_addrlen) == 0)
|
||||
return sock;
|
||||
return SocketToHandle(sock);
|
||||
|
||||
// Failed. Close the socket and return 0
|
||||
// Failed. Close the socket and return INVALID_SOCKET
|
||||
closesocket(sock);
|
||||
sock = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
return sock;
|
||||
return SocketToHandle(sock);
|
||||
}
|
||||
|
||||
SOCKET CASC_SOCKET::ReconnectAfterShutdown(SOCKET & sock, addrinfo * remoteItem)
|
||||
HANDLE CASC_SOCKET::ReconnectAfterShutdown(HANDLE & sock, PADDRINFO remoteItem)
|
||||
{
|
||||
// Retrieve the error code related to previous socket operation
|
||||
switch(GetSockError())
|
||||
@@ -222,8 +243,8 @@ SOCKET CASC_SOCKET::ReconnectAfterShutdown(SOCKET & sock, addrinfo * remoteItem)
|
||||
case WSAECONNRESET: // Windows
|
||||
{
|
||||
// Close the old socket
|
||||
if(sock != INVALID_SOCKET)
|
||||
closesocket(sock);
|
||||
if(sock != SocketToHandle(INVALID_SOCKET))
|
||||
closesocket(HandleToSocket(sock));
|
||||
|
||||
// Attempt to reconnect
|
||||
sock = CreateAndConnect(remoteItem);
|
||||
@@ -232,10 +253,10 @@ SOCKET CASC_SOCKET::ReconnectAfterShutdown(SOCKET & sock, addrinfo * remoteItem)
|
||||
}
|
||||
|
||||
// Another problem
|
||||
return INVALID_SOCKET;
|
||||
return SocketToHandle(INVALID_SOCKET);
|
||||
}
|
||||
|
||||
PCASC_SOCKET CASC_SOCKET::New(addrinfo * remoteList, addrinfo * remoteItem, const char * hostName, unsigned portNum, SOCKET sock)
|
||||
PCASC_SOCKET CASC_SOCKET::New(PADDRINFO remoteList, PADDRINFO remoteItem, const char * hostName, unsigned portNum, HANDLE sock)
|
||||
{
|
||||
PCASC_SOCKET pSocket;
|
||||
size_t length = strlen(hostName);
|
||||
@@ -268,7 +289,7 @@ PCASC_SOCKET CASC_SOCKET::Connect(const char * hostName, unsigned portNum)
|
||||
addrinfo * remoteList;
|
||||
addrinfo * remoteItem;
|
||||
addrinfo hints = {0};
|
||||
SOCKET sock;
|
||||
HANDLE sock;
|
||||
int nErrCode;
|
||||
|
||||
// Retrieve the information about the remote host
|
||||
@@ -293,7 +314,7 @@ PCASC_SOCKET CASC_SOCKET::Connect(const char * hostName, unsigned portNum)
|
||||
}
|
||||
|
||||
// Close the socket
|
||||
closesocket(sock);
|
||||
closesocket(HandleToSocket(sock));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,7 +337,7 @@ void CASC_SOCKET::Delete()
|
||||
|
||||
// Close the socket, if any
|
||||
if(sock != 0)
|
||||
closesocket(sock);
|
||||
closesocket(HandleToSocket(sock));
|
||||
sock = 0;
|
||||
|
||||
// Free the lock
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Defines
|
||||
|
||||
#ifndef INVALID_SOCKET
|
||||
#define INVALID_SOCKET (SOCKET)(-1)
|
||||
#endif
|
||||
|
||||
#ifndef SOCKET_ERROR
|
||||
#define SOCKET_ERROR (-1)
|
||||
#endif
|
||||
@@ -57,9 +53,9 @@ class CASC_SOCKET
|
||||
// Constructor and destructor
|
||||
static int GetSockError();
|
||||
static DWORD GetAddrInfoWrapper(const char * hostName, unsigned portNum, PADDRINFO hints, PADDRINFO * ppResult);
|
||||
static SOCKET CreateAndConnect(addrinfo * remoteItem);
|
||||
static SOCKET ReconnectAfterShutdown(SOCKET & sock, addrinfo * remoteItem);
|
||||
static PCASC_SOCKET New(addrinfo * remoteList, addrinfo * remoteItem, const char * hostName, unsigned portNum, SOCKET sock);
|
||||
static HANDLE CreateAndConnect(PADDRINFO remoteItem);
|
||||
static HANDLE ReconnectAfterShutdown(HANDLE & sock, PADDRINFO remoteItem);
|
||||
static PCASC_SOCKET New(PADDRINFO remoteList, PADDRINFO remoteItem, const char * hostName, unsigned portNum, HANDLE sock);
|
||||
static PCASC_SOCKET Connect(const char * hostName, unsigned portNum);
|
||||
|
||||
// Frees all resources and deletes the socket
|
||||
@@ -76,7 +72,7 @@ class CASC_SOCKET
|
||||
PADDRINFO remoteList; // List of the remote host informations
|
||||
PADDRINFO remoteItem; // The particular host picked during the last connection attempt
|
||||
CASC_LOCK Lock; // Lock for single threaded access
|
||||
SOCKET sock; // Opened and connected socket
|
||||
HANDLE sock; // Opened and connected socket
|
||||
DWORD dwRefCount; // Number of references
|
||||
DWORD portNum; // Port number
|
||||
char hostName[1]; // Buffer for storing remote host (variable length)
|
||||
|
||||
@@ -63,7 +63,7 @@ catch2
|
||||
|
||||
CascLib (An open-source implementation of library for reading CASC storage from Blizzard games since 2014)
|
||||
https://github.com/ladislav-zezula/CascLib
|
||||
Version: a5080b5794027a25d98aa6024b2bef17d06fe0ea
|
||||
Version: ebd79e8fd43279343c543a27fce620f6b1b53cb9
|
||||
|
||||
rapidjson (A fast JSON parser/generator for C++ with both SAX/DOM style API http://rapidjson.org/)
|
||||
https://github.com/Tencent/rapidjson
|
||||
|
||||
Reference in New Issue
Block a user