TrinityCore
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
CascOpenStorage.cpp File Reference
#include "CascLib.h"
#include "CascCommon.h"
+ Include dependency graph for CascOpenStorage.cpp:

Classes

struct  _BLOCK_SIZE_AND_HASH
 
struct  _FILE_INDEX_HEADER_V1
 
struct  _FILE_INDEX_HEADER_V2
 
struct  _FILE_ENCODING_SEGMENT
 

Macros

#define __CASCLIB_SELF__
 
#define CASC_ENCODING_SEGMENT_SIZE   0x1000
 

Typedefs

typedef struct _BLOCK_SIZE_AND_HASH BLOCK_SIZE_AND_HASH
 
typedef struct
_BLOCK_SIZE_AND_HASH
PBLOCK_SIZE_AND_HASH
 
typedef struct
_FILE_INDEX_HEADER_V1 
FILE_INDEX_HEADER_V1
 
typedef struct
_FILE_INDEX_HEADER_V1
PFILE_INDEX_HEADER_V1
 
typedef struct
_FILE_INDEX_HEADER_V2 
FILE_INDEX_HEADER_V2
 
typedef struct
_FILE_INDEX_HEADER_V2
PFILE_INDEX_HEADER_V2
 
typedef struct
_FILE_ENCODING_SEGMENT 
FILE_ENCODING_SEGMENT
 
typedef struct
_FILE_ENCODING_SEGMENT
PFILE_ENCODING_SEGMENT
 

Functions

void CopyFileKey (LPBYTE Trg, LPBYTE Src)
 
TCascStorageIsValidStorageHandle (HANDLE hStorage)
 
static bool IsIndexFileName_V1 (const TCHAR *szFileName)
 
static bool IsIndexFileName_V2 (const TCHAR *szFileName)
 
static bool IsCascIndexHeader_V1 (LPBYTE pbFileData, DWORD cbFileData)
 
static bool IsCascIndexHeader_V2 (LPBYTE pbFileData, DWORD cbFileData)
 
static bool CutLastPathPart (TCHAR *szWorkPath)
 
static int InsertExtraFile (TCascStorage *hs, const char *szFileName, PQUERY_KEY pQueryKey)
 
static int InitializeCascDirectories (TCascStorage *hs, const TCHAR *szDataPath)
 
static bool IndexDirectory_OnFileFound (const TCHAR *szFileName, PDWORD IndexArray, PDWORD OldIndexArray, void *pvContext)
 
static TCHARCreateIndexFileName (TCascStorage *hs, DWORD IndexValue, DWORD IndexVersion)
 
static int VerifyAndParseKeyMapping_V1 (PCASC_MAPPING_TABLE pKeyMapping, DWORD KeyIndex)
 
static int VerifyAndParseKeyMapping_V2 (PCASC_MAPPING_TABLE pKeyMapping, DWORD KeyIndex)
 
static int VerifyAndParseKeyMapping (PCASC_MAPPING_TABLE pKeyMapping, DWORD KeyIndex)
 
static int LoadKeyMapping (PCASC_MAPPING_TABLE pKeyMapping, DWORD KeyIndex)
 
static int CreateArrayOfIndexEntries (TCascStorage *hs)
 
static int CreateMapOfEncodingKeys (TCascStorage *hs, PFILE_ENCODING_SEGMENT pEncodingSegment, DWORD dwNumSegments)
 
static int LoadIndexFiles (TCascStorage *hs)
 
static LPBYTE LoadEncodingFileToMemory (HANDLE hFile, DWORD *pcbEncodingFile)
 
static LPBYTE LoadRootFileToMemory (HANDLE hFile, DWORD *pcbRootFile)
 
static int LoadEncodingFile (TCascStorage *hs)
 
static int LoadRootFile (TCascStorage *hs, DWORD dwLocaleMask)
 
static TCascStorageFreeCascStorage (TCascStorage *hs)
 
bool WINAPI CascOpenStorage (const TCHAR *szDataPath, DWORD dwLocaleMask, HANDLE *phStorage)
 
bool WINAPI CascGetStorageInfo (HANDLE hStorage, CASC_STORAGE_INFO_CLASS InfoClass, void *pvStorageInfo, size_t cbStorageInfo, size_t *pcbLengthNeeded)
 
bool WINAPI CascCloseStorage (HANDLE hStorage)
 

Variables

static const TCHARszAllowedHexChars = _T("0123456789aAbBcCdDeEfF")
 
static const TCHARszIndexFormat_V1 = _T("data.i%x%x")
 
static const TCHARszIndexFormat_V2 = _T("%02x%08x.idx")
 

Macro Definition Documentation

#define __CASCLIB_SELF__
#define CASC_ENCODING_SEGMENT_SIZE   0x1000

Typedef Documentation

Function Documentation

bool WINAPI CascCloseStorage ( HANDLE  hStorage)
1134 {
1135  TCascStorage * hs;
1136 
1137  // Verify the storage handle
1138  hs = IsValidStorageHandle(hStorage);
1139  if(hs == NULL)
1140  {
1142  return false;
1143  }
1144 
1145  // Only free the storage if the reference count reaches 0
1146  if(hs->dwRefCount == 1)
1147  {
1148  FreeCascStorage(hs);
1149  return true;
1150  }
1151 
1152  // Just decrement number of references
1153  hs->dwRefCount--;
1154  return true;
1155 }
TCascStorage * IsValidStorageHandle(HANDLE hStorage)
Definition: CascOpenStorage.cpp:100
arena_t NULL
Definition: jemalloc_internal.h:624
void SetLastError(int nError)
Definition: Common.cpp:75
Definition: CascCommon.h:186
DWORD dwRefCount
Definition: CascCommon.h:195
#define ERROR_INVALID_PARAMETER
Definition: CascPort.h:210
static TCascStorage * FreeCascStorage(TCascStorage *hs)
Definition: CascOpenStorage.cpp:934

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

bool WINAPI CascGetStorageInfo ( HANDLE  hStorage,
CASC_STORAGE_INFO_CLASS  InfoClass,
void *  pvStorageInfo,
size_t  cbStorageInfo,
size_t *  pcbLengthNeeded 
)
1081 {
1082  TCascStorage * hs;
1083  DWORD dwInfoValue = 0;
1084 
1085  // Verify the storage handle
1086  hs = IsValidStorageHandle(hStorage);
1087  if(hs == NULL)
1088  {
1090  return false;
1091  }
1092 
1093  // Differentiate between info classes
1094  switch(InfoClass)
1095  {
1096  case CascStorageFileCount:
1097  dwInfoValue = (DWORD)hs->pIndexEntryMap->ItemCount;
1098  break;
1099 
1100  case CascStorageFeatures:
1101  dwInfoValue |= (hs->pRootHandler->dwRootFlags & ROOT_FLAG_HAS_NAMES) ? CASC_FEATURE_LISTFILE : 0;
1102  break;
1103 
1104  case CascStorageGameInfo:
1105  dwInfoValue = hs->dwGameInfo;
1106  break;
1107 
1108  case CascStorageGameBuild:
1109  dwInfoValue = hs->dwBuildNumber;
1110  break;
1111 
1112  default:
1114  return false;
1115  }
1116 
1117  //
1118  // Return the required DWORD value
1119  //
1120 
1121  if(cbStorageInfo < sizeof(DWORD))
1122  {
1123  *pcbLengthNeeded = sizeof(DWORD);
1125  return false;
1126  }
1127 
1128  // Give the number of files
1129  *(PDWORD)pvStorageInfo = dwInfoValue;
1130  return true;
1131 }
TRootHandler * pRootHandler
Definition: CascCommon.h:223
Definition: CascLib.h:131
Definition: CascLib.h:132
DWORD * PDWORD
Definition: CascPort.h:151
TCascStorage * IsValidStorageHandle(HANDLE hStorage)
Definition: CascOpenStorage.cpp:100
DWORD dwRootFlags
Definition: RootHandler.h:75
#define ERROR_INSUFFICIENT_BUFFER
Definition: CascPort.h:213
#define ROOT_FLAG_HAS_NAMES
Definition: RootHandler.h:21
PCASC_MAP pIndexEntryMap
Definition: CascCommon.h:217
arena_t NULL
Definition: jemalloc_internal.h:624
Definition: CascLib.h:129
#define ERROR_INVALID_HANDLE
Definition: CascPort.h:207
Definition: CascLib.h:130
void SetLastError(int nError)
Definition: Common.cpp:75
Definition: CascCommon.h:186
DWORD dwGameInfo
Definition: CascCommon.h:196
unsigned int DWORD
Definition: CascPort.h:139
#define ERROR_INVALID_PARAMETER
Definition: CascPort.h:210
size_t ItemCount
Definition: Map.h:22
#define CASC_FEATURE_LISTFILE
Definition: CascLib.h:122
DWORD dwBuildNumber
Definition: CascCommon.h:197

+ Here is the call graph for this function:

bool WINAPI CascOpenStorage ( const TCHAR szDataPath,
DWORD  dwLocaleMask,
HANDLE phStorage 
)
1012 {
1013  TCascStorage * hs;
1014  int nError = ERROR_SUCCESS;
1015 
1016  // Allocate the storage structure
1017  hs = (TCascStorage *)CASC_ALLOC(TCascStorage, 1);
1018  if(hs == NULL)
1019  nError = ERROR_NOT_ENOUGH_MEMORY;
1020 
1021  // Load the storage configuration
1022  if(nError == ERROR_SUCCESS)
1023  {
1024  // Prepare the base storage parameters
1025  memset(hs, 0, sizeof(TCascStorage));
1026  hs->szClassName = "TCascStorage";
1027  hs->dwFileBeginDelta = 0xFFFFFFFF;
1029  hs->dwRefCount = 1;
1030  nError = InitializeCascDirectories(hs, szDataPath);
1031  }
1032 
1033  // Now we need to load the root file so we know the config files
1034  if(nError == ERROR_SUCCESS)
1035  {
1036  nError = LoadBuildInfo(hs);
1037  }
1038 
1039  // Load the index files
1040  if(nError == ERROR_SUCCESS)
1041  {
1042  nError = LoadIndexFiles(hs);
1043  }
1044 
1045  // Load the index files
1046  if(nError == ERROR_SUCCESS)
1047  {
1048  nError = LoadEncodingFile(hs);
1049  }
1050 
1051  // Initialize the dynamic array for extra files
1052  // Reserve space for 0x20 encoding entries
1053  if(nError == ERROR_SUCCESS)
1054  {
1056  }
1057 
1058  // Load the index files
1059  if(nError == ERROR_SUCCESS)
1060  {
1061  nError = LoadRootFile(hs, dwLocaleMask);
1062  }
1063 
1064  // If something failed, free the storage and return
1065  if(nError != ERROR_SUCCESS)
1066  {
1067  hs = FreeCascStorage(hs);
1068  SetLastError(nError);
1069  }
1070 
1071  *phStorage = (HANDLE)hs;
1072  return (nError == ERROR_SUCCESS);
1073 }
DWORD dwDefaultLocale
Definition: CascCommon.h:199
#define CASC_ALLOC(type, count)
Definition: CascCommon.h:302
void * HANDLE
Definition: CascPort.h:146
#define Array_Create(pArray, type, ItemCountMax)
Definition: DynamicArray.h:35
#define CASC_EXTRA_FILES
Definition: CascCommon.h:53
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
static int LoadEncodingFile(TCascStorage *hs)
Definition: CascOpenStorage.cpp:765
static int InitializeCascDirectories(TCascStorage *hs, const TCHAR *szDataPath)
Definition: CascOpenStorage.cpp:224
int LoadBuildInfo(TCascStorage *hs)
Definition: CascFiles.cpp:826
arena_t NULL
Definition: jemalloc_internal.h:624
DWORD dwFileBeginDelta
Definition: CascCommon.h:198
DYNAMIC_ARRAY ExtraEntries
Definition: CascCommon.h:221
#define CASC_LOCALE_ENUS
Definition: CascLib.h:67
void SetLastError(int nError)
Definition: Common.cpp:75
Definition: CascCommon.h:186
DWORD dwRefCount
Definition: CascCommon.h:195
Definition: CascCommon.h:171
static TCascStorage * FreeCascStorage(TCascStorage *hs)
Definition: CascOpenStorage.cpp:934
const char * szClassName
Definition: CascCommon.h:188
#define CASC_LOCALE_ENGB
Definition: CascLib.h:75
static int LoadIndexFiles(TCascStorage *hs)
Definition: CascOpenStorage.cpp:638
#define ERROR_SUCCESS
Definition: CascPort.h:204
static int LoadRootFile(TCascStorage *hs, DWORD dwLocaleMask)
Definition: CascOpenStorage.cpp:856

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

void CopyFileKey ( LPBYTE  Trg,
LPBYTE  Src 
)
inline
81 {
82  Trg[0x00] = Src[0x00];
83  Trg[0x01] = Src[0x01];
84  Trg[0x02] = Src[0x02];
85  Trg[0x03] = Src[0x03];
86  Trg[0x04] = Src[0x04];
87  Trg[0x05] = Src[0x05];
88  Trg[0x06] = Src[0x06];
89  Trg[0x07] = Src[0x07];
90  Trg[0x08] = Src[0x08];
91  Trg[0x09] = Src[0x09];
92  Trg[0x0A] = Src[0x0A];
93  Trg[0x0B] = Src[0x0B];
94  Trg[0x0C] = Src[0x0C];
95  Trg[0x0D] = Src[0x0D];
96  Trg[0x0E] = Src[0x0E];
97  Trg[0x0F] = Src[0x0F];
98 }
static int CreateArrayOfIndexEntries ( TCascStorage hs)
static
544 {
545  PCASC_MAP pMap;
546  DWORD TotalCount = 0;
547  int nError = ERROR_NOT_ENOUGH_MEMORY;
548 
549  // Count the total number of files in the storage
550  for(size_t i = 0; i < CASC_INDEX_COUNT; i++)
551  TotalCount += hs->KeyMapping[i].nIndexEntries;
552 
553  // Create the map of all index entries
554  pMap = Map_Create(TotalCount, CASC_FILE_KEY_SIZE, FIELD_OFFSET(CASC_INDEX_ENTRY, IndexKey));
555  if(pMap != NULL)
556  {
557  // Put all index entries in the map
558  for(size_t i = 0; i < CASC_INDEX_COUNT; i++)
559  {
560  PCASC_INDEX_ENTRY pIndexEntry = hs->KeyMapping[i].pIndexEntries;
561  DWORD nIndexEntries = hs->KeyMapping[i].nIndexEntries;
562 
563  for(DWORD j = 0; j < nIndexEntries; j++)
564  {
565  // Insert the index entry to the map
566  // Note that duplicate entries will not be inserted to the map
567  //
568  // Duplicate entries in WoW-WOD build 18179:
569  // 9e dc a7 8f e2 09 ad d8 b7 (encoding file)
570  // f3 5e bb fb d1 2b 3f ef 8b
571  // c8 69 9f 18 a2 5e df 7e 52
572  Map_InsertObject(pMap, pIndexEntry, pIndexEntry->IndexKey);
573 
574  // Move to the next entry
575  pIndexEntry++;
576  }
577  }
578 
579  // Store the map to the storage handle
580  hs->pIndexEntryMap = pMap;
581  nError = ERROR_SUCCESS;
582  }
583 
584  return nError;
585 }
PCASC_MAP Map_Create(DWORD dwMaxItems, DWORD dwKeyLength, DWORD dwKeyOffset)
Definition: Map.cpp:93
CASC_MAPPING_TABLE KeyMapping[CASC_INDEX_COUNT]
Definition: CascCommon.h:216
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
PCASC_MAP pIndexEntryMap
Definition: CascCommon.h:217
arena_t NULL
Definition: jemalloc_internal.h:624
PCASC_INDEX_ENTRY pIndexEntries
Definition: CascCommon.h:121
DWORD nIndexEntries
Definition: CascCommon.h:122
#define CASC_INDEX_COUNT
Definition: CascCommon.h:50
bool Map_InsertObject(PCASC_MAP pMap, void *pvNewObject, void *pvKey)
Definition: Map.cpp:170
#define FIELD_OFFSET(t, f)
Definition: CascPort.h:122
unsigned int DWORD
Definition: CascPort.h:139
Definition: Map.h:19
Definition: CascCommon.h:102
#define CASC_FILE_KEY_SIZE
Definition: CascCommon.h:51
BYTE IndexKey[CASC_FILE_KEY_SIZE]
Definition: CascCommon.h:104
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static TCHAR* CreateIndexFileName ( TCascStorage hs,
DWORD  IndexValue,
DWORD  IndexVersion 
)
static
335 {
336  TCHAR szPlainName[0x40];
337 
338  // Sanity checks
339  assert(hs->szIndexFormat != NULL);
340  assert(hs->szIndexPath != NULL);
341  assert(IndexValue <= 0x0F);
342 
343  // Create the full path
344  _stprintf(szPlainName, hs->szIndexFormat, IndexValue, IndexVersion);
345  return CombinePath(hs->szIndexPath, szPlainName);
346 }
arena_t NULL
Definition: jemalloc_internal.h:624
char TCHAR
Definition: CascPort.h:148
const TCHAR * szIndexFormat
Definition: CascCommon.h:189
TCHAR * CombinePath(const TCHAR *szDirectory, const TCHAR *szSubDir)
Definition: Common.cpp:157
TCHAR * szIndexPath
Definition: CascCommon.h:193
#define _stprintf
Definition: CascPort.h:181

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int CreateMapOfEncodingKeys ( TCascStorage hs,
PFILE_ENCODING_SEGMENT  pEncodingSegment,
DWORD  dwNumSegments 
)
static
588 {
589  PCASC_ENCODING_ENTRY pEncodingEntry;
590  DWORD dwMaxEntries;
591  int nError = ERROR_SUCCESS;
592 
593  // Sanity check
594  assert(hs->pIndexEntryMap != NULL);
595  assert(hs->pEncodingMap == NULL);
596 
597  // Calculate the largest eventual number of encoding entries
598  // Add space for extra entries
599  dwMaxEntries = (dwNumSegments * CASC_ENCODING_SEGMENT_SIZE) / (sizeof(CASC_ENCODING_ENTRY) + MD5_HASH_SIZE);
600 
601  // Create the map of the encoding entries
603  if(hs->pEncodingMap != NULL)
604  {
605  LPBYTE pbStartOfSegment = (LPBYTE)(pEncodingSegment + dwNumSegments);
606 
607  // Parse all segments
608  for(DWORD i = 0; i < dwNumSegments; i++)
609  {
610  LPBYTE pbEncodingEntry = pbStartOfSegment;
611  LPBYTE pbEndOfSegment = pbStartOfSegment + CASC_ENCODING_SEGMENT_SIZE - sizeof(CASC_ENCODING_ENTRY) - MD5_HASH_SIZE;
612 
613  // Parse all encoding entries
614  while(pbEncodingEntry <= pbEndOfSegment)
615  {
616  // Get pointer to the encoding entry
617  pEncodingEntry = (PCASC_ENCODING_ENTRY)pbEncodingEntry;
618  if(pEncodingEntry->KeyCount == 0)
619  break;
620 
621  // Insert the pointer the array
622  Map_InsertObject(hs->pEncodingMap, pEncodingEntry, pEncodingEntry->EncodingKey);
623 
624  // Move to the next encoding entry
625  pbEncodingEntry += sizeof(CASC_ENCODING_ENTRY) + (pEncodingEntry->KeyCount * MD5_HASH_SIZE);
626  }
627 
628  // Move to the next segment
629  pbStartOfSegment += CASC_ENCODING_SEGMENT_SIZE;
630  }
631  }
632  else
633  nError = ERROR_NOT_ENOUGH_MEMORY;
634 
635  return nError;
636 }
PCASC_MAP Map_Create(DWORD dwMaxItems, DWORD dwKeyLength, DWORD dwKeyOffset)
Definition: Map.cpp:93
#define CASC_EXTRA_FILES
Definition: CascCommon.h:53
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
PCASC_MAP pIndexEntryMap
Definition: CascCommon.h:217
arena_t NULL
Definition: jemalloc_internal.h:624
struct _CASC_ENCODING_ENTRY CASC_ENCODING_ENTRY
#define CASC_ENCODING_SEGMENT_SIZE
Definition: CascOpenStorage.cpp:22
BYTE * LPBYTE
Definition: CascPort.h:152
bool Map_InsertObject(PCASC_MAP pMap, void *pvNewObject, void *pvKey)
Definition: Map.cpp:170
#define MD5_HASH_SIZE
Definition: CascLib.h:105
struct _CASC_ENCODING_ENTRY * PCASC_ENCODING_ENTRY
#define FIELD_OFFSET(t, f)
Definition: CascPort.h:122
PCASC_MAP pEncodingMap
Definition: CascCommon.h:220
unsigned int DWORD
Definition: CascPort.h:139
BYTE EncodingKey[MD5_HASH_SIZE]
Definition: CascCommon.h:163
USHORT KeyCount
Definition: CascCommon.h:161
Definition: CascCommon.h:159
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool CutLastPathPart ( TCHAR szWorkPath)
static
166 {
167  size_t nLength = _tcslen(szWorkPath);
168 
169  for(nLength = _tcslen(szWorkPath); nLength > 0; nLength--)
170  {
171  if(szWorkPath[nLength] == '\\' || szWorkPath[nLength] == '/')
172  {
173  szWorkPath[nLength] = 0;
174  return true;
175  }
176  }
177 
178  return false;
179 }
#define _tcslen
Definition: CascPort.h:172

