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

Classes

struct  _DIABLO3_FILEID1_ENTRY
 
struct  _DIABLO3_FILEID2_ENTRY
 
struct  _DIABLO3_NAMED_ENTRY
 
struct  _DIABLO3_CORE_TOC_HEADER
 
struct  _DIABLO3_CORE_TOC_ENTRY
 
struct  _DIABLO3_DIR_HEADER
 
struct  _DIABLO3_CORE_TOC
 
struct  _DIABLO3_PACKAGES_DAT_HEADER
 
struct  _DIABLO3_ASSET_INFO
 
struct  _CASC_FILE_ENTRY
 
struct  TRootHandler_Diablo3
 

Macros

#define __CASCLIB_SELF__
 
#define DIABLO3_SUBDIR_SIGNATURE   0xEAF1FE87
 
#define DIABLO3_PACKAGES_SIGNATURE   0xAABB0002
 
#define DIABLO3_MAX_SUBDIRS   0x20
 
#define DIABLO3_INVALID_INDEX   0xFFFFFFFF
 
#define DIABLO3_INVALID_FILE   0xFFFFFFFF
 
#define DIABLO3_MAX_ASSETS   70
 
#define DIABLO3_MAX_LEVEL0_LENGTH   0x10
 
#define INVALID_FILE_INDEX   0xFFFFFFFF
 
#define INVALID_ASSET_INDEX   0xFF
 
#define ENTRY_FLAG_DIRECTORY_ENTRY   0x80
 
#define ENTRY_FLAG_PLAIN_NAME   0x01
 
#define ENTRY_FLAG_FULL_NAME   0x02
 
#define ENTRY_FLAG_FLAGS_MASK   0xF0
 
#define ENTRY_FLAG_NAME_MASK   0x0F
 
#define CASC_ENTRY_SHORT_NAME   0x000000001
 
#define CASC_ENTRY_HAS_SUBINDEX   0x000000002
 
#define SEARCH_PHASE_NAMES   0
 
#define SEARCH_PHASE_FILE_IDS   1
 
#define MAKE_INDEX64(ri, fi, si)   (((ULONGLONG)ri << 0x38) | ((ULONGLONG)fi << 0x18) | ((ULONGLONG)si))
 
#define INDEX64_ROOT_INDEX(hash)   (DWORD)((hash >> 0x38) & 0x000000FF)
 
#define INDEX64_FILE_INDEX(hash)   (DWORD)((hash >> 0x18) & 0xFFFFFFFF)
 
#define INDEX64_SUB_INDEX(hash)   (DWORD)((hash >> 0x00) & 0x00FFFFFF)
 
#define DIABLO3_ASSET_COUNT   (sizeof(Assets) / sizeof(Assets[0]))
 

Typedefs

typedef struct
_DIABLO3_FILEID1_ENTRY 
DIABLO3_FILEID1_ENTRY
 
typedef struct
_DIABLO3_FILEID1_ENTRY
PDIABLO3_FILEID1_ENTRY
 
typedef struct
_DIABLO3_FILEID2_ENTRY 
DIABLO3_FILEID2_ENTRY
 
typedef struct
_DIABLO3_FILEID2_ENTRY
PDIABLO3_FILEID2_ENTRY
 
typedef struct _DIABLO3_NAMED_ENTRY DIABLO3_NAMED_ENTRY
 
typedef struct
_DIABLO3_NAMED_ENTRY
PDIABLO3_NAMED_ENTRY
 
typedef struct
_DIABLO3_CORE_TOC_HEADER 
DIABLO3_CORE_TOC_HEADER
 
typedef struct
_DIABLO3_CORE_TOC_HEADER
PDIABLO3_CORE_TOC_HEADER
 
typedef struct
_DIABLO3_CORE_TOC_ENTRY 
DIABLO3_CORE_TOC_ENTRY
 
typedef struct
_DIABLO3_CORE_TOC_ENTRY
PDIABLO3_CORE_TOC_ENTRY
 
typedef struct _DIABLO3_DIR_HEADER DIABLO3_DIR_HEADER
 
typedef struct
_DIABLO3_DIR_HEADER
PDIABLO3_DIR_HEADER
 
typedef struct _DIABLO3_CORE_TOC DIABLO3_CORE_TOC
 
typedef struct _DIABLO3_CORE_TOCPDIABLO3_CORE_TOC
 
typedef struct
_DIABLO3_PACKAGES_DAT_HEADER 
DIABLO3_PACKAGES_DAT_HEADER
 
typedef struct
_DIABLO3_PACKAGES_DAT_HEADER
PDIABLO3_PACKAGES_DAT_HEADER
 
typedef struct _DIABLO3_ASSET_INFO DIABLO3_ASSET_INFO
 
typedef const DIABLO3_ASSET_INFOPDIABLO3_ASSET_INFO
 
typedef struct _CASC_FILE_ENTRY CASC_FILE_ENTRY
 
typedef struct _CASC_FILE_ENTRYPCASC_FILE_ENTRY
 

Functions

static PDIABLO3_ASSET_INFO GetAssetInfo (DWORD dwAssetIndex)
 
static DWORD VerifyNamedFileEntry (LPBYTE pbNamedEntry, LPBYTE pbFileEnd)
 
static char * FindPackageName (PCASC_MAP pPackageMap, const char *szAssetName, const char *szPlainName)
 
static size_t CreateShortName (PCASC_MAP pPackageMap, DWORD dwRootIndex, DWORD dwAssetIndex, const char *szPlainName, DWORD dwSubIndex, char *szBuffer)
 
static size_t CreateFileName (TRootHandler_Diablo3 *pRootHandler, const char *szShortName, char *szBuffer)
 
static PCASC_MAP CreatePackageMap (LPBYTE pbPackagesDat, LPBYTE pbPackagesEnd)
 
static int InsertFileEntry (TRootHandler_Diablo3 *pRootHandler, ENCODING_KEY &EncodingKey, const char *szFileName, size_t cchFileName)
 
static int ParseDirEntries_FileId1 (TRootHandler_Diablo3 *pRootHandler, LPBYTE pbFileEntries, DWORD dwFileEntries, DWORD dwRootDirIndex)
 
static int ParseDirEntries_FileId2 (TRootHandler_Diablo3 *pRootHandler, LPBYTE pbFileEntries, DWORD dwFileEntries, DWORD dwRootDirIndex)
 
static int ParseDirEntries_Named (TRootHandler_Diablo3 *pRootHandler, LPBYTE pbFileEntries, LPBYTE pbFileEnd, DWORD dwFileEntries, DWORD dwRootDirIndex)
 
static void ResolveFullFileNames (TRootHandler_Diablo3 *pRootHandler, PDIABLO3_CORE_TOC_ENTRY pCoreTocEntries, PCASC_MAP pPackageMap, LPBYTE pbCoreTocFile, DWORD dwFileIndexes)
 
static LPBYTE LoadFileToMemory (TCascStorage *hs, LPBYTE pbEncodingKey, DWORD *pcbFileData)
 
static LPBYTE LoadFileToMemory (TCascStorage *hs, const char *szFileName, DWORD *pcbFileData)
 
static int ParseDirectoryHeader (PDIABLO3_DIR_HEADER pDirHeader, LPBYTE pbDirFile, LPBYTE pbFileEnd)
 
static DWORD ScanDirectoryFile (TCascStorage *hs, LPBYTE pbRootFile, LPBYTE pbFileEnd)
 
static int ParseDirectoryFile (TRootHandler_Diablo3 *pRootHandler, LPBYTE pbDirFile, LPBYTE pbFileEnd, DWORD dwRootDirIndex)
 
static int ParseCoreTOC (TRootHandler_Diablo3 *pRootHandler, PCASC_MAP pPackageMap, LPBYTE pbCoreTocFile, LPBYTE pbCoreTocEnd)
 
static int D3Handler_Insert (TRootHandler_Diablo3 *pRootHandler, const char *szFileName, LPBYTE pbEncodingKey)
 
static LPBYTE D3Handler_Search (TRootHandler_Diablo3 *pRootHandler, TCascSearch *pSearch, PDWORD, PDWORD)
 
static void D3Handler_EndSearch (TRootHandler_Diablo3 *, TCascSearch *)
 
static LPBYTE D3Handler_GetKey (TRootHandler_Diablo3 *pRootHandler, const char *szFileName)
 
static void D3Handler_Close (TRootHandler_Diablo3 *pRootHandler)
 
int RootHandler_CreateDiablo3 (TCascStorage *hs, LPBYTE pbRootFile, DWORD cbRootFile)
 

Variables

static const DIABLO3_ASSET_INFO Assets []
 
static const DIABLO3_ASSET_INFO UnknownAsset = {"Unknown", "xxx"}
 

Macro Definition Documentation

#define __CASCLIB_SELF__
#define CASC_ENTRY_HAS_SUBINDEX   0x000000002
#define CASC_ENTRY_SHORT_NAME   0x000000001
#define DIABLO3_ASSET_COUNT   (sizeof(Assets) / sizeof(Assets[0]))
#define DIABLO3_INVALID_FILE   0xFFFFFFFF
#define DIABLO3_INVALID_INDEX   0xFFFFFFFF
#define DIABLO3_MAX_ASSETS   70
#define DIABLO3_MAX_LEVEL0_LENGTH   0x10
#define DIABLO3_MAX_SUBDIRS   0x20
#define DIABLO3_PACKAGES_SIGNATURE   0xAABB0002
#define DIABLO3_SUBDIR_SIGNATURE   0xEAF1FE87
#define ENTRY_FLAG_DIRECTORY_ENTRY   0x80
#define ENTRY_FLAG_FLAGS_MASK   0xF0
#define ENTRY_FLAG_FULL_NAME   0x02
#define ENTRY_FLAG_NAME_MASK   0x0F
#define ENTRY_FLAG_PLAIN_NAME   0x01
#define INDEX64_FILE_INDEX (   hash)    (DWORD)((hash >> 0x18) & 0xFFFFFFFF)
#define INDEX64_ROOT_INDEX (   hash)    (DWORD)((hash >> 0x38) & 0x000000FF)
#define INDEX64_SUB_INDEX (   hash)    (DWORD)((hash >> 0x00) & 0x00FFFFFF)
#define INVALID_ASSET_INDEX   0xFF
#define INVALID_FILE_INDEX   0xFFFFFFFF
#define MAKE_INDEX64 (   ri,
  fi,
  si 
)    (((ULONGLONG)ri << 0x38) | ((ULONGLONG)fi << 0x18) | ((ULONGLONG)si))
#define SEARCH_PHASE_FILE_IDS   1
#define SEARCH_PHASE_NAMES   0

Typedef Documentation

Function Documentation

static size_t CreateFileName ( TRootHandler_Diablo3 pRootHandler,
const char *  szShortName,
char *  szBuffer 
)
static
353 {
354  PCASC_FILE_ENTRY pRootEntry;
355  const char * szNameLevel0;
356  const char * szNameLevel1 = NULL;
357  DWORD dwRootIndex0 = 0;
358  DWORD dwAssetIndex = 0;
359 
360  // Retrieve the level-0 and level-1 directory indexes
361  ConvertStringToInt08(szShortName+0, &dwRootIndex0);
362  ConvertStringToInt08(szShortName+2, &dwAssetIndex);
363 
364  // Retrieve the name of the level-0 directory (aka root subdirectory)
365  pRootEntry = (PCASC_FILE_ENTRY)Array_ItemAt(&pRootHandler->FileTable, dwRootIndex0);
366  szNameLevel0 = (char *)Array_ItemAt(&pRootHandler->FileNames, pRootEntry->dwFileName);
367 
368  // Retrieve the name of the level-1 directory (aka asset name)
369  if(dwAssetIndex < DIABLO3_ASSET_COUNT)
370  szNameLevel1 = Assets[dwAssetIndex].szDirectoryName;
371  if(szNameLevel1 == NULL)
372  szNameLevel1 = UnknownAsset.szDirectoryName;
373 
374  // Copy the rest of the name as-is
375  return sprintf(szBuffer, "%s\\%s\\%s", szNameLevel0, szNameLevel1, szShortName + 4);
376 }
DYNAMIC_ARRAY FileTable
Definition: CascRootFile_Diablo3.cpp:149
Definition: CascRootFile_Diablo3.cpp:130
arena_t NULL
Definition: jemalloc_internal.h:624
static const DIABLO3_ASSET_INFO Assets[]
Definition: CascRootFile_Diablo3.cpp:161
int ConvertStringToInt08(const char *szString, PDWORD PtrValue)
Definition: Common.cpp:287
void * Array_ItemAt(PDYNAMIC_ARRAY pArray, size_t ItemIndex)
Definition: DynamicArray.cpp:81
struct _CASC_FILE_ENTRY * PCASC_FILE_ENTRY
std::string sprintf(CStringRef format, ArgList args)
Definition: format.h:3096
DWORD dwFileName
Definition: CascRootFile_Diablo3.cpp:134
unsigned int DWORD
Definition: CascPort.h:139
static const DIABLO3_ASSET_INFO UnknownAsset
Definition: CascRootFile_Diablo3.cpp:234
DYNAMIC_ARRAY FileNames
Definition: CascRootFile_Diablo3.cpp:152
const char * szDirectoryName
Definition: CascRootFile_Diablo3.cpp:123
#define DIABLO3_ASSET_COUNT
Definition: CascRootFile_Diablo3.cpp:236

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static PCASC_MAP CreatePackageMap ( LPBYTE  pbPackagesDat,
LPBYTE  pbPackagesEnd 
)
static
383 {
385  PCASC_MAP pPackageMap;
386 
387  // Get the header
388  if((pbPackagesDat + sizeof(DIABLO3_PACKAGES_DAT_HEADER)) >= pbPackagesEnd)
389  return NULL;
390  pbPackagesDat += sizeof(DIABLO3_PACKAGES_DAT_HEADER);
391 
392  // Check the signature and name count
393  if(pDatHeader->Signature != DIABLO3_PACKAGES_SIGNATURE)
394  return NULL;
395 
396  // Create the map for fast search of the file name
397  pPackageMap = Map_Create(pDatHeader->NumberOfNames, KEY_LENGTH_STRING, 0);
398  if(pPackageMap != NULL)
399  {
400  char * szFileName = (char *)pbPackagesDat;
401 
402  // Go as long as there is something
403  for(DWORD i = 0; i < pDatHeader->NumberOfNames; i++)
404  {
405  // Get the file extension
406  if((LPBYTE)szFileName >= pbPackagesEnd)
407  break;
408 
409  // Insert the file name to the map. The file extension is not included
410  Map_InsertString(pPackageMap, szFileName, true);
411  szFileName = szFileName + strlen(szFileName) + 1;
412  }
413  }
414 
415  return pPackageMap;
416 }
struct _DIABLO3_PACKAGES_DAT_HEADER DIABLO3_PACKAGES_DAT_HEADER
Definition: CascRootFile_Diablo3.cpp:114
PCASC_MAP Map_Create(DWORD dwMaxItems, DWORD dwKeyLength, DWORD dwKeyOffset)
Definition: Map.cpp:93
arena_t NULL
Definition: jemalloc_internal.h:624
BYTE * LPBYTE
Definition: CascPort.h:152
#define DIABLO3_PACKAGES_SIGNATURE
Definition: CascRootFile_Diablo3.cpp:21
DWORD Signature
Definition: CascRootFile_Diablo3.cpp:116
unsigned int DWORD
Definition: CascPort.h:139
Definition: Map.h:19
bool Map_InsertString(PCASC_MAP pMap, const char *szString, bool bCutExtension)
Definition: Map.cpp:207
DWORD NumberOfNames
Definition: CascRootFile_Diablo3.cpp:117
#define KEY_LENGTH_STRING
Definition: Map.h:17
struct _DIABLO3_PACKAGES_DAT_HEADER * PDIABLO3_PACKAGES_DAT_HEADER

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static size_t CreateShortName ( PCASC_MAP  pPackageMap,
DWORD  dwRootIndex,
DWORD  dwAssetIndex,
const char *  szPlainName,
DWORD  dwSubIndex,
char *  szBuffer 
)
static
285 {
286  PDIABLO3_ASSET_INFO pAssetInfo = GetAssetInfo(dwAssetIndex);
287  const char * szPackageName = NULL;
288  const char * szFormat;
289  size_t nLength;
290 
291  // Write the level-0 directory index as 2-digit hexa number
292  assert(dwRootIndex < 0x100);
293  *szBuffer++ = IntToHexChar[dwRootIndex >> 0x04];
294  *szBuffer++ = IntToHexChar[dwRootIndex & 0x0F];
295 
296  // Write the level-1 directory index as 2-digit hexa number
297  assert(dwAssetIndex < 0x100);
298  *szBuffer++ = IntToHexChar[dwAssetIndex >> 0x04];
299  *szBuffer++ = IntToHexChar[dwAssetIndex & 0x0F];
300 
301  // Construct the file name with ending "." for extension
302  szFormat = (dwSubIndex != DIABLO3_INVALID_INDEX) ? "%s\\%04u." : "%s.";
303  nLength = sprintf(szBuffer, szFormat, szPlainName, dwSubIndex);
304 
305  // Try to fixup the file extension from the package name.
306  // File extensions are not predictable because for subitems,
307  // they are not always equal to the main items:
308  //
309  // SoundBank\3D Ambience.sbk
310  // SoundBank\3D Ambience\0000.smp
311  // SoundBank\3D Ambience\0002.smp
312  // ...
313  // SoundBank\Angel.sbk
314  // SoundBank\Angel\0000.fsb
315  // SoundBank\Angel\0002.fsb
316  //
317  // We use the Base\Data_D3\PC\Misc\Packages.dat for real file extensions, where possible
318  //
319  if(pPackageMap != NULL)
320  {
321  // Retrieve the asset name
322  szPackageName = FindPackageName(pPackageMap, pAssetInfo->szDirectoryName, szBuffer);
323  if(szPackageName != NULL)
324  {
325  strcpy(szBuffer, szPackageName + strlen(pAssetInfo->szDirectoryName) + 1);
326  nLength = strlen(szBuffer);
327  }
328  }
329 
330  // If we havent't found the package, we either use the default asset extension or "xxx"
331  if(szPackageName == NULL)
332  {
333  if(dwSubIndex == DIABLO3_INVALID_INDEX)
334  {
335  strcpy(szBuffer + nLength, pAssetInfo->szExtension);
336  nLength += strlen(pAssetInfo->szExtension);
337  }
338  else
339  {
340  strcpy(szBuffer + nLength, "xxx");
341  nLength += 3;
342  }
343  }
344 
345  // Return the length of the short file name
346  return nLength + 4;
347 }
static PDIABLO3_ASSET_INFO GetAssetInfo(DWORD dwAssetIndex)
Definition: CascRootFile_Diablo3.cpp:241
arena_t NULL
Definition: jemalloc_internal.h:624
unsigned char IntToHexChar[]
Definition: Common.cpp:62
#define DIABLO3_INVALID_INDEX
Definition: CascRootFile_Diablo3.cpp:24
std::string sprintf(CStringRef format, ArgList args)
Definition: format.h:3096
const char * szExtension
Definition: CascRootFile_Diablo3.cpp:124
static char * FindPackageName(PCASC_MAP pPackageMap, const char *szAssetName, const char *szPlainName)
Definition: CascRootFile_Diablo3.cpp:265
const char * szDirectoryName
Definition: CascRootFile_Diablo3.cpp:123
Definition: CascRootFile_Diablo3.cpp:121

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void D3Handler_Close ( TRootHandler_Diablo3 pRootHandler)
static
996 {
997  if(pRootHandler != NULL)
998  {
999  // Free the file map
1000  Map_Free(pRootHandler->pRootMap);
1001 
1002  // Free the array of the file entries and file names
1003  Array_Free(&pRootHandler->FileTable);
1004  Array_Free(&pRootHandler->FileNames);
1005 
1006  // Free the root file itself
1007  CASC_FREE(pRootHandler);
1008  }
1009 }
DYNAMIC_ARRAY FileTable
Definition: CascRootFile_Diablo3.cpp:149
void Map_Free(PCASC_MAP pMap)
Definition: Map.cpp:279
arena_t NULL
Definition: jemalloc_internal.h:624
void Array_Free(PDYNAMIC_ARRAY pArray)
Definition: DynamicArray.cpp:95
PCASC_MAP pRootMap
Definition: CascRootFile_Diablo3.cpp:155
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
DYNAMIC_ARRAY FileNames
Definition: CascRootFile_Diablo3.cpp:152

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void D3Handler_EndSearch ( TRootHandler_Diablo3 ,
TCascSearch  
)
static
981 {
982  // Do nothing
983 }