+ Here is the caller graph for this function:

static TCascStorage* FreeCascStorage ( TCascStorage hs)
static
935 {
936  size_t i;
937 
938  if(hs != NULL)
939  {
940  // Free the root handler
941  if(hs->pRootHandler != NULL)
943  hs->pRootHandler = NULL;
944 
945  // Free the extra encoding entries
946  Array_Free(&hs->ExtraEntries);
947 
948  // Free the pointers to file entries
949  if(hs->pEncodingMap != NULL)
950  Map_Free(hs->pEncodingMap);
951  if(hs->EncodingFile.pbData != NULL)
953  if(hs->pIndexEntryMap != NULL)
955 
956  // Close all data files
957  for(i = 0; i < CASC_MAX_DATA_FILES; i++)
958  {
959  if(hs->DataFileArray[i] != NULL)
960  {
962  hs->DataFileArray[i] = NULL;
963  }
964  }
965 
966  // Close all key mappings
967  for(i = 0; i < CASC_INDEX_COUNT; i++)
968  {
969  if(hs->KeyMapping[i].szFileName != NULL)
971  if(hs->KeyMapping[i].pbFileData != NULL)
973  hs->KeyMapping[i].pIndexEntries = NULL;
974  }
975 
976  // Free the file paths
977  if(hs->szRootPath != NULL)
978  CASC_FREE(hs->szRootPath);
979  if(hs->szDataPath != NULL)
980  CASC_FREE(hs->szDataPath);
981  if(hs->szBuildFile != NULL)
982  CASC_FREE(hs->szBuildFile);
983  if(hs->szIndexPath != NULL)
984  CASC_FREE(hs->szIndexPath);
985  if(hs->szUrlPath != NULL)
986  CASC_FREE(hs->szUrlPath);
987 
988  // Free the blobs
994  FreeCascBlob(&hs->RootKey);
995  FreeCascBlob(&hs->PatchKey);
997  FreeCascBlob(&hs->InstallKey);
999 
1000  // Free the storage structure
1001  hs->szClassName = NULL;
1002  CASC_FREE(hs);
1003  }
1004 
1005  return NULL;
1006 }
TRootHandler * pRootHandler
Definition: CascCommon.h:223
QUERY_KEY RootKey
Definition: CascCommon.h:208
CASC_MAPPING_TABLE KeyMapping[CASC_INDEX_COUNT]
Definition: CascCommon.h:216
#define CASC_MAX_DATA_FILES
Definition: CascCommon.h:52
void Map_Free(PCASC_MAP pMap)
Definition: Map.cpp:279
QUERY_KEY ArchivesKey
Definition: CascCommon.h:206
QUERY_KEY DownloadKey
Definition: CascCommon.h:210
PCASC_MAP pIndexEntryMap
Definition: CascCommon.h:217
arena_t NULL
Definition: jemalloc_internal.h:624
void Array_Free(PDYNAMIC_ARRAY pArray)
Definition: DynamicArray.cpp:95
void FreeCascBlob(PQUERY_KEY pBlob)
Definition: CascCommon.cpp:80
LPBYTE pbFileData
Definition: CascCommon.h:112
QUERY_KEY CdnBuildKey
Definition: CascCommon.h:204
PCASC_INDEX_ENTRY pIndexEntries
Definition: CascCommon.h:121
QUERY_KEY ArchivesGroup
Definition: CascCommon.h:205
DYNAMIC_ARRAY ExtraEntries
Definition: CascCommon.h:221
TCHAR * szUrlPath
Definition: CascCommon.h:194
#define CASC_INDEX_COUNT
Definition: CascCommon.h:50
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
TCHAR * szRootPath
Definition: CascCommon.h:190
TCHAR * szFileName
Definition: CascCommon.h:111
QUERY_KEY PatchArchivesKey
Definition: CascCommon.h:207
QUERY_KEY EncodingFile
Definition: CascCommon.h:219
LPBYTE pbData
Definition: CascLib.h:140
PCASC_MAP pEncodingMap
Definition: CascCommon.h:220
QUERY_KEY EncodingKey
Definition: CascCommon.h:212
QUERY_KEY CdnConfigKey
Definition: CascCommon.h:203
TCHAR * szIndexPath
Definition: CascCommon.h:193
TCHAR * szBuildFile
Definition: CascCommon.h:192
void FileStream_Close(TFileStream *pStream)
Definition: FileStream.cpp:2707
void RootHandler_Close(TRootHandler *pRootHandler)
Definition: RootHandler.cpp:71
TCHAR * szDataPath
Definition: CascCommon.h:191
const char * szClassName
Definition: CascCommon.h:188
TFileStream * DataFileArray[CASC_MAX_DATA_FILES]
Definition: CascCommon.h:214
QUERY_KEY PatchKey
Definition: CascCommon.h:209
QUERY_KEY InstallKey
Definition: CascCommon.h:211

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool IndexDirectory_OnFileFound ( const TCHAR szFileName,
PDWORD  IndexArray,
PDWORD  OldIndexArray,
void *  pvContext 
)
static
265 {
266  TCascStorage * hs = (TCascStorage *)pvContext;
267  DWORD IndexValue = 0;
268  DWORD IndexVersion = 0;
269 
270  // Auto-detect the format of the index file name
271  if(hs->szIndexFormat == NULL)
272  {
273  if(IsIndexFileName_V1(szFileName))
275  else if(IsIndexFileName_V2(szFileName))
277  else
278  return false;
279  }
280 
282  {
283  // Check the index file name format
284  if(!IsIndexFileName_V1(szFileName))
285  return false;
286 
287  // Get the main index from the first two digits
288  if(ConvertDigitToInt32(szFileName + 6, &IndexValue) != ERROR_SUCCESS)
289  return false;
290  if(ConvertDigitToInt32(szFileName + 7, &IndexVersion) != ERROR_SUCCESS)
291  return false;
292  }
293 
294  else if(hs->szIndexFormat == szIndexFormat_V2)
295  {
296  // Check the index file name format
297  if(!IsIndexFileName_V2(szFileName))
298  return false;
299 
300  // Get the main index from the first two digits
301  if(ConvertStringToInt32(szFileName, 2, &IndexValue) != ERROR_SUCCESS)
302  return false;
303  if(ConvertStringToInt32(szFileName + 2, 8, &IndexVersion) != ERROR_SUCCESS)
304  return false;
305  }
306  else
307  {
308  // Should never happen
309  assert(false);
310  return false;
311  }
312 
313  // The index value must not be greater than 0x0F
314  if(IndexValue >= CASC_INDEX_COUNT)
315  return false;
316 
317  // If the new subindex is greater than the previous one,
318  // use this one instead
319  if(IndexVersion > IndexArray[IndexValue])
320  {
321  OldIndexArray[IndexValue] = IndexArray[IndexValue];
322  IndexArray[IndexValue] = IndexVersion;
323  }
324  else if(IndexVersion > OldIndexArray[IndexValue])
325  {
326  OldIndexArray[IndexValue] = IndexVersion;
327  }
328 
329  // Note: WoW6 only keeps last two index files
330  // Any additional index files are deleted at this point
331  return true;
332 }
static const TCHAR * szIndexFormat_V1
Definition: CascOpenStorage.cpp:74
int ConvertStringToInt32(const TCHAR *szString, size_t nMaxDigits, PDWORD PtrValue)
Definition: Common.cpp:303
arena_t NULL
Definition: jemalloc_internal.h:624
int ConvertDigitToInt32(const TCHAR *szString, PDWORD PtrValue)
Definition: Common.cpp:275
const TCHAR * szIndexFormat
Definition: CascCommon.h:189
#define CASC_INDEX_COUNT
Definition: CascCommon.h:50
Definition: CascCommon.h:186
static bool IsIndexFileName_V1(const TCHAR *szFileName)
Definition: CascOpenStorage.cpp:108
unsigned int DWORD
Definition: CascPort.h:139
static bool IsIndexFileName_V2(const TCHAR *szFileName)
Definition: CascOpenStorage.cpp:116
static const TCHAR * szIndexFormat_V2
Definition: CascOpenStorage.cpp:75
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int InitializeCascDirectories ( TCascStorage hs,
const TCHAR szDataPath 
)
static
225 {
226  TCHAR * szWorkPath;
227  int nError = ERROR_NOT_ENOUGH_MEMORY;
228 
229  // Find the root directory of the storage. The root directory
230  // is the one where ".build.info" is.
231  szWorkPath = CascNewStr(szDataPath, 0);
232  if(szWorkPath != NULL)
233  {
234  // Get the length and go up until we find the ".build.info" or ".build.db"
235  for(;;)
236  {
237  // Is this a game directory?
238  nError = CheckGameDirectory(hs, szWorkPath);
239  if(nError == ERROR_SUCCESS)
240  {
241  nError = ERROR_SUCCESS;
242  break;
243  }
244 
245  // Cut one path part
246  if(!CutLastPathPart(szWorkPath))
247  {
248  nError = ERROR_FILE_NOT_FOUND;
249  break;
250  }
251  }
252 
253  // Free the work path buffer
254  CASC_FREE(szWorkPath);
255  }
256 
257  return nError;
258 }
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
arena_t NULL
Definition: jemalloc_internal.h:624
char TCHAR
Definition: CascPort.h:148
static bool CutLastPathPart(TCHAR *szWorkPath)
Definition: CascOpenStorage.cpp:165
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
#define ERROR_FILE_NOT_FOUND
Definition: CascPort.h:205
int CheckGameDirectory(TCascStorage *hs, TCHAR *szDirectory)
Definition: CascFiles.cpp:909
char * CascNewStr(const char *szString, size_t nCharsToReserve)
Definition: Common.cpp:102
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int InsertExtraFile ( TCascStorage hs,
const char *  szFileName,
PQUERY_KEY  pQueryKey 
)
static
185 {
186  // If the given key is not encoding key (aka, it's an index key),
187  // we need to create a fake encoding entry
188  if(pQueryKey->cbData == MD5_HASH_SIZE * 2)
189  {
190  PCASC_ENCODING_ENTRY pNewEntry;
191  PCASC_INDEX_ENTRY pIndexEntry;
192  QUERY_KEY IndexKey;
193 
194  // Find the entry in the index table in order to get the file size
195  IndexKey.pbData = pQueryKey->pbData + MD5_HASH_SIZE;
196  IndexKey.cbData = MD5_HASH_SIZE;
197  pIndexEntry = FindIndexEntry(hs, &IndexKey);
198  if(pIndexEntry == NULL)
199  return ERROR_FILE_NOT_FOUND;
200 
201  // Create a fake entry in the encoding map
202  pNewEntry = (PCASC_ENCODING_ENTRY)Array_Insert(&hs->ExtraEntries, NULL, 1);
203  if(pNewEntry == NULL)
205 
206  // Fill the encoding entry
207  pNewEntry->KeyCount = 1;
208  pNewEntry->FileSizeBE[0] = pIndexEntry->FileSizeLE[3];
209  pNewEntry->FileSizeBE[1] = pIndexEntry->FileSizeLE[2];
210  pNewEntry->FileSizeBE[2] = pIndexEntry->FileSizeLE[1];
211  pNewEntry->FileSizeBE[3] = pIndexEntry->FileSizeLE[0];
212  memcpy(pNewEntry->EncodingKey, pQueryKey->pbData, MD5_HASH_SIZE);
213  memcpy(pNewEntry + 1, pQueryKey->pbData + MD5_HASH_SIZE, MD5_HASH_SIZE);
214 
215  // Insert the entry to the map of encoding keys
216  Map_InsertObject(hs->pEncodingMap, pNewEntry, pNewEntry->EncodingKey);
217  }
218 
219  // Now we need to insert the entry to the root handler in order
220  // to be able to translate file name to encoding key
221  return RootHandler_Insert(hs->pRootHandler, szFileName, pQueryKey->pbData);
222 }
TRootHandler * pRootHandler
Definition: CascCommon.h:223
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
BYTE FileSizeBE[4]
Definition: CascCommon.h:162
Definition: CascLib.h:138
arena_t NULL
Definition: jemalloc_internal.h:624
DYNAMIC_ARRAY ExtraEntries
Definition: CascCommon.h:221
DWORD cbData
Definition: CascLib.h:141
bool Map_InsertObject(PCASC_MAP pMap, void *pvNewObject, void *pvKey)
Definition: Map.cpp:170
#define MD5_HASH_SIZE
Definition: CascLib.h:105
struct _CASC_ENCODING_ENTRY * PCASC_ENCODING_ENTRY
#define ERROR_FILE_NOT_FOUND
Definition: CascPort.h:205
LPBYTE pbData
Definition: CascLib.h:140
PCASC_MAP pEncodingMap
Definition: CascCommon.h:220
void * Array_Insert(PDYNAMIC_ARRAY pArray, const void *NewItems, size_t NewItemCount)
Definition: DynamicArray.cpp:63
Definition: CascCommon.h:102
BYTE EncodingKey[MD5_HASH_SIZE]
Definition: CascCommon.h:163
int RootHandler_Insert(TRootHandler *pRootHandler, const char *szFileName, LPBYTE pbEncodingKey)
Definition: RootHandler.cpp:18
USHORT KeyCount
Definition: CascCommon.h:161
Definition: CascCommon.h:159
PCASC_INDEX_ENTRY FindIndexEntry(TCascStorage *hs, PQUERY_KEY pIndexKey)
Definition: CascOpenFile.cpp:25
BYTE FileSizeLE[4]
Definition: CascCommon.h:106

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool IsCascIndexHeader_V1 ( LPBYTE  pbFileData,
DWORD  cbFileData 
)
static
125 {
126  PFILE_INDEX_HEADER_V1 pIndexHeader = (PFILE_INDEX_HEADER_V1)pbFileData;
127  DWORD dwHeaderHash;
128  bool bResult = false;
129 
130  // Check the size
131  if(cbFileData >= sizeof(FILE_INDEX_HEADER_V1))
132  {
133  // Save the header hash
134  dwHeaderHash = pIndexHeader->dwHeaderHash;
135  pIndexHeader->dwHeaderHash = 0;
136 
137  // Calculate the hash
138  if(hashlittle(pIndexHeader, sizeof(FILE_INDEX_HEADER_V1), 0) == dwHeaderHash)
139  bResult = true;
140 
141  // Put the hash back
142  pIndexHeader->dwHeaderHash = dwHeaderHash;
143  }
144 
145  return bResult;
146 }
DWORD dwHeaderHash
Definition: CascOpenStorage.cpp:47
struct _FILE_INDEX_HEADER_V1 * PFILE_INDEX_HEADER_V1
Definition: CascOpenStorage.cpp:31
unsigned int DWORD
Definition: CascPort.h:139
uint32_t hashlittle(const void *key, size_t length, uint32_t initval)

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool IsCascIndexHeader_V2 ( LPBYTE  pbFileData,
DWORD  cbFileData 
)
static
149 {
150  PBLOCK_SIZE_AND_HASH pSizeAndHash = (PBLOCK_SIZE_AND_HASH)pbFileData;
151  unsigned int HashHigh = 0;
152  unsigned int HashLow = 0;
153 
154  // Check for the header
155  if(cbFileData < sizeof(BLOCK_SIZE_AND_HASH) || pSizeAndHash->cbBlockSize < 0x10)
156  return false;
157  if(cbFileData < pSizeAndHash->cbBlockSize + sizeof(BLOCK_SIZE_AND_HASH))
158  return false;
159 
160  // The index header for CASC v 2.0 begins with length and checksum
161  hashlittle2(pSizeAndHash + 1, pSizeAndHash->cbBlockSize, &HashHigh, &HashLow);
162  return (HashHigh == pSizeAndHash->dwBlockHash);
163 }
void hashlittle2(const void *key, size_t length, uint32_t *pc, uint32_t *pb)
Definition: CascOpenStorage.cpp:24
DWORD cbBlockSize
Definition: CascOpenStorage.cpp:26
struct _BLOCK_SIZE_AND_HASH * PBLOCK_SIZE_AND_HASH
DWORD dwBlockHash
Definition: CascOpenStorage.cpp:27

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static bool IsIndexFileName_V1 ( const TCHAR szFileName)
static
109 {
110  // Check if the name looks like a valid index file
111  return (_tcslen(szFileName) == 8 &&
112  _tcsnicmp(szFileName, _T("data.i"), 6) == 0 &&
113  _tcsspn(szFileName + 6, szAllowedHexChars) == 2);
114 }
#define _T(x)
Definition: CascPort.h:171
#define _tcslen
Definition: CascPort.h:172
#define _tcsnicmp
Definition: CascPort.h:188
static const TCHAR * szAllowedHexChars
Definition: CascOpenStorage.cpp:73
#define _tcsspn
Definition: CascPort.h:178

+ Here is the caller graph for this function:

static bool IsIndexFileName_V2 ( const TCHAR szFileName)
static
117 {
118  // Check if the name looks like a valid index file
119  return (_tcslen(szFileName) == 14 &&
120  _tcsspn(szFileName, _T("0123456789aAbBcCdDeEfF")) == 0x0A &&
121  _tcsicmp(szFileName + 0x0A, _T(".idx")) == 0);
122 }
#define _T(x)
Definition: CascPort.h:171
#define _tcslen
Definition: CascPort.h:172
#define _tcsicmp
Definition: CascPort.h:187
#define _tcsspn
Definition: CascPort.h:178

+ Here is the caller graph for this function:

TCascStorage* IsValidStorageHandle ( HANDLE  hStorage)
101 {
102  TCascStorage * hs = (TCascStorage *)hStorage;
103 
104  return (hs != NULL && hs->szClassName != NULL && !strcmp(hs->szClassName, "TCascStorage")) ? hs : NULL;
105 }
arena_t NULL
Definition: jemalloc_internal.h:624
Definition: CascCommon.h:186
const char * szClassName
Definition: CascCommon.h:188

+ Here is the caller graph for this function:

static int LoadEncodingFile ( TCascStorage hs)
static
766 {
767  PFILE_ENCODING_SEGMENT pEncodingSegment;
768  QUERY_KEY EncodingKey;
769  LPBYTE pbStartOfSegment;
770  LPBYTE pbEncodingFile = NULL;
771  HANDLE hFile = NULL;
772  DWORD cbEncodingFile = 0;
773  DWORD dwNumSegments = 0;
774  DWORD dwSegmentsPos = 0;
775  int nError = ERROR_SUCCESS;
776 
777  // Open the encoding file
778  EncodingKey.pbData = hs->EncodingKey.pbData + MD5_HASH_SIZE;
779  EncodingKey.cbData = MD5_HASH_SIZE;
780  if(!CascOpenFileByIndexKey((HANDLE)hs, &EncodingKey, 0, &hFile))
781  nError = GetLastError();
782 
783  // Load the entire ENCODING file to memory
784  if(nError == ERROR_SUCCESS)
785  {
786  // Load the necessary part of the ENCODING file to memory
787  pbEncodingFile = LoadEncodingFileToMemory(hFile, &cbEncodingFile);
788  if(pbEncodingFile == NULL || cbEncodingFile <= sizeof(CASC_ENCODING_HEADER))
789  nError = ERROR_FILE_CORRUPT;
790 
791  // Close the encoding file
792  CascCloseFile(hFile);
793  }
794 
795  // Verify all encoding segments
796  if(nError == ERROR_SUCCESS)
797  {
798  PCASC_ENCODING_HEADER pEncodingHeader = (PCASC_ENCODING_HEADER)pbEncodingFile;
799 
800  // Convert size and offset
801  dwNumSegments = ConvertBytesToInteger_4(pEncodingHeader->Entries_TableA);
802  dwSegmentsPos = ConvertBytesToInteger_4(pEncodingHeader->Size_StringTable1);
803 
804  // Store the encoding file to the CASC storage
805  hs->EncodingFile.pbData = pbEncodingFile;
806  hs->EncodingFile.cbData = cbEncodingFile;
807 
808  // Allocate the array of encoding segments
809  pEncodingSegment = (PFILE_ENCODING_SEGMENT)(pbEncodingFile + sizeof(CASC_ENCODING_HEADER) + dwSegmentsPos);
810  pbStartOfSegment = (LPBYTE)(pEncodingSegment + dwNumSegments);
811 
812  // Go through all encoding segments and verify them
813  for(DWORD i = 0; i < dwNumSegments; i++)
814  {
815  PCASC_ENCODING_ENTRY pEncodingEntry = (PCASC_ENCODING_ENTRY)pbStartOfSegment;
816 
817  // Check if there is enough space in the buffer
818  if((pbStartOfSegment + CASC_ENCODING_SEGMENT_SIZE) > (pbEncodingFile + cbEncodingFile))
819  {
820  nError = ERROR_FILE_CORRUPT;
821  break;
822  }
823 
824  // Check the hash of the entire segment
825  // Note that verifying takes considerable time of the storage loading
826 // if(!VerifyDataBlockHash(pbStartOfSegment, CASC_ENCODING_SEGMENT_SIZE, pEncodingSegment->SegmentHash))
827 // {
828 // nError = ERROR_FILE_CORRUPT;
829 // break;
830 // }
831 
832  // Check if the encoding key matches with the expected first value
833  if(memcmp(pEncodingEntry->EncodingKey, pEncodingSegment->FirstEncodingKey, MD5_HASH_SIZE))
834  {
835  nError = ERROR_FILE_CORRUPT;
836  break;
837  }
838 
839  // Move to the next segment
840  pbStartOfSegment += CASC_ENCODING_SEGMENT_SIZE;
841  pEncodingSegment++;
842  }
843  }
844 
845  // Create the map of the encoding keys
846  // Note that the array of encoding keys is already sorted - no need to sort it
847  if(nError == ERROR_SUCCESS)
848  {
849  pEncodingSegment = (PFILE_ENCODING_SEGMENT)(pbEncodingFile + sizeof(CASC_ENCODING_HEADER) + dwSegmentsPos);
850  nError = CreateMapOfEncodingKeys(hs, pEncodingSegment, dwNumSegments);
851  }
852 
853  return nError;
854 }
void * HANDLE
Definition: CascPort.h:146
#define ERROR_FILE_CORRUPT
Definition: CascPort.h:218
Definition: CascLib.h:138
arena_t NULL
Definition: jemalloc_internal.h:624
struct _FILE_ENCODING_SEGMENT * PFILE_ENCODING_SEGMENT
static LPBYTE LoadEncodingFileToMemory(HANDLE hFile, DWORD *pcbEncodingFile)
Definition: CascOpenStorage.cpp:673
#define CASC_ENCODING_SEGMENT_SIZE
Definition: CascOpenStorage.cpp:22
BYTE * LPBYTE
Definition: CascPort.h:152
bool WINAPI CascOpenFileByIndexKey(HANDLE hStorage, PQUERY_KEY pIndexKey, DWORD dwFlags, HANDLE *phFile)
Definition: CascOpenFile.cpp:150
static int CreateMapOfEncodingKeys(TCascStorage *hs, PFILE_ENCODING_SEGMENT pEncodingSegment, DWORD dwNumSegments)
Definition: CascOpenStorage.cpp:587
DWORD cbData
Definition: CascLib.h:141
#define MD5_HASH_SIZE
Definition: CascLib.h:105
struct _CASC_ENCODING_ENTRY * PCASC_ENCODING_ENTRY
struct _CASC_ENCODING_HEADER * PCASC_ENCODING_HEADER
LPBYTE pbData
Definition: CascLib.h:140
QUERY_KEY EncodingKey
Definition: CascCommon.h:212
unsigned int DWORD
Definition: CascPort.h:139
BYTE Entries_TableA[4]
Definition: CascCommon.h:152
BYTE EncodingKey[MD5_HASH_SIZE]
Definition: CascCommon.h:163
int GetLastError()
Definition: Common.cpp:70
bool WINAPI CascCloseFile(HANDLE hFile)
Definition: CascOpenFile.cpp:273
Definition: CascOpenStorage.cpp:63
Definition: CascCommon.h:144
Definition: CascCommon.h:159
BYTE Size_StringTable1[4]
Definition: CascCommon.h:155
DWORD ConvertBytesToInteger_4(LPBYTE ValueAsBytes)
Definition: CascCommon.cpp:31
BYTE FirstEncodingKey[MD5_HASH_SIZE]
Definition: CascOpenStorage.cpp:65
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static LPBYTE LoadEncodingFileToMemory ( HANDLE  hFile,
DWORD pcbEncodingFile 
)
static
674 {
675  CASC_ENCODING_HEADER EncodingHeader;
676  LPBYTE pbEncodingFile = NULL;
677  DWORD cbEncodingFile = 0;
678  DWORD dwSegmentPos = 0;
679  DWORD dwNumSegments = 0;
680  DWORD dwBytesRead = 0;
681  int nError = ERROR_BAD_FORMAT;
682 
683  // Read the encoding header
684  CascReadFile(hFile, &EncodingHeader, sizeof(CASC_ENCODING_HEADER), &dwBytesRead);
685  if(dwBytesRead == sizeof(CASC_ENCODING_HEADER))
686  {
687  // Check the version and sizes
688  if(EncodingHeader.Version != 0x01 || EncodingHeader.ChecksumSizeA != MD5_HASH_SIZE || EncodingHeader.ChecksumSizeB != MD5_HASH_SIZE)
689  {
690  assert(false);
691  return NULL;
692  }
693 
694  // Get the number of segments
695  dwNumSegments = ConvertBytesToInteger_4(EncodingHeader.Entries_TableA);
696  dwSegmentPos = ConvertBytesToInteger_4(EncodingHeader.Size_StringTable1);
697  if(EncodingHeader.Magic[0] == 'E' && EncodingHeader.Magic[1] == 'N' && dwSegmentPos != 0 && dwNumSegments != 0)
698  nError = ERROR_SUCCESS;
699  }
700 
701  // Calculate and allocate space for the entire file
702  if(nError == ERROR_SUCCESS)
703  {
704  cbEncodingFile = sizeof(CASC_ENCODING_HEADER) +
705  dwSegmentPos +
706  dwNumSegments * (sizeof(FILE_ENCODING_SEGMENT) + CASC_ENCODING_SEGMENT_SIZE);
707  pbEncodingFile = CASC_ALLOC(BYTE, cbEncodingFile);
708  if(pbEncodingFile == NULL)
709  nError = ERROR_NOT_ENOUGH_MEMORY;
710  }
711 
712  // If all went OK, we load the entire file to memory
713  if(nError == ERROR_SUCCESS)
714  {
715  // Copy the header itself
716  memcpy(pbEncodingFile, &EncodingHeader, sizeof(CASC_ENCODING_HEADER));
717 
718  // Read the rest of the data
719  CascReadFile(hFile, pbEncodingFile + sizeof(CASC_ENCODING_HEADER), cbEncodingFile - sizeof(CASC_ENCODING_HEADER), &dwBytesRead);
720  if(dwBytesRead != (cbEncodingFile - sizeof(CASC_ENCODING_HEADER)))
721  nError = ERROR_FILE_CORRUPT;
722  }
723 
724  // Give the loaded file length
725  if(pcbEncodingFile != NULL)
726  *pcbEncodingFile = cbEncodingFile;
727  return pbEncodingFile;
728 }
BYTE ChecksumSizeA
Definition: CascCommon.h:148
BYTE ChecksumSizeB
Definition: CascCommon.h:149
#define CASC_ALLOC(type, count)
Definition: CascCommon.h:302
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
#define ERROR_FILE_CORRUPT
Definition: CascPort.h:218
arena_t NULL
Definition: jemalloc_internal.h:624
#define CASC_ENCODING_SEGMENT_SIZE
Definition: CascOpenStorage.cpp:22
BYTE Magic[2]
Definition: CascCommon.h:146
BYTE * LPBYTE
Definition: CascPort.h:152
#define MD5_HASH_SIZE
Definition: CascLib.h:105
BYTE Version
Definition: CascCommon.h:147
unsigned int DWORD
Definition: CascPort.h:139
BYTE Entries_TableA[4]
Definition: CascCommon.h:152
Definition: CascOpenStorage.cpp:63
bool WINAPI CascReadFile(HANDLE hFile, void *lpBuffer, DWORD dwToRead, PDWORD pdwRead)
Definition: CascReadFile.cpp:459
Definition: CascCommon.h:144
#define ERROR_BAD_FORMAT
Definition: CascPort.h:214
BYTE Size_StringTable1[4]
Definition: CascCommon.h:155
unsigned char BYTE
Definition: CascPort.h:136
DWORD ConvertBytesToInteger_4(LPBYTE ValueAsBytes)
Definition: CascCommon.cpp:31
struct _CASC_ENCODING_HEADER CASC_ENCODING_HEADER
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int LoadIndexFiles ( TCascStorage hs)
static
639 {
640  DWORD IndexArray[CASC_INDEX_COUNT];
641  DWORD OldIndexArray[CASC_INDEX_COUNT];
642  int nError;
643  int i;
644 
645  // Scan all index files
646  memset(IndexArray, 0, sizeof(IndexArray));
647  memset(OldIndexArray, 0, sizeof(OldIndexArray));
648  nError = ScanIndexDirectory(hs->szIndexPath, IndexDirectory_OnFileFound, IndexArray, OldIndexArray, hs);
649  if(nError == ERROR_SUCCESS)
650  {
651  // Load each index file
652  for(i = 0; i < CASC_INDEX_COUNT; i++)
653  {
654  hs->KeyMapping[i].szFileName = CreateIndexFileName(hs, i, IndexArray[i]);
655  if(hs->KeyMapping[i].szFileName != NULL)
656  {
657  nError = LoadKeyMapping(&hs->KeyMapping[i], i);
658  if(nError != ERROR_SUCCESS)
659  break;
660  }
661  }
662  }
663 
664  // Now we need to build the map of the index entries
665  if(nError == ERROR_SUCCESS)
666  {
667  nError = CreateArrayOfIndexEntries(hs);
668  }
669 
670  return nError;
671 }
CASC_MAPPING_TABLE KeyMapping[CASC_INDEX_COUNT]
Definition: CascCommon.h:216
arena_t NULL
Definition: jemalloc_internal.h:624
int ScanIndexDirectory(const TCHAR *szIndexPath, INDEX_FILE_FOUND pfnOnFileFound, PDWORD IndexArray, PDWORD OldIndexArray, void *pvContext)
Definition: Directory.cpp:41
#define CASC_INDEX_COUNT
Definition: CascCommon.h:50
static int CreateArrayOfIndexEntries(TCascStorage *hs)
Definition: CascOpenStorage.cpp:543
TCHAR * szFileName
Definition: CascCommon.h:111
static int LoadKeyMapping(PCASC_MAPPING_TABLE pKeyMapping, DWORD KeyIndex)
Definition: CascOpenStorage.cpp:495
TCHAR * szIndexPath
Definition: CascCommon.h:193
unsigned int DWORD
Definition: CascPort.h:139
static bool IndexDirectory_OnFileFound(const TCHAR *szFileName, PDWORD IndexArray, PDWORD OldIndexArray, void *pvContext)
Definition: CascOpenStorage.cpp:260
static TCHAR * CreateIndexFileName(TCascStorage *hs, DWORD IndexValue, DWORD IndexVersion)
Definition: CascOpenStorage.cpp:334
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int LoadKeyMapping ( PCASC_MAPPING_TABLE  pKeyMapping,
DWORD  KeyIndex 
)
static
496 {
497  TFileStream * pStream;
498  ULONGLONG FileSize = 0;
499  int nError = ERROR_SUCCESS;
500 
501  // Sanity checks
502  assert(pKeyMapping->szFileName != NULL && pKeyMapping->szFileName[0] != 0);
503 
504  // Open the stream for read-only access and read the file
506  if(pStream != NULL)
507  {
508  // Retrieve the file size
509  FileStream_GetSize(pStream, &FileSize);
510  if(0 < FileSize && FileSize <= 0x100000)
511  {
512  // WoW6 actually reads THE ENTIRE file to memory
513  // Verified on Mac build (x64)
514  pKeyMapping->pbFileData = CASC_ALLOC(BYTE, (DWORD)FileSize);
515  pKeyMapping->cbFileData = (DWORD)FileSize;
516 
517  // Load the data to memory and parse it
518  if(pKeyMapping->pbFileData != NULL)
519  {
520  if(FileStream_Read(pStream, NULL, pKeyMapping->pbFileData, pKeyMapping->cbFileData))
521  {
522  nError = VerifyAndParseKeyMapping(pKeyMapping, KeyIndex);
523  }
524  }
525  else
526  nError = ERROR_NOT_ENOUGH_MEMORY;
527  }
528  else
529  {
530  assert(false);
531  nError = ERROR_BAD_FORMAT;
532  }
533 
534  // Close the file stream
535  FileStream_Close(pStream);
536  }
537  else
538  nError = GetLastError();
539 
540  return ERROR_SUCCESS;
541 }
#define CASC_ALLOC(type, count)
Definition: CascCommon.h:302
unsigned long long ULONGLONG
Definition: CascPort.h:144
bool FileStream_Read(TFileStream *pStream, ULONGLONG *pByteOffset, void *pvBuffer, DWORD dwBytesToRead)
Definition: FileStream.cpp:2551
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
bool FileStream_GetSize(TFileStream *pStream, ULONGLONG *pFileSize)
Definition: FileStream.cpp:2595
arena_t NULL
Definition: jemalloc_internal.h:624
LPBYTE pbFileData
Definition: CascCommon.h:112
TCHAR * szFileName
Definition: CascCommon.h:111
static int VerifyAndParseKeyMapping(PCASC_MAPPING_TABLE pKeyMapping, DWORD KeyIndex)
Definition: CascOpenStorage.cpp:476
DWORD cbFileData
Definition: CascCommon.h:113
#define STREAM_PROVIDER_FLAT
Definition: CascLib.h:50
void FileStream_Close(TFileStream *pStream)
Definition: FileStream.cpp:2707
unsigned int DWORD
Definition: CascPort.h:139
TFileStream * FileStream_OpenFile(const TCHAR *szFileName, DWORD dwStreamFlags)
Definition: FileStream.cpp:2384
int GetLastError()
Definition: Common.cpp:70
#define BASE_PROVIDER_FILE
Definition: CascLib.h:45
Definition: FileStream.h:153
#define ERROR_BAD_FORMAT
Definition: CascPort.h:214
unsigned char BYTE
Definition: CascPort.h:136
#define STREAM_FLAG_READ_ONLY
Definition: CascLib.h:56
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int LoadRootFile ( TCascStorage hs,
DWORD  dwLocaleMask 
)
static
857 {
858  PDWORD FileSignature;
859  HANDLE hFile = NULL;
860  LPBYTE pbRootFile = NULL;
861  DWORD cbRootFile = 0;
862  int nError = ERROR_SUCCESS;
863 
864  // Sanity checks
865  assert(hs->pEncodingMap != NULL);
866  assert(hs->pRootHandler == NULL);
867 
868  // Locale: The default parameter is 0 - in that case,
869  // we assign the default locale, loaded from the .build.info file
870  if(dwLocaleMask == 0)
871  dwLocaleMask = hs->dwDefaultLocale;
872 
873  // Load the entire ROOT file to memory
874  if(!CascOpenFileByEncodingKey((HANDLE)hs, &hs->RootKey, 0, &hFile))
875  nError = GetLastError();
876 
877  // Load the entire file to memory
878  if(nError == ERROR_SUCCESS)
879  {
880  pbRootFile = LoadRootFileToMemory(hFile, &cbRootFile);
881  CascCloseFile(hFile);
882  }
883 
884  // Check if the version of the ROOT file
885  if(nError == ERROR_SUCCESS && pbRootFile != NULL)
886  {
887  FileSignature = (PDWORD)pbRootFile;
888  switch(FileSignature[0])
889  {
891  nError = RootHandler_CreateMNDX(hs, pbRootFile, cbRootFile);
892  break;
893 
895  nError = RootHandler_CreateDiablo3(hs, pbRootFile, cbRootFile);
896  break;
897 
899  nError = RootHandler_CreateOverwatch(hs, pbRootFile, cbRootFile);
900  break;
901 
902  default:
903  nError = RootHandler_CreateWoW6(hs, pbRootFile, cbRootFile, dwLocaleMask);
904  break;
905  }
906  }
907 
908  // Insert entry for the
909  if(nError == ERROR_SUCCESS)
910  {
911  InsertExtraFile(hs, "ENCODING", &hs->EncodingKey);
912  InsertExtraFile(hs, "ROOT", &hs->RootKey);
913  InsertExtraFile(hs, "DOWNLOAD", &hs->DownloadKey);
914  InsertExtraFile(hs, "INSTALL", &hs->InstallKey);
915  }
916 
917 #ifdef _DEBUG
918  if(nError == ERROR_SUCCESS)
919  {
920  //RootFile_Dump(hs,
921  // pbRootFile,
922  // cbRootFile,
923  // _T("\\casc_root_%build%.txt"),
924  // _T("\\Ladik\\Appdir\\CascLib\\listfile\\listfile-wow6.txt"),
925  // DUMP_LEVEL_INDEX_ENTRIES);
926  }
927 #endif
928 
929  // Free the root file
930  CASC_FREE(pbRootFile);
931  return nError;
932 }
TRootHandler * pRootHandler
Definition: CascCommon.h:223
QUERY_KEY RootKey
Definition: CascCommon.h:208
DWORD dwDefaultLocale
Definition: CascCommon.h:199
void * HANDLE
Definition: CascPort.h:146
DWORD * PDWORD
Definition: CascPort.h:151
int RootHandler_CreateMNDX(TCascStorage *hs, LPBYTE pbRootFile, DWORD cbRootFile)
Definition: CascRootFile_Mndx.cpp:3139
arena_t NULL
Definition: jemalloc_internal.h:624
#define CASC_DIABLO3_ROOT_SIGNATURE
Definition: RootHandler.h:18
int RootHandler_CreateWoW6(TCascStorage *hs, LPBYTE pbRootFile, DWORD cbRootFile, DWORD dwLocaleMask)
Definition: CascRootFile_WoW6.cpp:487
BYTE * LPBYTE
Definition: CascPort.h:152
static int InsertExtraFile(TCascStorage *hs, const char *szFileName, PQUERY_KEY pQueryKey)
Definition: CascOpenStorage.cpp:181
static LPBYTE LoadRootFileToMemory(HANDLE hFile, DWORD *pcbRootFile)
Definition: CascOpenStorage.cpp:730
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
int RootHandler_CreateDiablo3(TCascStorage *hs, LPBYTE pbRootFile, DWORD cbRootFile)
Definition: CascRootFile_Diablo3.cpp:1079
int RootHandler_CreateOverwatch(TCascStorage *hs, LPBYTE pbRootFile, DWORD cbRootFile)
Definition: CascRootFile_Ovr.cpp:133
PCASC_MAP pEncodingMap
Definition: CascCommon.h:220
unsigned int DWORD
Definition: CascPort.h:139
#define CASC_MNDX_ROOT_SIGNATURE
Definition: RootHandler.h:17
int GetLastError()
Definition: Common.cpp:70
bool WINAPI CascCloseFile(HANDLE hFile)
Definition: CascOpenFile.cpp:273
bool WINAPI CascOpenFileByEncodingKey(HANDLE hStorage, PQUERY_KEY pEncodingKey, DWORD dwFlags, HANDLE *phFile)
Definition: CascOpenFile.cpp:173
#define CASC_OVERWATCH_ROOT_SIGNATURE
Definition: RootHandler.h:19
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static LPBYTE LoadRootFileToMemory ( HANDLE  hFile,
DWORD pcbRootFile 
)
static
731 {
732  LPBYTE pbRootFile = NULL;
733  DWORD cbRootFile = 0;
734  DWORD dwBytesRead = 0;
735  int nError = ERROR_SUCCESS;
736 
737  // Retrieve the size of the ROOT file
738  cbRootFile = CascGetFileSize(hFile, NULL);
739  if(cbRootFile == 0)
740  nError = ERROR_BAD_FORMAT;
741 
742  // Allocate space for the entire file
743  if(nError == ERROR_SUCCESS)
744  {
745  pbRootFile = CASC_ALLOC(BYTE, cbRootFile);
746  if(pbRootFile == NULL)
747  nError = ERROR_NOT_ENOUGH_MEMORY;
748  }
749 
750  // If all went OK, we load the entire file to memory
751  if(nError == ERROR_SUCCESS)
752  {
753  // Read the entire file to memory
754  CascReadFile(hFile, pbRootFile, cbRootFile, &dwBytesRead);
755  if(dwBytesRead != cbRootFile)
756  nError = ERROR_FILE_CORRUPT;
757  }
758 
759  // Give the loaded file length
760  if(pcbRootFile != NULL)
761  *pcbRootFile = cbRootFile;
762  return pbRootFile;
763 }
#define CASC_ALLOC(type, count)
Definition: CascCommon.h:302
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
#define ERROR_FILE_CORRUPT
Definition: CascPort.h:218
arena_t NULL
Definition: jemalloc_internal.h:624
BYTE * LPBYTE
Definition: CascPort.h:152
DWORD WINAPI CascGetFileSize(HANDLE hFile, PDWORD pdwFileSizeHigh)
Definition: CascReadFile.cpp:367
unsigned int DWORD
Definition: CascPort.h:139
bool WINAPI CascReadFile(HANDLE hFile, void *lpBuffer, DWORD dwToRead, PDWORD pdwRead)
Definition: CascReadFile.cpp:459
#define ERROR_BAD_FORMAT
Definition: CascPort.h:214
unsigned char BYTE
Definition: CascPort.h:136
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int VerifyAndParseKeyMapping ( PCASC_MAPPING_TABLE  pKeyMapping,
DWORD  KeyIndex 
)
static
477 {
478  // Sanity checks
479  assert(pKeyMapping->pbFileData != NULL);
480  assert(pKeyMapping->cbFileData != 0);
481 
482  // Check for CASC version 2
483  if(IsCascIndexHeader_V2(pKeyMapping->pbFileData, pKeyMapping->cbFileData))
484  return VerifyAndParseKeyMapping_V2(pKeyMapping, KeyIndex);
485 
486  // Check for CASC version 1
487  if(IsCascIndexHeader_V1(pKeyMapping->pbFileData, pKeyMapping->cbFileData))
488  return VerifyAndParseKeyMapping_V1(pKeyMapping, KeyIndex);
489 
490  // Unknown CASC version
491  assert(false);
492  return ERROR_BAD_FORMAT;
493 }
static bool IsCascIndexHeader_V1(LPBYTE pbFileData, DWORD cbFileData)
Definition: CascOpenStorage.cpp:124
arena_t NULL
Definition: jemalloc_internal.h:624
static bool IsCascIndexHeader_V2(LPBYTE pbFileData, DWORD cbFileData)
Definition: CascOpenStorage.cpp:148
LPBYTE pbFileData
Definition: CascCommon.h:112
static int VerifyAndParseKeyMapping_V1(PCASC_MAPPING_TABLE pKeyMapping, DWORD KeyIndex)
Definition: CascOpenStorage.cpp:348
static int VerifyAndParseKeyMapping_V2(PCASC_MAPPING_TABLE pKeyMapping, DWORD KeyIndex)
Definition: CascOpenStorage.cpp:389
DWORD cbFileData
Definition: CascCommon.h:113
#define ERROR_BAD_FORMAT
Definition: CascPort.h:214

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int VerifyAndParseKeyMapping_V1 ( PCASC_MAPPING_TABLE  pKeyMapping,
DWORD  KeyIndex 
)
static
349 {
350  PFILE_INDEX_HEADER_V1 pIndexHeader = (PFILE_INDEX_HEADER_V1)pKeyMapping->pbFileData;
351  DWORD dwDataHash1;
352  DWORD dwDataHash2;
353 
354  // Verify the format
355  if(pIndexHeader->field_0 != 0x0005)
356  return ERROR_NOT_SUPPORTED;
357  if(pIndexHeader->KeyIndex != KeyIndex)
358  return ERROR_NOT_SUPPORTED;
359  if(pIndexHeader->field_8 == 0)
360  return ERROR_NOT_SUPPORTED;
361 
362  // Verofy the bit counts
363  if(pIndexHeader->SpanSizeBytes != 0x04 ||
364  pIndexHeader->SpanOffsBytes != 0x05 ||
365  pIndexHeader->KeyBytes != 0x09)
366  return ERROR_NOT_SUPPORTED;
367 
368  pKeyMapping->ExtraBytes = 0;
369  pKeyMapping->SpanSizeBytes = pIndexHeader->SpanSizeBytes;
370  pKeyMapping->SpanOffsBytes = pIndexHeader->SpanOffsBytes;
371  pKeyMapping->KeyBytes = pIndexHeader->KeyBytes;
372  pKeyMapping->SegmentBits = pIndexHeader->SegmentBits;
373  pKeyMapping->MaxFileOffset = pIndexHeader->MaxFileOffset;
374 
375  // Get the pointer to the key entry array
376  pKeyMapping->nIndexEntries = pIndexHeader->KeyCount1 + pIndexHeader->KeyCount2;
377  if(pKeyMapping->nIndexEntries != 0)
378  pKeyMapping->pIndexEntries = (PCASC_INDEX_ENTRY)(pKeyMapping->pbFileData + sizeof(FILE_INDEX_HEADER_V1));
379 
380  // Verify hashes
381  dwDataHash1 = hashlittle(pKeyMapping->pIndexEntries, pIndexHeader->KeyCount1 * sizeof(CASC_INDEX_ENTRY), 0);
382  dwDataHash2 = hashlittle(pKeyMapping->pIndexEntries + pIndexHeader->KeyCount1, pIndexHeader->KeyCount2 * sizeof(CASC_INDEX_ENTRY), 0);
383  if(dwDataHash1 != pIndexHeader->KeysHash1 || dwDataHash2 != pIndexHeader->KeysHash2)
384  return ERROR_FILE_CORRUPT;
385 
386  return ERROR_SUCCESS;
387 }
BYTE SpanSizeBytes
Definition: CascCommon.h:115
USHORT field_0
Definition: CascOpenStorage.cpp:33
BYTE SegmentBits
Definition: CascCommon.h:118
BYTE KeyBytes
Definition: CascCommon.h:117
ULONGLONG MaxFileOffset
Definition: CascCommon.h:119
#define ERROR_FILE_CORRUPT
Definition: CascPort.h:218
DWORD KeysHash1
Definition: CascOpenStorage.cpp:45
BYTE SpanOffsBytes
Definition: CascOpenStorage.cpp:40
LPBYTE pbFileData
Definition: CascCommon.h:112
struct _CASC_INDEX_ENTRY * PCASC_INDEX_ENTRY
PCASC_INDEX_ENTRY pIndexEntries
Definition: CascCommon.h:121
ULONGLONG field_8
Definition: CascOpenStorage.cpp:37
BYTE SpanOffsBytes
Definition: CascCommon.h:116
DWORD nIndexEntries
Definition: CascCommon.h:122
ULONGLONG MaxFileOffset
Definition: CascOpenStorage.cpp:38
BYTE KeyBytes
Definition: CascOpenStorage.cpp:41
BYTE SegmentBits
Definition: CascOpenStorage.cpp:42
struct _FILE_INDEX_HEADER_V1 * PFILE_INDEX_HEADER_V1
Definition: CascOpenStorage.cpp:31
DWORD KeyCount1
Definition: CascOpenStorage.cpp:43
unsigned int DWORD
Definition: CascPort.h:139
DWORD KeysHash2
Definition: CascOpenStorage.cpp:46
Definition: CascCommon.h:102
BYTE KeyIndex
Definition: CascOpenStorage.cpp:34
DWORD KeyCount2
Definition: CascOpenStorage.cpp:44
#define ERROR_NOT_SUPPORTED
Definition: CascPort.h:209
BYTE SpanSizeBytes
Definition: CascOpenStorage.cpp:39
uint32_t hashlittle(const void *key, size_t length, uint32_t initval)
#define ERROR_SUCCESS
Definition: CascPort.h:204
BYTE ExtraBytes
Definition: CascCommon.h:114

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int VerifyAndParseKeyMapping_V2 ( PCASC_MAPPING_TABLE  pKeyMapping,
DWORD  KeyIndex 
)
static
390 {
391  PFILE_INDEX_HEADER_V2 pIndexHeader = (PFILE_INDEX_HEADER_V2)pKeyMapping->pbFileData;
392  PBLOCK_SIZE_AND_HASH pSizeAndHash;
393  LPBYTE pbLastPartEnd;
394  LPBYTE pbLastPart;
395  DWORD FilePosition;
396  DWORD LastPartLength;
397  unsigned int HashHigh = 0;
398  unsigned int HashLow = 0;
399 
400  // The index header v2 begins after the SizeAndHash
401  pSizeAndHash = (PBLOCK_SIZE_AND_HASH)pKeyMapping->pbFileData;
402  pIndexHeader = (PFILE_INDEX_HEADER_V2)(pSizeAndHash + 1);
403  if(pIndexHeader->IndexVersion != 0x07 || pIndexHeader->KeyIndex != KeyIndex)
404  return ERROR_BAD_FORMAT;
405 
406  if(pIndexHeader->ExtraBytes != 0x00 ||
407  pIndexHeader->SpanSizeBytes != 0x04 ||
408  pIndexHeader->SpanOffsBytes != 0x05 ||
409  pIndexHeader->KeyBytes != CASC_FILE_KEY_SIZE)
410  return ERROR_BAD_FORMAT;
411 
412  // Remember the sizes
413  pKeyMapping->ExtraBytes = pIndexHeader->ExtraBytes;
414  pKeyMapping->SpanSizeBytes = pIndexHeader->SpanSizeBytes;
415  pKeyMapping->SpanOffsBytes = pIndexHeader->SpanOffsBytes;
416  pKeyMapping->KeyBytes = pIndexHeader->KeyBytes;
417  pKeyMapping->SegmentBits = pIndexHeader->SegmentBits;
418  pKeyMapping->MaxFileOffset = pIndexHeader->MaxFileOffset;
419 
420  // Get the data position
421  FilePosition = (sizeof(BLOCK_SIZE_AND_HASH) + pSizeAndHash->cbBlockSize + 0x0F) & 0xFFFFFFF0;
422  if((FilePosition + 0x08) > pKeyMapping->cbFileData)
423  return ERROR_BAD_FORMAT;
424 
425  // Get the pointer to "size+hash" block
426  pSizeAndHash = (PBLOCK_SIZE_AND_HASH)(pKeyMapping->pbFileData + FilePosition);
427  FilePosition += 0x08;
428 
429  if((FilePosition + pSizeAndHash->cbBlockSize) > pKeyMapping->cbFileData)
430  return ERROR_BAD_FORMAT;
431  if(pSizeAndHash->cbBlockSize < sizeof(CASC_INDEX_ENTRY))
432  return ERROR_BAD_FORMAT;
433 
434  // Remember the array of file keys
435  pKeyMapping->pIndexEntries = (PCASC_INDEX_ENTRY)(pKeyMapping->pbFileData + FilePosition);
436  pKeyMapping->nIndexEntries = pSizeAndHash->cbBlockSize / sizeof(CASC_INDEX_ENTRY);
437  FilePosition += pSizeAndHash->cbBlockSize;
438 
439  // Verify the integrity of the key array
440  for(DWORD i = 0; i < pKeyMapping->nIndexEntries; i++)
441  hashlittle2(pKeyMapping->pIndexEntries + i, sizeof(CASC_INDEX_ENTRY), &HashHigh, &HashLow);
442  if(HashHigh != pSizeAndHash->dwBlockHash)
443  return ERROR_BAD_FORMAT;
444 
445  // Align the data position up to next 0x1000
446  FilePosition = ALIGN_TO_SIZE(FilePosition, 0x1000);
447  if(FilePosition > pKeyMapping->cbFileData)
448  return ERROR_BAD_FORMAT;
449 
450  LastPartLength = pKeyMapping->cbFileData - FilePosition;
451  if(LastPartLength < 0x7800)
452  return ERROR_BAD_FORMAT;
453 
454  pbLastPart = pKeyMapping->pbFileData + FilePosition;
455  pbLastPartEnd = pbLastPart + ((LastPartLength >> 0x09) << 0x09);
456 
457  while(pbLastPart < pbLastPartEnd)
458  {
459  for(int i = 0; i < 0x1F8; i += 0x18)
460  {
461  PDWORD PtrLastPart = (PDWORD)pbLastPart;
462  if(PtrLastPart[0] == 0)
463  return ERROR_SUCCESS;
464 
465  HashLow = hashlittle(PtrLastPart + i, 0x13, 0) | 0x80000000;
466  if(HashLow != PtrLastPart[0])
467  return ERROR_BAD_FORMAT;
468  }
469 
470  pbLastPart += 0x200;
471  }
472 
473  return ERROR_SUCCESS;
474 }
void hashlittle2(const void *key, size_t length, uint32_t *pc, uint32_t *pb)
BYTE SpanSizeBytes
Definition: CascCommon.h:115
DWORD * PDWORD
Definition: CascPort.h:151
BYTE SegmentBits
Definition: CascCommon.h:118
Definition: CascOpenStorage.cpp:24
BYTE KeyBytes
Definition: CascCommon.h:117
ULONGLONG MaxFileOffset
Definition: CascCommon.h:119
BYTE ExtraBytes
Definition: CascOpenStorage.cpp:54
#define ALIGN_TO_SIZE(x, a)
Definition: Common.h:21
struct _BLOCK_SIZE_AND_HASH BLOCK_SIZE_AND_HASH
LPBYTE pbFileData
Definition: CascCommon.h:112
struct _CASC_INDEX_ENTRY * PCASC_INDEX_ENTRY
PCASC_INDEX_ENTRY pIndexEntries
Definition: CascCommon.h:121
BYTE * LPBYTE
Definition: CascPort.h:152
BYTE SpanOffsBytes
Definition: CascCommon.h:116
BYTE KeyIndex
Definition: CascOpenStorage.cpp:53
DWORD nIndexEntries
Definition: CascCommon.h:122
struct _BLOCK_SIZE_AND_HASH * PBLOCK_SIZE_AND_HASH
struct _CASC_INDEX_ENTRY CASC_INDEX_ENTRY
BYTE SegmentBits
Definition: CascOpenStorage.cpp:58
DWORD cbFileData
Definition: CascCommon.h:113
unsigned int DWORD
Definition: CascPort.h:139
Definition: CascCommon.h:102
BYTE KeyBytes
Definition: CascOpenStorage.cpp:57
BYTE SpanOffsBytes
Definition: CascOpenStorage.cpp:56
#define CASC_FILE_KEY_SIZE
Definition: CascCommon.h:51
Definition: CascOpenStorage.cpp:50
struct _FILE_INDEX_HEADER_V2 * PFILE_INDEX_HEADER_V2
#define ERROR_BAD_FORMAT
Definition: CascPort.h:214
BYTE SpanSizeBytes
Definition: CascOpenStorage.cpp:55
uint32_t hashlittle(const void *key, size_t length, uint32_t initval)
USHORT IndexVersion
Definition: CascOpenStorage.cpp:52
#define ERROR_SUCCESS
Definition: CascPort.h:204
BYTE ExtraBytes
Definition: CascCommon.h:114
ULONGLONG MaxFileOffset
Definition: CascOpenStorage.cpp:59

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

Variable Documentation

const TCHAR* szAllowedHexChars = _T("0123456789aAbBcCdDeEfF")
static
const TCHAR* szIndexFormat_V1 = _T("data.i%x%x")
static
const TCHAR* szIndexFormat_V2 = _T("%02x%08x.idx")
static