+ Here is the caller graph for this function:

static LPBYTE D3Handler_GetKey ( TRootHandler_Diablo3 pRootHandler,
const char *  szFileName 
)
static
986 {
987  PCASC_FILE_ENTRY pFileEntry;
988  ULONGLONG FileNameHash = CalcFileNameHash(szFileName);
989 
990  // Find the file in the name table
991  pFileEntry = (PCASC_FILE_ENTRY)Map_FindObject(pRootHandler->pRootMap, &FileNameHash, NULL);
992  return (pFileEntry != NULL) ? pFileEntry->EncodingKey.Value : NULL;
993 }
void * Map_FindObject(PCASC_MAP pMap, void *pvKey, PDWORD PtrIndex)
Definition: Map.cpp:138
ULONGLONG CalcFileNameHash(const char *szFileName)
Definition: Common.cpp:260
unsigned long long ULONGLONG
Definition: CascPort.h:144
Definition: CascRootFile_Diablo3.cpp:130
arena_t NULL
Definition: jemalloc_internal.h:624
ENCODING_KEY EncodingKey
Definition: CascRootFile_Diablo3.cpp:132
PCASC_MAP pRootMap
Definition: CascRootFile_Diablo3.cpp:155
struct _CASC_FILE_ENTRY * PCASC_FILE_ENTRY
BYTE Value[MD5_HASH_SIZE]
Definition: CascCommon.h:98

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int D3Handler_Insert ( TRootHandler_Diablo3 pRootHandler,
const char *  szFileName,
LPBYTE  pbEncodingKey 
)
static
932 {
933  ENCODING_KEY EncodingKey;
934  DWORD dwFileIndex;
935 
936  // Don't let the number of items to overflow
937  if(pRootHandler->FileTable.ItemCount >= pRootHandler->FileTable.ItemCountMax)
939 
940  // Insert the item
941  EncodingKey = *(PENCODING_KEY)pbEncodingKey;
942  dwFileIndex = InsertFileEntry(pRootHandler,
943  EncodingKey,
944  szFileName,
945  strlen(szFileName) + 1);
946  return (dwFileIndex != INVALID_FILE_INDEX) ? ERROR_SUCCESS : ERROR_NOT_ENOUGH_MEMORY;
947 }
Definition: CascCommon.h:96
DYNAMIC_ARRAY FileTable
Definition: CascRootFile_Diablo3.cpp:149
static int InsertFileEntry(TRootHandler_Diablo3 *pRootHandler, ENCODING_KEY &EncodingKey, const char *szFileName, size_t cchFileName)
Definition: CascRootFile_Diablo3.cpp:419
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
#define INVALID_FILE_INDEX
Definition: CascRootFile_Diablo3.cpp:29
struct _ENCODING_KEY * PENCODING_KEY
unsigned int DWORD
Definition: CascPort.h:139
size_t ItemCountMax
Definition: DynamicArray.h:20
#define ERROR_SUCCESS
Definition: CascPort.h:204
size_t ItemCount
Definition: DynamicArray.h:21

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static LPBYTE D3Handler_Search ( TRootHandler_Diablo3 pRootHandler,
TCascSearch pSearch,
PDWORD  ,
PDWORD   
)
static
950 {
951  PCASC_FILE_ENTRY pFileEntry;
952  const char * szSrcName = NULL;
953 
954  // Are we still inside the root directory range?
955  while(pSearch->IndexLevel1 < pRootHandler->FileTable.ItemCount)
956  {
957  // Get the n-th directory and the file name
958  pFileEntry = (PCASC_FILE_ENTRY)Array_ItemAt(&pRootHandler->FileTable, pSearch->IndexLevel1);
959  szSrcName = (char *)Array_ItemAt(&pRootHandler->FileNames, pFileEntry->dwFileName);
960 
961  // This is either a full file name or an abbreviated name
962  if(pFileEntry->dwFlags & CASC_ENTRY_SHORT_NAME)
963  {
964  CreateFileName(pRootHandler, szSrcName, pSearch->szFileName);
965  }
966  else
967  {
968  strcpy(pSearch->szFileName, szSrcName);
969  }
970 
971  // Prepare for the next search
972  pSearch->IndexLevel1++;
973  return pFileEntry->EncodingKey.Value;
974  }
975 
976  // No more entries
977  return NULL;
978 }
DYNAMIC_ARRAY FileTable
Definition: CascRootFile_Diablo3.cpp:149
static size_t CreateFileName(TRootHandler_Diablo3 *pRootHandler, const char *szShortName, char *szBuffer)
Definition: CascRootFile_Diablo3.cpp:349
Definition: CascRootFile_Diablo3.cpp:130
arena_t NULL
Definition: jemalloc_internal.h:624
DWORD dwFlags
Definition: CascRootFile_Diablo3.cpp:135
ENCODING_KEY EncodingKey
Definition: CascRootFile_Diablo3.cpp:132
void * Array_ItemAt(PDYNAMIC_ARRAY pArray, size_t ItemIndex)
Definition: DynamicArray.cpp:81
struct _CASC_FILE_ENTRY * PCASC_FILE_ENTRY
DWORD dwFileName
Definition: CascRootFile_Diablo3.cpp:134
char szFileName[MAX_PATH]
Definition: CascCommon.h:268
BYTE Value[MD5_HASH_SIZE]
Definition: CascCommon.h:98
DYNAMIC_ARRAY FileNames
Definition: CascRootFile_Diablo3.cpp:152
#define CASC_ENTRY_SHORT_NAME
Definition: CascRootFile_Diablo3.cpp:39
size_t IndexLevel1
Definition: CascCommon.h:272
size_t ItemCount
Definition: DynamicArray.h:21

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static char* FindPackageName ( PCASC_MAP  pPackageMap,
const char *  szAssetName,
const char *  szPlainName 
)
static
269 {
270  char szFileName[MAX_PATH+1];
271  size_t nLength;
272 
273  // Construct the name without extension and find it in the map
274  nLength = sprintf(szFileName, "%s\\%s", szAssetName, szPlainName);
275  return (char *)Map_FindString(pPackageMap, szFileName, szFileName + nLength);
276 }
#define MAX_PATH
Definition: CascPort.h:160
std::string sprintf(CStringRef format, ArgList args)
Definition: format.h:3096
const char * Map_FindString(PCASC_MAP pMap, const char *szString, const char *szStringEnd)
Definition: Map.cpp:251

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static PDIABLO3_ASSET_INFO GetAssetInfo ( DWORD  dwAssetIndex)
static
242 {
243  if(dwAssetIndex < DIABLO3_ASSET_COUNT && Assets[dwAssetIndex].szDirectoryName != NULL)
244  return &Assets[dwAssetIndex];
245  return &UnknownAsset;
246 }
arena_t NULL
Definition: jemalloc_internal.h:624
static const DIABLO3_ASSET_INFO Assets[]
Definition: CascRootFile_Diablo3.cpp:161
static const DIABLO3_ASSET_INFO UnknownAsset
Definition: CascRootFile_Diablo3.cpp:234
#define DIABLO3_ASSET_COUNT
Definition: CascRootFile_Diablo3.cpp:236

+ Here is the caller graph for this function:

static int InsertFileEntry ( TRootHandler_Diablo3 pRootHandler,
ENCODING_KEY EncodingKey,
const char *  szFileName,
size_t  cchFileName 
)
static
424 {
425  PCASC_FILE_ENTRY pFileEntry;
426 
427  // We must not allow the file name array to be reallocated.
428  // Reallocating the array would cause pointers in TRootHandler_Diablo3::pRootMap
429  // become invalid
430  if(pRootHandler->FileTable.ItemCount >= pRootHandler->FileTable.ItemCountMax)
431  {
432  assert(false);
434  }
435 
436  // Insert the plain name to the root handler's global name list
437  szFileName = (const char *)Array_Insert(&pRootHandler->FileNames, szFileName, cchFileName);
438  if(szFileName == NULL)
440 
441  // Make sure that we don't exceed the file limit at this phase
442  pFileEntry = (PCASC_FILE_ENTRY)Array_Insert(&pRootHandler->FileTable, NULL, 1);
443  assert(pFileEntry != NULL);
444 
445  // Store the info into the file entry
446  pFileEntry->EncodingKey = EncodingKey;
447  pFileEntry->FileNameHash = CalcFileNameHash(szFileName);
448  pFileEntry->dwFileName = (DWORD)Array_IndexOf(&pRootHandler->FileNames, szFileName);
449  pFileEntry->dwFlags = 0;
450 
451  // Verify collisions (debug version only)
452  assert(Map_FindObject(pRootHandler->pRootMap, &pFileEntry->FileNameHash, NULL) == NULL);
453 
454  // Calculate the file name hash
455  Map_InsertObject(pRootHandler->pRootMap, pFileEntry, &pFileEntry->FileNameHash);
456 
457  // Success
458  return ERROR_SUCCESS;
459 }
DYNAMIC_ARRAY FileTable
Definition: CascRootFile_Diablo3.cpp:149
void * Map_FindObject(PCASC_MAP pMap, void *pvKey, PDWORD PtrIndex)
Definition: Map.cpp:138
ULONGLONG CalcFileNameHash(const char *szFileName)
Definition: Common.cpp:260
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
Definition: CascRootFile_Diablo3.cpp:130
arena_t NULL
Definition: jemalloc_internal.h:624
DWORD dwFlags
Definition: CascRootFile_Diablo3.cpp:135
ENCODING_KEY EncodingKey
Definition: CascRootFile_Diablo3.cpp:132
PCASC_MAP pRootMap
Definition: CascRootFile_Diablo3.cpp:155
bool Map_InsertObject(PCASC_MAP pMap, void *pvNewObject, void *pvKey)
Definition: Map.cpp:170
struct _CASC_FILE_ENTRY * PCASC_FILE_ENTRY
DWORD dwFileName
Definition: CascRootFile_Diablo3.cpp:134
void * Array_Insert(PDYNAMIC_ARRAY pArray, const void *NewItems, size_t NewItemCount)
Definition: DynamicArray.cpp:63
unsigned int DWORD
Definition: CascPort.h:139
size_t Array_IndexOf(PDYNAMIC_ARRAY pArray, const void *ArrayPtr)
Definition: DynamicArray.cpp:87
DYNAMIC_ARRAY FileNames
Definition: CascRootFile_Diablo3.cpp:152
ULONGLONG FileNameHash
Definition: CascRootFile_Diablo3.cpp:133
size_t ItemCountMax
Definition: DynamicArray.h:20
#define ERROR_SUCCESS
Definition: CascPort.h:204
size_t ItemCount
Definition: DynamicArray.h:21

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static LPBYTE LoadFileToMemory ( TCascStorage hs,
LPBYTE  pbEncodingKey,
DWORD pcbFileData 
)
static
649 {
650  QUERY_KEY EncodingKey;
651  LPBYTE pbFileData = NULL;
652  HANDLE hFile;
653  DWORD cbBytesRead = 0;
654  DWORD cbFileData = 0;
655 
656  // Open the file by encoding key
657  EncodingKey.pbData = pbEncodingKey;
658  EncodingKey.cbData = MD5_HASH_SIZE;
659  if(CascOpenFileByEncodingKey((HANDLE)hs, &EncodingKey, 0, &hFile))
660  {
661  // Retrieve the file size
662  cbFileData = CascGetFileSize(hFile, NULL);
663  if(cbFileData > 0)
664  {
665  pbFileData = CASC_ALLOC(BYTE, cbFileData);
666  if(pbFileData != NULL)
667  {
668  CascReadFile(hFile, pbFileData, cbFileData, &cbBytesRead);
669  }
670  }
671 
672  // Close the file
673  CascCloseFile(hFile);
674  }
675 
676  // Give the file to the caller
677  if(pcbFileData != NULL)
678  pcbFileData[0] = cbBytesRead;
679  return pbFileData;
680 }
#define CASC_ALLOC(type, count)
Definition: CascCommon.h:302
void * HANDLE
Definition: CascPort.h:146
Definition: CascLib.h:138
arena_t NULL
Definition: jemalloc_internal.h:624
BYTE * LPBYTE
Definition: CascPort.h:152
DWORD cbData
Definition: CascLib.h:141
#define MD5_HASH_SIZE
Definition: CascLib.h:105
LPBYTE pbData
Definition: CascLib.h:140
DWORD WINAPI CascGetFileSize(HANDLE hFile, PDWORD pdwFileSizeHigh)
Definition: CascReadFile.cpp:367
unsigned int DWORD
Definition: CascPort.h:139
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
bool WINAPI CascReadFile(HANDLE hFile, void *lpBuffer, DWORD dwToRead, PDWORD pdwRead)
Definition: CascReadFile.cpp:459
unsigned char BYTE
Definition: CascPort.h:136

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static LPBYTE LoadFileToMemory ( TCascStorage hs,
const char *  szFileName,
DWORD pcbFileData 
)
static
683 {
684  LPBYTE pbEncodingKey = NULL;
685  LPBYTE pbFileData = NULL;
686 
687  // Try to find encoding key for the file
688  pbEncodingKey = RootHandler_GetKey(hs->pRootHandler, szFileName);
689  if(pbEncodingKey != NULL)
690  pbFileData = LoadFileToMemory(hs, pbEncodingKey, pcbFileData);
691 
692  return pbFileData;
693 }
TRootHandler * pRootHandler
Definition: CascCommon.h:223
arena_t NULL
Definition: jemalloc_internal.h:624
BYTE * LPBYTE
Definition: CascPort.h:152
LPBYTE RootHandler_GetKey(TRootHandler *pRootHandler, const char *szFileName)
Definition: RootHandler.cpp:44
static LPBYTE LoadFileToMemory(TCascStorage *hs, LPBYTE pbEncodingKey, DWORD *pcbFileData)
Definition: CascRootFile_Diablo3.cpp:648

+ Here is the call graph for this function:

static int ParseCoreTOC ( TRootHandler_Diablo3 pRootHandler,
PCASC_MAP  pPackageMap,
LPBYTE  pbCoreTocFile,
LPBYTE  pbCoreTocEnd 
)
static
867 {
868  PDIABLO3_CORE_TOC_HEADER pTocHeader;
869  PDIABLO3_CORE_TOC_ENTRY pSortedEntries;
870  PDIABLO3_CORE_TOC_ENTRY pTocEntry;
871  LPBYTE pbCoreTocNames;
872  DWORD dwFileIndexes = 0;
873  DWORD i;
874 
875  // Check the space for header
876  if((pbCoreTocFile + sizeof(DIABLO3_CORE_TOC_HEADER)) > pbCoreTocEnd)
877  return ERROR_FILE_CORRUPT;
878  pTocHeader = (PDIABLO3_CORE_TOC_HEADER)pbCoreTocFile;
879  pbCoreTocFile += sizeof(DIABLO3_CORE_TOC_HEADER);
880 
881  // Calculate space needed for allocation
882  for(i = 0; i < DIABLO3_MAX_ASSETS; i++)
883  {
884  // Get the first entry
885  pTocEntry = (PDIABLO3_CORE_TOC_ENTRY)(pbCoreTocFile + pTocHeader->EntryOffsets[i]);
886 
887  // Find out the entry with the maximum index
888  for(DWORD n = 0; n < pTocHeader->EntryCounts[i]; n++)
889  {
890  if(pTocEntry->FileIndex > dwFileIndexes)
891  dwFileIndexes = pTocEntry->FileIndex + 1;
892  pTocEntry++;
893  }
894  }
895 
896  // Allocate and populate the array of DIABLO3_CORE_TOC_ENTRYs
897  pSortedEntries = CASC_ALLOC(DIABLO3_CORE_TOC_ENTRY, dwFileIndexes);
898  if(pSortedEntries != NULL)
899  {
900  // Initialize all entries to invalid
901  memset(pSortedEntries, 0xFF, dwFileIndexes * sizeof(DIABLO3_CORE_TOC_ENTRY));
902 
903  // Populate the linear array with the entries
904  for(i = 0; i < DIABLO3_MAX_ASSETS; i++)
905  {
906  // Set the pointers
907  pTocEntry = (PDIABLO3_CORE_TOC_ENTRY)(pbCoreTocFile + pTocHeader->EntryOffsets[i]);
908  pbCoreTocNames = (LPBYTE)(pTocEntry + pTocHeader->EntryCounts[i]);
909 
910  // Setup the entries
911  for(DWORD n = 0; n < pTocHeader->EntryCounts[i]; n++)
912  {
913  pSortedEntries[pTocEntry->FileIndex].AssetIndex = pTocEntry->AssetIndex;
914  pSortedEntries[pTocEntry->FileIndex].FileIndex = pTocEntry->FileIndex;
915  pSortedEntries[pTocEntry->FileIndex].NameOffset = (DWORD)(pbCoreTocNames - pbCoreTocFile) + pTocEntry->NameOffset;
916  pTocEntry++;
917  }
918  }
919 
920  // Now use the linear array to resolve the asset indexes and plain names
921  ResolveFullFileNames(pRootHandler, pSortedEntries, pPackageMap, pbCoreTocFile, dwFileIndexes);
922  CASC_FREE(pSortedEntries);
923  }
924 
925  return ERROR_SUCCESS;
926 }
#define CASC_ALLOC(type, count)
Definition: CascCommon.h:302
#define DIABLO3_MAX_ASSETS
Definition: CascRootFile_Diablo3.cpp:26
DWORD EntryOffsets[DIABLO3_MAX_ASSETS]
Definition: CascRootFile_Diablo3.cpp:78
DWORD AssetIndex
Definition: CascRootFile_Diablo3.cpp:86
#define ERROR_FILE_CORRUPT
Definition: CascPort.h:218
arena_t NULL
Definition: jemalloc_internal.h:624
DWORD NameOffset
Definition: CascRootFile_Diablo3.cpp:88
BYTE * LPBYTE
Definition: CascPort.h:152
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
DWORD FileIndex
Definition: CascRootFile_Diablo3.cpp:87
struct _DIABLO3_CORE_TOC_HEADER * PDIABLO3_CORE_TOC_HEADER
Definition: CascRootFile_Diablo3.cpp:75
static void ResolveFullFileNames(TRootHandler_Diablo3 *pRootHandler, PDIABLO3_CORE_TOC_ENTRY pCoreTocEntries, PCASC_MAP pPackageMap, LPBYTE pbCoreTocFile, DWORD dwFileIndexes)
Definition: CascRootFile_Diablo3.cpp:591
Definition: CascRootFile_Diablo3.cpp:84
struct _DIABLO3_CORE_TOC_ENTRY * PDIABLO3_CORE_TOC_ENTRY
unsigned int DWORD
Definition: CascPort.h:139
DWORD EntryCounts[DIABLO3_MAX_ASSETS]
Definition: CascRootFile_Diablo3.cpp:77
struct _DIABLO3_CORE_TOC_HEADER DIABLO3_CORE_TOC_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 ParseDirectoryFile ( TRootHandler_Diablo3 pRootHandler,
LPBYTE  pbDirFile,
LPBYTE  pbFileEnd,
DWORD  dwRootDirIndex 
)
static
811 {
812  DIABLO3_DIR_HEADER DirHeader;
813  int nError;
814 
815  // Sanity checks
816  assert(pRootHandler->FileTable.ItemArray != NULL);
817  assert(pRootHandler->FileTable.ItemCount < pRootHandler->FileTable.ItemCountMax);
818 
819  // Parse the directory header in order to retrieve the items
820  nError = ParseDirectoryHeader(&DirHeader, pbDirFile, pbFileEnd);
821  if(nError != ERROR_SUCCESS)
822  return nError;
823 
824  // Process all DIABLO3_FILEID1_ENTRY entries. These are for files
825  // belonging to an asset group, without subitem number.
826  // Example: "SoundBank\SoundFile.smp"
827  // We skip inserting them to the name map, because the names are not known yet
828  if(DirHeader.pbEntries1 && DirHeader.dwEntries1)
829  {
830  assert(dwRootDirIndex != DIABLO3_INVALID_INDEX);
831  nError = ParseDirEntries_FileId1(pRootHandler, DirHeader.pbEntries1, DirHeader.dwEntries1, dwRootDirIndex);
832  if(nError != ERROR_SUCCESS)
833  return nError;
834  }
835 
836  // Parse all DIABLO3_FILEID2_ENTRY entries. These are for files
837  // belonging to an asset group, with a subitem number.
838  // Example: "SoundBank\SoundFile\0001.smp"
839  // We skip inserting them to the name map, because the names are not known yet
840  if(DirHeader.pbEntries2 && DirHeader.dwEntries2)
841  {
842  assert(dwRootDirIndex != DIABLO3_INVALID_INDEX);
843  nError = ParseDirEntries_FileId2(pRootHandler, DirHeader.pbEntries2, DirHeader.dwEntries2, dwRootDirIndex);
844  if(nError != ERROR_SUCCESS)
845  return nError;
846  }
847 
848 
849  // Parse all named entries. These are for files with arbitrary names,
850  // and they do not belong to an asset.
851  if(DirHeader.pbEntries3 && DirHeader.dwEntries3)
852  {
853  nError = ParseDirEntries_Named(pRootHandler, DirHeader.pbEntries3, pbFileEnd, DirHeader.dwEntries3, dwRootDirIndex);
854  if(nError != ERROR_SUCCESS)
855  return nError;
856  }
857 
858  // Give the directory to the caller
859  return nError;
860 }
DWORD dwEntries3
Definition: CascRootFile_Diablo3.cpp:100
DYNAMIC_ARRAY FileTable
Definition: CascRootFile_Diablo3.cpp:149
DWORD dwEntries2
Definition: CascRootFile_Diablo3.cpp:99
arena_t NULL
Definition: jemalloc_internal.h:624
static int ParseDirectoryHeader(PDIABLO3_DIR_HEADER pDirHeader, LPBYTE pbDirFile, LPBYTE pbFileEnd)
Definition: CascRootFile_Diablo3.cpp:695
static int ParseDirEntries_Named(TRootHandler_Diablo3 *pRootHandler, LPBYTE pbFileEntries, LPBYTE pbFileEnd, DWORD dwFileEntries, DWORD dwRootDirIndex)
Definition: CascRootFile_Diablo3.cpp:525
LPBYTE pbEntries1
Definition: CascRootFile_Diablo3.cpp:95
#define DIABLO3_INVALID_INDEX
Definition: CascRootFile_Diablo3.cpp:24
static int ParseDirEntries_FileId2(TRootHandler_Diablo3 *pRootHandler, LPBYTE pbFileEntries, DWORD dwFileEntries, DWORD dwRootDirIndex)
Definition: CascRootFile_Diablo3.cpp:493
DWORD dwEntries1
Definition: CascRootFile_Diablo3.cpp:98
char * ItemArray
Definition: DynamicArray.h:19
Definition: CascRootFile_Diablo3.cpp:93
LPBYTE pbEntries2
Definition: CascRootFile_Diablo3.cpp:96
LPBYTE pbEntries3
Definition: CascRootFile_Diablo3.cpp:97
static int ParseDirEntries_FileId1(TRootHandler_Diablo3 *pRootHandler, LPBYTE pbFileEntries, DWORD dwFileEntries, DWORD dwRootDirIndex)
Definition: CascRootFile_Diablo3.cpp:461
size_t ItemCountMax
Definition: DynamicArray.h:20
#define ERROR_SUCCESS
Definition: CascPort.h:204
size_t ItemCount
Definition: DynamicArray.h:21

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int ParseDirectoryHeader ( PDIABLO3_DIR_HEADER  pDirHeader,
LPBYTE  pbDirFile,
LPBYTE  pbFileEnd 
)
static
699 {
700  DWORD dwSignature = 0;
701 
702  //
703  // Structure of a Diablo3 directory file
704  // 1) Signature (4 bytes)
705  // 2) Number of DIABLO3_FILEID1_ENTRY entries (4 bytes)
706  // 3) Array of DIABLO3_FILEID1_ENTRY entries
707  // 4) Number of DIABLO3_FILEID2_ENTRY entries (4 bytes)
708  // 5) Array of DIABLO3_FILEID2_ENTRY entries
709  // 6) Number of DIABLO3_NAMED_ENTRY entries (4 bytes)
710  // 7) Array of DIABLO3_NAMED_ENTRY entries
711  //
712 
713  // Prepare the header signature
714  memset(pDirHeader, 0, sizeof(DIABLO3_DIR_HEADER));
715 
716  // Get the signature
717  if((pbDirFile + sizeof(DWORD)) >= pbFileEnd)
718  return ERROR_BAD_FORMAT;
719  dwSignature = *(PDWORD)pbDirFile;
720 
721  // Check the signature
722  if(dwSignature != CASC_DIABLO3_ROOT_SIGNATURE && dwSignature != DIABLO3_SUBDIR_SIGNATURE)
723  return ERROR_BAD_FORMAT;
724  pbDirFile += sizeof(DWORD);
725 
726  // Subdirectories have extra two arrays
727  if(dwSignature == DIABLO3_SUBDIR_SIGNATURE)
728  {
729  // Get the number of DIABLO3_FILEID1_ENTRY items
730  if((pbDirFile + sizeof(DWORD)) >= pbFileEnd)
731  return ERROR_BAD_FORMAT;
732  pDirHeader->dwEntries1 = *(PDWORD)pbDirFile;
733 
734  // Get the array of DIABLO3_FILEID1_ENTRY
735  pDirHeader->pbEntries1 = (pbDirFile + sizeof(DWORD));
736  pbDirFile = pbDirFile + sizeof(DWORD) + pDirHeader->dwEntries1 * sizeof(DIABLO3_FILEID1_ENTRY);
737 
738  // Get the number of DIABLO3_FILEID2_ENTRY items
739  if((pbDirFile + sizeof(DWORD)) >= pbFileEnd)
740  return ERROR_BAD_FORMAT;
741  pDirHeader->dwEntries2 = *(PDWORD)pbDirFile;
742 
743  // Get the array of DIABLO3_FILEID2_ENTRY
744  pDirHeader->pbEntries2 = (pbDirFile + sizeof(DWORD));
745  pbDirFile = pbDirFile + sizeof(DWORD) + pDirHeader->dwEntries2 * sizeof(DIABLO3_FILEID2_ENTRY);
746  }
747 
748  // Get the pointer and length DIABLO3_NAMED_ENTRY array
749  if((pbDirFile + sizeof(DWORD)) >= pbFileEnd)
750  return ERROR_BAD_FORMAT;
751  pDirHeader->dwEntries3 = *(PDWORD)pbDirFile;
752  pDirHeader->pbEntries3 = (pbDirFile + sizeof(DWORD));
753  return ERROR_SUCCESS;
754 }
DWORD dwEntries3
Definition: CascRootFile_Diablo3.cpp:100
DWORD dwEntries2
Definition: CascRootFile_Diablo3.cpp:99
DWORD * PDWORD
Definition: CascPort.h:151
Definition: CascRootFile_Diablo3.cpp:60
#define CASC_DIABLO3_ROOT_SIGNATURE
Definition: RootHandler.h:18
Definition: CascRootFile_Diablo3.cpp:53
LPBYTE pbEntries1
Definition: CascRootFile_Diablo3.cpp:95
unsigned int DWORD
Definition: CascPort.h:139
DWORD dwEntries1
Definition: CascRootFile_Diablo3.cpp:98
#define ERROR_BAD_FORMAT
Definition: CascPort.h:214
Definition: CascRootFile_Diablo3.cpp:93
LPBYTE pbEntries2
Definition: CascRootFile_Diablo3.cpp:96
#define DIABLO3_SUBDIR_SIGNATURE
Definition: CascRootFile_Diablo3.cpp:20
LPBYTE pbEntries3
Definition: CascRootFile_Diablo3.cpp:97
#define ERROR_SUCCESS
Definition: CascPort.h:204

+ Here is the caller graph for this function:

static int ParseDirEntries_FileId1 ( TRootHandler_Diablo3 pRootHandler,
LPBYTE  pbFileEntries,
DWORD  dwFileEntries,
DWORD  dwRootDirIndex 
)
static
466 {
467  PDIABLO3_FILEID1_ENTRY pEntry = (PDIABLO3_FILEID1_ENTRY)pbFileEntries;
468  PCASC_FILE_ENTRY pFileEntry;
469 
470  // Overflow test
471  if((pRootHandler->FileTable.ItemCount + dwFileEntries) >= pRootHandler->FileTable.ItemCountMax)
472  {
473  assert(false);
475  }
476 
477  // Parse the all ID1 entries in the file
478  for(DWORD i = 0; i < dwFileEntries; i++, pEntry++)
479  {
480  // Insert the file entry to the global list
481  pFileEntry = (PCASC_FILE_ENTRY)Array_Insert(&pRootHandler->FileTable, NULL, 1);
482  assert(pFileEntry != NULL);
483 
484  // Fill the index entry
485  pFileEntry->EncodingKey = pEntry->EncodingKey;
486  pFileEntry->FileNameHash = MAKE_INDEX64(dwRootDirIndex, pEntry->FileIndex, 0);
487  pFileEntry->dwFlags = CASC_ENTRY_SHORT_NAME;
488  }
489 
490  return ERROR_SUCCESS;
491 }
DYNAMIC_ARRAY FileTable
Definition: CascRootFile_Diablo3.cpp:149
ENCODING_KEY EncodingKey
Definition: CascRootFile_Diablo3.cpp:55
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
Definition: CascRootFile_Diablo3.cpp:130
arena_t NULL
Definition: jemalloc_internal.h:624
DWORD dwFlags
Definition: CascRootFile_Diablo3.cpp:135
ENCODING_KEY EncodingKey
Definition: CascRootFile_Diablo3.cpp:132
Definition: CascRootFile_Diablo3.cpp:53
struct _CASC_FILE_ENTRY * PCASC_FILE_ENTRY
void * Array_Insert(PDYNAMIC_ARRAY pArray, const void *NewItems, size_t NewItemCount)
Definition: DynamicArray.cpp:63
unsigned int DWORD
Definition: CascPort.h:139
struct _DIABLO3_FILEID1_ENTRY * PDIABLO3_FILEID1_ENTRY
ULONGLONG FileNameHash
Definition: CascRootFile_Diablo3.cpp:133
#define CASC_ENTRY_SHORT_NAME
Definition: CascRootFile_Diablo3.cpp:39
DWORD FileIndex
Definition: CascRootFile_Diablo3.cpp:56
#define MAKE_INDEX64(ri, fi, si)
Definition: CascRootFile_Diablo3.cpp:47
size_t ItemCountMax
Definition: DynamicArray.h:20
#define ERROR_SUCCESS
Definition: CascPort.h:204
size_t ItemCount
Definition: DynamicArray.h:21

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int ParseDirEntries_FileId2 ( TRootHandler_Diablo3 pRootHandler,
LPBYTE  pbFileEntries,
DWORD  dwFileEntries,
DWORD  dwRootDirIndex 
)
static
498 {
499  PDIABLO3_FILEID2_ENTRY pEntry = (PDIABLO3_FILEID2_ENTRY)pbFileEntries;
500  PCASC_FILE_ENTRY pFileEntry;
501 
502  // Overflow test
503  if((pRootHandler->FileTable.ItemCount + dwFileEntries) >= pRootHandler->FileTable.ItemCountMax)
504  {
505  assert(false);
507  }
508 
509  // Parse the all ID1 entries in the file
510  for(DWORD i = 0; i < dwFileEntries; i++, pEntry++)
511  {
512  // Insert the file entry to the global list
513  pFileEntry = (PCASC_FILE_ENTRY)Array_Insert(&pRootHandler->FileTable, NULL, 1);
514  assert(pFileEntry != NULL);
515 
516  // Fill the index entry
517  pFileEntry->EncodingKey = pEntry->EncodingKey;
518  pFileEntry->FileNameHash = MAKE_INDEX64(dwRootDirIndex, pEntry->FileIndex, pEntry->SubIndex);
520  }
521 
522  return ERROR_SUCCESS;
523 }
DYNAMIC_ARRAY FileTable
Definition: CascRootFile_Diablo3.cpp:149
Definition: CascRootFile_Diablo3.cpp:60
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
Definition: CascRootFile_Diablo3.cpp:130
arena_t NULL
Definition: jemalloc_internal.h:624
DWORD dwFlags
Definition: CascRootFile_Diablo3.cpp:135
ENCODING_KEY EncodingKey
Definition: CascRootFile_Diablo3.cpp:132
#define CASC_ENTRY_HAS_SUBINDEX
Definition: CascRootFile_Diablo3.cpp:40
DWORD FileIndex
Definition: CascRootFile_Diablo3.cpp:63
struct _CASC_FILE_ENTRY * PCASC_FILE_ENTRY
DWORD SubIndex
Definition: CascRootFile_Diablo3.cpp:64
void * Array_Insert(PDYNAMIC_ARRAY pArray, const void *NewItems, size_t NewItemCount)
Definition: DynamicArray.cpp:63
unsigned int DWORD
Definition: CascPort.h:139
ENCODING_KEY EncodingKey
Definition: CascRootFile_Diablo3.cpp:62
ULONGLONG FileNameHash
Definition: CascRootFile_Diablo3.cpp:133
#define CASC_ENTRY_SHORT_NAME
Definition: CascRootFile_Diablo3.cpp:39
#define MAKE_INDEX64(ri, fi, si)
Definition: CascRootFile_Diablo3.cpp:47
size_t ItemCountMax
Definition: DynamicArray.h:20
struct _DIABLO3_FILEID2_ENTRY * PDIABLO3_FILEID2_ENTRY
#define ERROR_SUCCESS
Definition: CascPort.h:204
size_t ItemCount
Definition: DynamicArray.h:21

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static int ParseDirEntries_Named ( TRootHandler_Diablo3 pRootHandler,
LPBYTE  pbFileEntries,
LPBYTE  pbFileEnd,
DWORD  dwFileEntries,
DWORD  dwRootDirIndex 
)
static
531 {
532  char szFileName[MAX_PATH+1];
533  char * szNamePtr = szFileName;
534  DWORD cbFileEntry;
535  int nError = ERROR_SUCCESS;
536 
537  // Overflow test
538  if((pRootHandler->FileTable.ItemCount + dwFileEntries) >= pRootHandler->FileTable.ItemCountMax)
539  {
540  assert(false);
542  }
543 
544  // If we the file is not in the root directory itself,
545  // prepare the prefix for the root directory.
546  if(dwRootDirIndex != DIABLO3_INVALID_INDEX)
547  {
548  PCASC_FILE_ENTRY pRootEntry = (PCASC_FILE_ENTRY)Array_ItemAt(&pRootHandler->FileTable, dwRootDirIndex);
549  const char * szRootName = (const char *)Array_ItemAt(&pRootHandler->FileNames, pRootEntry->dwFileName);
550 
551  // Copy the root directory name
552  while(szRootName[0] != 0)
553  *szNamePtr++ = *szRootName++;
554 
555  // Append the backslash
556  *szNamePtr++ = '\\';
557  }
558 
559  // Parse the file entry
560  while(pbFileEntries < pbFileEnd)
561  {
562  PDIABLO3_NAMED_ENTRY pNamedEntry = (PDIABLO3_NAMED_ENTRY)pbFileEntries;
563  DWORD cchFileName;
564 
565  // Verify the named entry whether it does not go beyond the EOF
566  cbFileEntry = VerifyNamedFileEntry(pbFileEntries, pbFileEnd);
567  if(cbFileEntry == 0)
568  return ERROR_FILE_CORRUPT;
569 
570  // Append the file name to the prepared file name
571  // This way we obtain the full name and the name lookup
572  // will be fully operational
573  memcpy(szNamePtr, pNamedEntry->szFileName, (cbFileEntry - sizeof(ENCODING_KEY)));
574  cchFileName = (DWORD)((szNamePtr - szFileName) + (cbFileEntry - sizeof(ENCODING_KEY)));
575 
576  // Insert the named entry to the global file table
577  nError = InsertFileEntry(pRootHandler,
578  pNamedEntry->EncodingKey,
579  szFileName,
580  cchFileName);
581  if(nError != ERROR_SUCCESS)
582  return nError;
583 
584  // Move the pointer to the next entry
585  pbFileEntries += cbFileEntry;
586  }
587 
588  return ERROR_SUCCESS;
589 }
Definition: CascCommon.h:96
DYNAMIC_ARRAY FileTable
Definition: CascRootFile_Diablo3.cpp:149
static int InsertFileEntry(TRootHandler_Diablo3 *pRootHandler, ENCODING_KEY &EncodingKey, const char *szFileName, size_t cchFileName)
Definition: CascRootFile_Diablo3.cpp:419
struct _DIABLO3_NAMED_ENTRY * PDIABLO3_NAMED_ENTRY
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
static DWORD VerifyNamedFileEntry(LPBYTE pbNamedEntry, LPBYTE pbFileEnd)
Definition: CascRootFile_Diablo3.cpp:248
#define ERROR_FILE_CORRUPT
Definition: CascPort.h:218
#define MAX_PATH
Definition: CascPort.h:160
Definition: CascRootFile_Diablo3.cpp:130
BYTE szFileName[1]
Definition: CascRootFile_Diablo3.cpp:71
struct _ENCODING_KEY ENCODING_KEY
Definition: CascRootFile_Diablo3.cpp:68
void * Array_ItemAt(PDYNAMIC_ARRAY pArray, size_t ItemIndex)
Definition: DynamicArray.cpp:81
#define DIABLO3_INVALID_INDEX
Definition: CascRootFile_Diablo3.cpp:24
struct _CASC_FILE_ENTRY * PCASC_FILE_ENTRY
DWORD dwFileName
Definition: CascRootFile_Diablo3.cpp:134
unsigned int DWORD
Definition: CascPort.h:139
DYNAMIC_ARRAY FileNames
Definition: CascRootFile_Diablo3.cpp:152
ENCODING_KEY EncodingKey
Definition: CascRootFile_Diablo3.cpp:70
size_t ItemCountMax
Definition: DynamicArray.h:20
#define ERROR_SUCCESS
Definition: CascPort.h:204
size_t ItemCount
Definition: DynamicArray.h:21

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static void ResolveFullFileNames ( TRootHandler_Diablo3 pRootHandler,
PDIABLO3_CORE_TOC_ENTRY  pCoreTocEntries,
PCASC_MAP  pPackageMap,
LPBYTE  pbCoreTocFile,
DWORD  dwFileIndexes 
)
static
597 {
598  PCASC_FILE_ENTRY pFileEntry;
599  char * szPlainName;
600  char * szNamePtr;
601  size_t nLength;
602  DWORD dwRootIndex;
603  DWORD dwFileIndex;
604  DWORD dwSubIndex;
605  char szShortName[MAX_PATH+1];
606  char szFullName[MAX_PATH+1];
607 
608  // Parse the entire file table
609  for(size_t i = 0; i < pRootHandler->FileTable.ItemCount; i++)
610  {
611  // Retrieve the file entry at n-th position
612  pFileEntry = (PCASC_FILE_ENTRY)Array_ItemAt(&pRootHandler->FileTable, i);
613 
614  // Skip the items that already have full name
615  if(pFileEntry->dwFlags & CASC_ENTRY_SHORT_NAME)
616  {
617  // Retrieve the file index of that file
618  dwRootIndex = INDEX64_ROOT_INDEX(pFileEntry->FileNameHash);
619  dwFileIndex = INDEX64_FILE_INDEX(pFileEntry->FileNameHash);
620  dwSubIndex = (pFileEntry->dwFlags & CASC_ENTRY_HAS_SUBINDEX) ? INDEX64_SUB_INDEX(pFileEntry->FileNameHash) : DIABLO3_INVALID_INDEX;
621  assert(dwFileIndex < dwFileIndexes);
622 
623  // Get the plain name of the file
624  szPlainName = (char *)(pbCoreTocFile + pCoreTocEntries[dwFileIndex].NameOffset);
625 
626  // Create the short file name
627  nLength = CreateShortName(pPackageMap,
628  dwRootIndex,
629  pCoreTocEntries[dwFileIndex].AssetIndex,
630  szPlainName,
631  dwSubIndex,
632  szShortName);
633 
634  // Insert the short name to the list of the names
635  szNamePtr = (char *)Array_Insert(&pRootHandler->FileNames, szShortName, nLength + 1);
636  pFileEntry->dwFileName = (DWORD)Array_IndexOf(&pRootHandler->FileNames, szNamePtr);
637 
638  // Create the full file name
639  nLength = CreateFileName(pRootHandler, szShortName, szFullName);
640  pFileEntry->FileNameHash = CalcFileNameHash(szFullName);
641 
642  // Insert the entry to the name map. Use the mapping of FullName -> FileHash
643  Map_InsertObject(pRootHandler->pRootMap, pFileEntry, &pFileEntry->FileNameHash);
644  }
645  }
646 }
DYNAMIC_ARRAY FileTable
Definition: CascRootFile_Diablo3.cpp:149
ULONGLONG CalcFileNameHash(const char *szFileName)
Definition: Common.cpp:260
#define INDEX64_FILE_INDEX(hash)
Definition: CascRootFile_Diablo3.cpp:49
#define MAX_PATH
Definition: CascPort.h:160
static size_t CreateFileName(TRootHandler_Diablo3 *pRootHandler, const char *szShortName, char *szBuffer)
Definition: CascRootFile_Diablo3.cpp:349
Definition: CascRootFile_Diablo3.cpp:130
DWORD dwFlags
Definition: CascRootFile_Diablo3.cpp:135
#define INDEX64_ROOT_INDEX(hash)
Definition: CascRootFile_Diablo3.cpp:48
static size_t CreateShortName(PCASC_MAP pPackageMap, DWORD dwRootIndex, DWORD dwAssetIndex, const char *szPlainName, DWORD dwSubIndex, char *szBuffer)
Definition: CascRootFile_Diablo3.cpp:278
PCASC_MAP pRootMap
Definition: CascRootFile_Diablo3.cpp:155
#define CASC_ENTRY_HAS_SUBINDEX
Definition: CascRootFile_Diablo3.cpp:40
void * Array_ItemAt(PDYNAMIC_ARRAY pArray, size_t ItemIndex)
Definition: DynamicArray.cpp:81
bool Map_InsertObject(PCASC_MAP pMap, void *pvNewObject, void *pvKey)
Definition: Map.cpp:170
#define DIABLO3_INVALID_INDEX
Definition: CascRootFile_Diablo3.cpp:24
struct _CASC_FILE_ENTRY * PCASC_FILE_ENTRY
DWORD dwFileName
Definition: CascRootFile_Diablo3.cpp:134
void * Array_Insert(PDYNAMIC_ARRAY pArray, const void *NewItems, size_t NewItemCount)
Definition: DynamicArray.cpp:63
unsigned int DWORD
Definition: CascPort.h:139
#define INDEX64_SUB_INDEX(hash)
Definition: CascRootFile_Diablo3.cpp:50
size_t Array_IndexOf(PDYNAMIC_ARRAY pArray, const void *ArrayPtr)
Definition: DynamicArray.cpp:87
DYNAMIC_ARRAY FileNames
Definition: CascRootFile_Diablo3.cpp:152
ULONGLONG FileNameHash
Definition: CascRootFile_Diablo3.cpp:133
#define CASC_ENTRY_SHORT_NAME
Definition: CascRootFile_Diablo3.cpp:39
size_t ItemCount
Definition: DynamicArray.h:21

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

int RootHandler_CreateDiablo3 ( TCascStorage hs,
LPBYTE  pbRootFile,
DWORD  cbRootFile 
)
1080 {
1081  TRootHandler_Diablo3 * pRootHandler;
1082  PCASC_MAP pPackageMap = NULL;
1083  LPBYTE pbRootFileEnd = pbRootFile + cbRootFile;
1084  LPBYTE pbPackagesDat = NULL;
1085  DWORD dwTotalFileCount;
1086  DWORD cbPackagesDat = 0;
1087  int nError;
1088 
1089  // Allocate the root handler object
1090  hs->pRootHandler = pRootHandler = CASC_ALLOC(TRootHandler_Diablo3, 1);
1091  if(pRootHandler == NULL)
1092  return ERROR_NOT_ENOUGH_MEMORY;
1093 
1094  // Fill-in the handler functions
1095  memset(pRootHandler, 0, sizeof(TRootHandler_Diablo3));
1096  pRootHandler->Insert = (ROOT_INSERT)D3Handler_Insert;
1097  pRootHandler->Search = (ROOT_SEARCH)D3Handler_Search;
1098  pRootHandler->EndSearch = (ROOT_ENDSEARCH)D3Handler_EndSearch;
1099  pRootHandler->GetKey = (ROOT_GETKEY)D3Handler_GetKey;
1100  pRootHandler->Close = (ROOT_CLOSE)D3Handler_Close;
1101 
1102  // Fill-in the flags
1103  pRootHandler->dwRootFlags |= ROOT_FLAG_HAS_NAMES;
1104 
1105  // Scan the total number of files in the root directories
1106  // Reserve space for extra files
1107  dwTotalFileCount = ScanDirectoryFile(hs, pbRootFile, pbRootFileEnd);
1108  if(dwTotalFileCount == 0)
1109  return ERROR_FILE_CORRUPT;
1110  dwTotalFileCount += CASC_EXTRA_FILES;
1111 
1112  // Allocate the global linear file table
1113  // Note: This is about 18 MB of memory for Diablo III PTR build 30013
1114  nError = Array_Create(&pRootHandler->FileTable, CASC_FILE_ENTRY, dwTotalFileCount);
1115  if(nError != ERROR_SUCCESS)
1116  return nError;
1117 
1118  // Allocate global buffer for file names.
1119  // The size of the buffer was taken from Diablo III build 30013
1120  nError = Array_Create(&pRootHandler->FileNames, char, 0x01000000);
1121  if(nError != ERROR_SUCCESS)
1122  return nError;
1123 
1124  // Create map of ROOT_ENTRY -> FileEntry
1125  pRootHandler->pRootMap = Map_Create(dwTotalFileCount, sizeof(ULONGLONG), FIELD_OFFSET(CASC_FILE_ENTRY, FileNameHash));
1126  if(pRootHandler->pRootMap == NULL)
1127  return ERROR_NOT_ENOUGH_MEMORY;
1128 
1129  // Parse the ROOT file and insert all entries in the file table
1130  nError = ParseDirectoryFile(pRootHandler, pbRootFile, pbRootFileEnd, DIABLO3_INVALID_INDEX);
1131  if(nError == ERROR_SUCCESS)
1132  {
1133  size_t dwRootEntries = pRootHandler->FileTable.ItemCount;
1134 
1135  // We expect the number of level-0 to be less than maximum
1136  assert(dwRootEntries < DIABLO3_MAX_SUBDIRS);
1137 
1138  // Now parse the all root items and load them
1139  for(size_t i = 0; i < dwRootEntries; i++)
1140  {
1141  PCASC_FILE_ENTRY pRootEntry = (PCASC_FILE_ENTRY)Array_ItemAt(&pRootHandler->FileTable, i);
1142 
1143  // Load the entire file to memory
1144  pbRootFile = LoadFileToMemory(hs, pRootEntry->EncodingKey.Value, &cbRootFile);
1145  if(pbRootFile != NULL)
1146  {
1147  nError = ParseDirectoryFile(pRootHandler, pbRootFile, pbRootFile + cbRootFile, i);
1148  CASC_FREE(pbRootFile);
1149  }
1150  }
1151  }
1152 
1153  // Note: The file "Base\Data_D3\PC\Misc\Packages.dat" contains the names
1154  // of the files (without level-0 and level-1 directory). We can use these
1155  // names for supplying the missing extensions
1156  if(nError == ERROR_SUCCESS)
1157  {
1158  // Load the entire file to memory
1159  pbPackagesDat = LoadFileToMemory(hs, "Base\\Data_D3\\PC\\Misc\\Packages.dat", &cbPackagesDat);
1160  if(pbPackagesDat != NULL)
1161  {
1162  pPackageMap = CreatePackageMap(pbPackagesDat, pbPackagesDat + cbPackagesDat);
1163  }
1164  }
1165 
1166  // Vast majorify of files at this moment don't have names.
1167  // We can load the Base\CoreTOC.dat file in order
1168  // to get directory asset indexes, file names and extensions
1169  if(nError == ERROR_SUCCESS)
1170  {
1171  LPBYTE pbCoreTOC;
1172  DWORD cbCoreTOC = 0;
1173 
1174  // Load the entire file to memory
1175  pbCoreTOC = LoadFileToMemory(hs, "Base\\CoreTOC.dat", &cbCoreTOC);
1176  if(pbCoreTOC != NULL)
1177  {
1178  ParseCoreTOC(pRootHandler, pPackageMap, pbCoreTOC, pbCoreTOC + cbCoreTOC);
1179  CASC_FREE(pbCoreTOC);
1180  }
1181  }
1182 
1183  // Free the packages map
1184  if(pPackageMap != NULL)
1185  Map_Free(pPackageMap);
1186  if(pbPackagesDat != NULL)
1187  CASC_FREE(pbPackagesDat);
1188  return nError;
1189 }
TRootHandler * pRootHandler
Definition: CascCommon.h:223
DYNAMIC_ARRAY FileTable
Definition: CascRootFile_Diablo3.cpp:149
static PCASC_MAP CreatePackageMap(LPBYTE pbPackagesDat, LPBYTE pbPackagesEnd)
Definition: CascRootFile_Diablo3.cpp:380
#define CASC_ALLOC(type, count)
Definition: CascCommon.h:302
unsigned long long ULONGLONG
Definition: CascPort.h:144
static DWORD ScanDirectoryFile(TCascStorage *hs, LPBYTE pbRootFile, LPBYTE pbFileEnd)
Definition: CascRootFile_Diablo3.cpp:756
static LPBYTE D3Handler_GetKey(TRootHandler_Diablo3 *pRootHandler, const char *szFileName)
Definition: CascRootFile_Diablo3.cpp:985
PCASC_MAP Map_Create(DWORD dwMaxItems, DWORD dwKeyLength, DWORD dwKeyOffset)
Definition: Map.cpp:93
LPBYTE(* ROOT_SEARCH)(struct TRootHandler *pRootHandler, struct _TCascSearch *pSearch, PDWORD PtrFileSize, PDWORD PtrLocaleFlags)
Definition: RootHandler.h:36
#define Array_Create(pArray, type, ItemCountMax)
Definition: DynamicArray.h:35
#define CASC_EXTRA_FILES
Definition: CascCommon.h:53
DWORD dwRootFlags
Definition: RootHandler.h:75
#define ERROR_NOT_ENOUGH_MEMORY
Definition: CascPort.h:208
void Map_Free(PCASC_MAP pMap)
Definition: Map.cpp:279
ROOT_GETKEY GetKey
Definition: RootHandler.h:71
ROOT_INSERT Insert
Definition: RootHandler.h:68
void(* ROOT_ENDSEARCH)(struct TRootHandler *pRootHandler, struct _TCascSearch *pSearch)
Definition: RootHandler.h:43
#define ERROR_FILE_CORRUPT
Definition: CascPort.h:218
#define ROOT_FLAG_HAS_NAMES
Definition: RootHandler.h:21
Definition: CascRootFile_Diablo3.cpp:130
arena_t NULL
Definition: jemalloc_internal.h:624
LPBYTE(* ROOT_GETKEY)(struct TRootHandler *pRootHandler, const char *szFileName)
Definition: RootHandler.h:48
#define DIABLO3_MAX_SUBDIRS
Definition: CascRootFile_Diablo3.cpp:22
ENCODING_KEY EncodingKey
Definition: CascRootFile_Diablo3.cpp:132
PCASC_MAP pRootMap
Definition: CascRootFile_Diablo3.cpp:155
BYTE * LPBYTE
Definition: CascPort.h:152
static LPBYTE D3Handler_Search(TRootHandler_Diablo3 *pRootHandler, TCascSearch *pSearch, PDWORD, PDWORD)
Definition: CascRootFile_Diablo3.cpp:949
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
void * Array_ItemAt(PDYNAMIC_ARRAY pArray, size_t ItemIndex)
Definition: DynamicArray.cpp:81
#define DIABLO3_INVALID_INDEX
Definition: CascRootFile_Diablo3.cpp:24
struct _CASC_FILE_ENTRY * PCASC_FILE_ENTRY
ROOT_SEARCH Search
Definition: RootHandler.h:69
#define FIELD_OFFSET(t, f)
Definition: CascPort.h:122
static int ParseDirectoryFile(TRootHandler_Diablo3 *pRootHandler, LPBYTE pbDirFile, LPBYTE pbFileEnd, DWORD dwRootDirIndex)
Definition: CascRootFile_Diablo3.cpp:806
static int D3Handler_Insert(TRootHandler_Diablo3 *pRootHandler, const char *szFileName, LPBYTE pbEncodingKey)
Definition: CascRootFile_Diablo3.cpp:931
static void D3Handler_Close(TRootHandler_Diablo3 *pRootHandler)
Definition: CascRootFile_Diablo3.cpp:995
ROOT_ENDSEARCH EndSearch
Definition: RootHandler.h:70
unsigned int DWORD
Definition: CascPort.h:139
Definition: Map.h:19
Definition: CascRootFile_Diablo3.cpp:146
int(* ROOT_INSERT)(struct TRootHandler *pRootHandler, const char *szFileName, LPBYTE pbEncodingKey)
Definition: RootHandler.h:30
static int ParseCoreTOC(TRootHandler_Diablo3 *pRootHandler, PCASC_MAP pPackageMap, LPBYTE pbCoreTocFile, LPBYTE pbCoreTocEnd)
Definition: CascRootFile_Diablo3.cpp:862
BYTE Value[MD5_HASH_SIZE]
Definition: CascCommon.h:98
DYNAMIC_ARRAY FileNames
Definition: CascRootFile_Diablo3.cpp:152
static void D3Handler_EndSearch(TRootHandler_Diablo3 *, TCascSearch *)
Definition: CascRootFile_Diablo3.cpp:980
void(* ROOT_CLOSE)(struct TRootHandler *pRootHandler)
Definition: RootHandler.h:62
ROOT_CLOSE Close
Definition: RootHandler.h:73
#define ERROR_SUCCESS
Definition: CascPort.h:204
size_t ItemCount
Definition: DynamicArray.h:21
static LPBYTE LoadFileToMemory(TCascStorage *hs, LPBYTE pbEncodingKey, DWORD *pcbFileData)
Definition: CascRootFile_Diablo3.cpp:648

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static DWORD ScanDirectoryFile ( TCascStorage hs,
LPBYTE  pbRootFile,
LPBYTE  pbFileEnd 
)
static
760 {
761  PDIABLO3_NAMED_ENTRY pNamedEntry;
762  DIABLO3_DIR_HEADER RootHeader;
763  DIABLO3_DIR_HEADER DirHeader;
764  LPBYTE pbSubDir;
765  DWORD dwTotalFileCount;
766  DWORD cbNamedEntry;
767  DWORD cbSubDir;
768  int nError;
769 
770  // Parse the directory header in order to retrieve the items
771  nError = ParseDirectoryHeader(&RootHeader, pbRootFile, pbFileEnd);
772  if(nError != ERROR_SUCCESS)
773  return 0;
774 
775  // Add the root directory's entries
776  dwTotalFileCount = RootHeader.dwEntries1 + RootHeader.dwEntries2 + RootHeader.dwEntries3;
777 
778  // Parse the named entries
779  for(DWORD i = 0; i < RootHeader.dwEntries3; i++)
780  {
781  // Get the this named entry
782  if((cbNamedEntry = VerifyNamedFileEntry(RootHeader.pbEntries3, pbFileEnd)) == 0)
783  return 0;
784  pNamedEntry = (PDIABLO3_NAMED_ENTRY)RootHeader.pbEntries3;
785  RootHeader.pbEntries3 += cbNamedEntry;
786 
787  // Load the subdirectory to memory
788  pbSubDir = LoadFileToMemory(hs, pNamedEntry->EncodingKey.Value, &cbSubDir);
789  if(pbSubDir != NULL)
790  {
791  // Count the files in the subdirectory
792  if(ParseDirectoryHeader(&DirHeader, pbSubDir, pbSubDir + cbSubDir) == ERROR_SUCCESS)
793  {
794  dwTotalFileCount += DirHeader.dwEntries1 + DirHeader.dwEntries2 + DirHeader.dwEntries3;
795  }
796 
797  // Free the subdirectory
798  CASC_FREE(pbSubDir);
799  }
800  }
801 
802  // Return the total number of entries
803  return dwTotalFileCount;
804 }
DWORD dwEntries3
Definition: CascRootFile_Diablo3.cpp:100
DWORD dwEntries2
Definition: CascRootFile_Diablo3.cpp:99
struct _DIABLO3_NAMED_ENTRY * PDIABLO3_NAMED_ENTRY
static DWORD VerifyNamedFileEntry(LPBYTE pbNamedEntry, LPBYTE pbFileEnd)
Definition: CascRootFile_Diablo3.cpp:248
arena_t NULL
Definition: jemalloc_internal.h:624
static int ParseDirectoryHeader(PDIABLO3_DIR_HEADER pDirHeader, LPBYTE pbDirFile, LPBYTE pbFileEnd)
Definition: CascRootFile_Diablo3.cpp:695
BYTE * LPBYTE
Definition: CascPort.h:152
#define CASC_FREE(ptr)
Definition: CascCommon.h:303
Definition: CascRootFile_Diablo3.cpp:68
unsigned int DWORD
Definition: CascPort.h:139
DWORD dwEntries1
Definition: CascRootFile_Diablo3.cpp:98
BYTE Value[MD5_HASH_SIZE]
Definition: CascCommon.h:98
ENCODING_KEY EncodingKey
Definition: CascRootFile_Diablo3.cpp:70
Definition: CascRootFile_Diablo3.cpp:93
LPBYTE pbEntries3
Definition: CascRootFile_Diablo3.cpp:97
#define ERROR_SUCCESS
Definition: CascPort.h:204
static LPBYTE LoadFileToMemory(TCascStorage *hs, LPBYTE pbEncodingKey, DWORD *pcbFileData)
Definition: CascRootFile_Diablo3.cpp:648

+ Here is the call graph for this function:

+ Here is the caller graph for this function:

static DWORD VerifyNamedFileEntry ( LPBYTE  pbNamedEntry,
LPBYTE  pbFileEnd 
)
static
249 {
250  LPBYTE pbFileName = ((PDIABLO3_NAMED_ENTRY)pbNamedEntry)->szFileName;
251 
252  // Find the end of the name
253  while(pbFileName < pbFileEnd && pbFileName[0] != 0)
254  pbFileName++;
255 
256  // Did we get past the end of the root file?
257  if(pbFileName >= pbFileEnd)
258  return 0;
259  pbFileName++;
260 
261  // Return the length of the structure
262  return (DWORD)(pbFileName - pbNamedEntry);
263 }
struct _DIABLO3_NAMED_ENTRY * PDIABLO3_NAMED_ENTRY
BYTE * LPBYTE
Definition: CascPort.h:152
unsigned int DWORD
Definition: CascPort.h:139

+ Here is the caller graph for this function:

Variable Documentation

const DIABLO3_ASSET_INFO Assets[]
static
const DIABLO3_ASSET_INFO UnknownAsset = {"Unknown", "xxx"}
static