aboutsummaryrefslogtreecommitdiff
path: root/dep/CascLib
diff options
context:
space:
mode:
Diffstat (limited to 'dep/CascLib')
-rw-r--r--dep/CascLib/src/CascCommon.h5
-rw-r--r--dep/CascLib/src/CascDecrypt.cpp287
-rw-r--r--dep/CascLib/src/CascDumpData.cpp2
-rw-r--r--dep/CascLib/src/CascFiles.cpp72
-rw-r--r--dep/CascLib/src/CascFindFile.cpp2
-rw-r--r--dep/CascLib/src/CascIndexFiles.cpp84
-rw-r--r--dep/CascLib/src/CascLib.h70
-rw-r--r--dep/CascLib/src/CascOpenStorage.cpp68
-rw-r--r--dep/CascLib/src/CascPort.h61
-rw-r--r--dep/CascLib/src/CascReadFile.cpp24
-rw-r--r--dep/CascLib/src/DllMain.rc8
-rw-r--r--dep/CascLib/src/common/Common.cpp50
-rw-r--r--dep/CascLib/src/common/Common.h39
-rw-r--r--dep/CascLib/src/common/Csv.cpp2
-rw-r--r--dep/CascLib/src/common/Csv.h2
-rw-r--r--dep/CascLib/src/common/Directory.cpp6
-rw-r--r--dep/CascLib/src/common/FileStream.cpp238
-rw-r--r--dep/CascLib/src/common/FileStream.h9
-rw-r--r--dep/CascLib/src/common/FileTree.cpp8
-rw-r--r--dep/CascLib/src/common/ListFile.cpp2
-rw-r--r--dep/CascLib/src/common/ListFile.h2
-rw-r--r--dep/CascLib/src/md5/md5.cpp86
22 files changed, 791 insertions, 336 deletions
diff --git a/dep/CascLib/src/CascCommon.h b/dep/CascLib/src/CascCommon.h
index 7700c782cbf..8ef9d557a51 100644
--- a/dep/CascLib/src/CascCommon.h
+++ b/dep/CascLib/src/CascCommon.h
@@ -207,7 +207,7 @@ typedef struct _CASC_FILE_FRAME
CONTENT_KEY FrameHash; // MD5 hash of the file frame
ULONGLONG StartOffset; // Starting offset of the file span
ULONGLONG EndOffset; // Ending offset of the file span
- DWORD DataFileOffset; // Offset in the data file (data.###)
+ ULONGLONG DataFileOffset; // Offset in the data file (data.###)
DWORD EncodedSize; // Encoded size of the frame
DWORD ContentSize; // Content size of the frame
} CASC_FILE_FRAME, *PCASC_FILE_FRAME;
@@ -275,6 +275,7 @@ struct TCascStorage
// Class members
PCASC_OPEN_STORAGE_ARGS pArgs; // Open storage arguments. Only valid during opening the storage
+ CASC_LOCK StorageLock; // Lock for multi-threaded operations
LPCTSTR szIndexFormat; // Format of the index file name
LPTSTR szCodeName; // On local storage, this select a product in a multi-product storage. For online storage, this selects a product
@@ -285,6 +286,7 @@ struct TCascStorage
LPTSTR szCdnServers; // Multi-SZ list of CDN servers
LPTSTR szCdnPath; // Remote CDN sub path for the product
LPSTR szRegion; // Product region. Only when "versions" is used as storage root file
+ LPSTR szBuildKey; // Product build key, aka MD5 of the build file
DWORD dwDefaultLocale; // Default locale, read from ".build.info"
DWORD dwBuildNumber; // Product build number
DWORD dwRefCount; // Number of references
@@ -330,7 +332,6 @@ struct TCascStorage
CASC_ARRAY ExtraKeysList; // List additional encryption keys
CASC_MAP EncryptionKeys; // Map of encryption keys
ULONGLONG LastFailKeyName; // The value of the encryption key that recently was NOT found.
-
};
struct TCascFile
diff --git a/dep/CascLib/src/CascDecrypt.cpp b/dep/CascLib/src/CascDecrypt.cpp
index 308be6cab46..ccce1fc0a5b 100644
--- a/dep/CascLib/src/CascDecrypt.cpp
+++ b/dep/CascLib/src/CascDecrypt.cpp
@@ -48,8 +48,8 @@ static CASC_ENCRYPTION_KEY CascKeys[] =
// { 0xD0CAE11366CEEA83ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? }}, // 1.12.3.2609 (build 45364)
// Warcraft III Reforged beta (build)
- { 0x6E4296823E7D561EULL, { 0xC0, 0xBF, 0xA2, 0x94, 0x3A, 0xC3, 0xE9, 0x22, 0x86, 0xE4, 0x44, 0x3E, 0xE3, 0x56, 0x0D, 0x65 }}, // Build 13369
- { 0xE04D60E31DDEBF63ULL, { 0x26, 0x3D, 0xB5, 0xC4, 0x02, 0xDA, 0x8D, 0x4D, 0x68, 0x63, 0x09, 0xCB, 0x2E, 0x32, 0x54, 0xD0 }}, // Build 13445
+ { 0x6E4296823E7D561EULL, { 0xC0, 0xBF, 0xA2, 0x94, 0x3A, 0xC3, 0xE9, 0x22, 0x86, 0xE4, 0x44, 0x3E, 0xE3, 0x56, 0x0D, 0x65 }}, // 1.32.0.13369 Base content (Beta Week 0)
+ { 0xE04D60E31DDEBF63ULL, { 0x26, 0x3D, 0xB5, 0xC4, 0x02, 0xDA, 0x8D, 0x4D, 0x68, 0x63, 0x09, 0xCB, 0x2E, 0x32, 0x54, 0xD0 }}, // 1.32.0.13445 Base content (Beta Week 1)
// Overwatch
{ 0xFB680CB6A8BF81F3ULL, { 0x62, 0xD9, 0x0E, 0xFA, 0x7F, 0x36, 0xD7, 0x1C, 0x39, 0x8A, 0xE2, 0xF1, 0xFE, 0x37, 0xBD, 0xB9 } }, // 0.8.0.24919_retailx64 (hardcoded)
@@ -222,7 +222,7 @@ static CASC_ENCRYPTION_KEY CascKeys[] =
{ 0x14C4257E557B49A1ULL, { 0x06, 0x4A, 0x97, 0x09, 0xF4, 0x2D, 0x50, 0xCB, 0x5F, 0x8B, 0x94, 0xBC, 0x1A, 0xCF, 0xDD, 0x5D } }, // 242 WOW-28440patch8.1.0_PTR dor cinematic
{ 0x1254E65319C6EEFFULL, { 0x79, 0xD2, 0xB3, 0xD1, 0xCC, 0xB0, 0x15, 0x47, 0x4E, 0x71, 0x58, 0x81, 0x38, 0x64, 0xB8, 0xE6 } }, // 243 WOW-28440patch8.1.0_PTR akt cinematic
{ 0xC8753773ADF1174CULL, { 0x1E, 0x0E, 0x37, 0xD4, 0x2E, 0xE5, 0xCE, 0x5E, 0x80, 0x67, 0xF0, 0x39, 0x4B, 0x09, 0x05, 0xF2 } }, // 244 WOW-28938patch8.1.5_PTR Obsidian Worldbreaker mount & Lil' Nefarian pet
-// { 0x2170BCAA9FA96E22ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 245 WOW-28938patch8.1.5_PTR alpaca mount
+ { 0x2170BCAA9FA96E22ULL, { 0x6D, 0xDA, 0x6D, 0x48, 0xD7, 0x2D, 0xC8, 0x00, 0x5D, 0xB9, 0xDC, 0x15, 0x36, 0x8D, 0x35, 0xBC } }, // 245 WOW-28938patch8.1.5_PTR baby alpaca pet
// { 0x75485627AA225F4DULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 246 WOW-28938patch8.1.5_PTR fdid 2741546, 2741548, 2741549
{ 0x08717B15BF3C7955ULL, { 0x4B, 0x06, 0xBF, 0x9D, 0x17, 0x66, 0x3C, 0xEB, 0x33, 0x12, 0xEA, 0x3C, 0x69, 0xFB, 0xC5, 0xDD } }, // 248 WOW-29220patch8.1.5_PTR inv_encrypted20.blp (fdid 2823166)
// { 0xD19DCF7ACA8D96D6ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 249 WOW-30080patch8.2.0_PTR starts at fdid 2843110, 10 files
@@ -233,35 +233,296 @@ static CASC_ENCRYPTION_KEY CascKeys[] =
{ 0x6A026290FBDB3754ULL, { 0x3D, 0x2D, 0x62, 0x08, 0x50, 0xA6, 0x76, 0x5D, 0xD5, 0x91, 0x22, 0x4F, 0x60, 0x5B, 0x94, 0x9A } }, // 255 WOW-30080patch8.2.0_PTR BlizzCon 2019 - Wendigo transmog set
{ 0xCF72FD04608D36EDULL, { 0xA0, 0xA8, 0x89, 0x97, 0x6D, 0x02, 0xFA, 0x8D, 0x00, 0xF7, 0xAF, 0x00, 0x17, 0xAD, 0x72, 0x1F } }, // 257 WOW-30262patch8.2.0_PTR Azshara Warbringer cinematic (5 files)
{ 0x17F07C2E3A45DB3DULL, { 0x6D, 0x38, 0x86, 0xBD, 0xB9, 0x1E, 0x71, 0x5A, 0xE7, 0x18, 0x2D, 0x9F, 0x3A, 0x08, 0xF2, 0xC9 } }, // 258 WOW-30262patch8.2.0_PTR Solesa Naksu Nazjatar phase (34 files)
-// { 0xDFAB5841B87802B5ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 259 WOW-31337patch8.2.5_PTR starts at fdid 3016206, 8 files, 3016206 is a creature
+ { 0xDFAB5841B87802B5ULL, { 0xF3, 0x7E, 0x96, 0xED, 0x8A, 0x1F, 0x8D, 0x85, 0x2F, 0x07, 0x5D, 0xDE, 0x37, 0xC7, 0x13, 0x27 } }, // 259 WOW-31337patch8.2.5_PTR Ratmount2 Flying Rat Mount
{ 0xC050FA06BB0538F6ULL, { 0xC5, 0x52, 0xF5, 0xD0, 0xB7, 0x22, 0x31, 0x50, 0x2D, 0x25, 0x47, 0x31, 0x4E, 0x60, 0x15, 0xF7 } }, // 260 WOW-30495patch8.2.0_PTR Crossroads cinematic (5 files)
{ 0xAB5CDD3FC321831FULL, { 0xE1, 0x38, 0x4F, 0x5B, 0x06, 0xEB, 0xBC, 0xD3, 0x33, 0x69, 0x5A, 0xA6, 0xFF, 0xC6, 0x83, 0x18 } }, // 261 WOW-30495patch8.2.0_PTR Azshara kill cinematic (5 files)
{ 0xA7B7D1F12395040EULL, { 0x36, 0xAD, 0x3B, 0x31, 0x27, 0x3F, 0x1E, 0xBC, 0xEE, 0x85, 0x20, 0xAA, 0xA7, 0x4B, 0x12, 0xF2 } }, // 262 WOW-30495patch8.2.0_PTR Nazjatar intro cinematics (9 files)
{ 0x83A2AB72DD8AE992ULL, { 0x02, 0x3C, 0xFF, 0x06, 0x2B, 0x19, 0xA5, 0x29, 0xB9, 0xF1, 0x4F, 0x9B, 0x7A, 0xAA, 0xC5, 0xBB } }, // 263 WOW-31337patch8.2.5_PTR 8.2.5 War Campaign scenario/models
{ 0xBEAF567CC45362F0ULL, { 0x8B, 0xD3, 0xED, 0x79, 0x24, 0x05, 0xD9, 0xEE, 0x74, 0x2B, 0xF6, 0xAF, 0xA9, 0x44, 0x57, 0x8A } }, // 264 WOW-31337patch8.2.5_PTR 8.2.5 War Campaign quests/vo
{ 0x7BB3A77FD8D14783ULL, { 0x4C, 0x94, 0xE3, 0x60, 0x9C, 0xFE, 0x0A, 0x82, 0x00, 0x0A, 0x0B, 0xD4, 0x60, 0x69, 0xAC, 0x6F } }, // 265 WOW-31337patch8.2.5_PTR 8.2.5 War Campaign epilogue quests
- { 0x8F4098E2470FE0C8ULL, { 0xAA, 0x71, 0x8D, 0x1F, 0x1A, 0x23, 0x07, 0x8D, 0x49, 0xAD, 0x0C, 0x60, 0x6A, 0x72, 0xF3, 0xD5 } }, // 266 WOW-31337patch8.2.5_PTR 8.2.5 War Campaign epilogue in-game cinematic
-// { 0x6AC5C837A2027A6BULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 267 WOW-31337patch8.2.5_PTR starts at fdid 3037834, 263 files, 3037834 & 3040716 are creatures
+ { 0x8F4098E2470FE0C8ULL, { 0xAA, 0x71, 0x8D, 0x1F, 0x1A, 0x23, 0x07, 0x8D, 0x49, 0xAD, 0x0C, 0x60, 0x6A, 0x72, 0xF3, 0xD5 } }, // 266 WOW-31337patch8.2.5_PTR 8.2.5 War Campaign epilogue in-game cinematic5
+ { 0x6AC5C837A2027A6BULL, { 0xB0, 0xB7, 0xCE, 0x09, 0x17, 0x63, 0xD1, 0x5E, 0x7F, 0x69, 0xA8, 0xE2, 0x34, 0x2C, 0xDD, 0x7C } }, // 267 WOW-31337patch8.2.5_PTR Shadowlands CE rewards
{ 0x302AAD8B1F441D95ULL, { 0x24, 0xB8, 0x64, 0x38, 0xCF, 0x02, 0x53, 0x86, 0x49, 0xE5, 0xBA, 0x67, 0x2F, 0xD5, 0x99, 0x3A } }, // 271 WOW-31337patch8.2.5_PTR RaF mounts & armor
// { 0x5C909F00088734B9ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 272 WOW-31337patch8.2.5_PTR Unused in 8.2.5
-// { 0xF785977C76DE9C77ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 273 WOW-31337patch8.2.5_PTR starts at fdid 3071600, 313 files, Winter Veil?
-// { 0x1CDAF3931871BEC3ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 275 WOW-31337patch8.2.5_PTR unknown toy/achievement, 28 files
+ { 0xF785977C76DE9C77ULL, { 0x7F, 0x3C, 0x19, 0x51, 0xF5, 0x28, 0x3A, 0x18, 0xC1, 0xC6, 0xD4, 0x5B, 0x68, 0x67, 0xB5, 0x1A } }, // 273 WOW-31337patch8.2.5_PTR Starts at fdid 3071600, 313 files, Winter Veil?
+ { 0x1CDAF3931871BEC3ULL, { 0x66, 0xB4, 0xD3, 0x4A, 0x3A, 0xF3, 0x0E, 0x5E, 0xB7, 0xF4, 0x14, 0xF6, 0xC3, 0x0A, 0xAF, 0x4F } }, // 275 WOW-31337patch8.2.5_PTR Winter Veil 2019 toy/achievement (28 files)
{ 0x814E1AB43F3F9345ULL, { 0xB6, 0x5E, 0x2A, 0x63, 0xA1, 0x16, 0xAA, 0x25, 0x1F, 0xA5, 0xD7, 0xB0, 0xBA, 0xAB, 0xF7, 0x78 } }, // 276 WOW-31599patch8.2.5_PTR The Negotiation cinematic (5 files)
{ 0x1FBE97A317FFBEFAULL, { 0xBD, 0x71, 0xF7, 0x8D, 0x43, 0x11, 0x7C, 0x68, 0x72, 0x4B, 0xB6, 0xE0, 0xD9, 0x57, 0x7E, 0x08 } }, // 277 WOW-31599patch8.2.5_PTR Reckoning cinematic (5 files)
+// { 0x30581F81528FB27CULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 278 WOW-32044patch8.3.0_PTR Contains creature that uses monkey sounds
// { 0x4287F49A5BB366DAULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 279 WOW-31599patch8.2.5_PTR Unused in 8.2.5
+ { 0xD134F430A45C1CF2ULL, { 0x54, 0x3D, 0xA7, 0x84, 0xD4, 0xBD, 0x24, 0x28, 0xCF, 0xB5, 0xEB, 0xFE, 0xBA, 0x76, 0x2A, 0x90 } }, // 280 WOW-32044patch8.3.0_PTR Encrypted map w/ Icecrown assets, Darion Mograine VO
// { 0x01C82EE0725EDA3AULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 281 WOW-31812patch8.2.5_PTR Unused in 8.2.5
// { 0x04C0C50B5BE0CC78ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 282 WOW-31812patch8.2.5_PTR Unused in 8.2.5
// { 0xA26FD104489B3DE5ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 283 WOW-31812patch8.2.5_PTR Unused in 8.2.5
+// { 0xEA6C3B8F210A077FULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 284 WOW-32044patch8.3.0_PTR 18 files, 3159888 is a creature that uses gronn sounds, likely a mount
+// { 0x4A738212694AD0B6ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 285 WOW-32044patch8.3.0_PTR Unused in 32044
+// { 0x2A430C60DDCC75FFULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 286 WOW-32044patch8.3.0_PTR 254 files, appears to be items
+ { 0x0A096FB251CFF471ULL, { 0x05, 0xC7, 0x59, 0x12, 0xEC, 0xFF, 0x04, 0x0F, 0x85, 0xFB, 0x46, 0x97, 0xC9, 0x9C, 0x77, 0x03 } }, // 287 WOW-32414patch8.3.0_PTR In-game scene & VO
+// { 0x205AFFCDFBA639CBULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 288 WOW-32414patch8.3.0_PTR
+ { 0x32B62CF10571971FULL, { 0x18, 0xB8, 0x3F, 0xDD, 0x5E, 0x4B, 0x39, 0x7F, 0xB8, 0x9B, 0xB5, 0x72, 0x46, 0x75, 0xCC, 0xBA } }, // 289 WOW-32489patch8.3.0_PTR In-game Wrathion scene
+// { 0xB408D6CDE8E0D4C1ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 290 WOW-33978patch9.0.1_Beta
+ { 0x1DBE03EF5A0059E1ULL, { 0xD6, 0x3B, 0x26, 0x3C, 0xB1, 0xC7, 0xE8, 0x56, 0x23, 0xCC, 0x42, 0x58, 0x79, 0xCC, 0x59, 0x2D } }, // 294 WOW-32489patch8.3.0_PTR Cinematic
+ { 0x29D08CEA080FDB84ULL, { 0x06, 0x51, 0x32, 0xA6, 0x42, 0x8B, 0x19, 0xDF, 0xCB, 0x2B, 0x68, 0x94, 0x8B, 0xE9, 0x58, 0xF5 } }, // 295 WOW-32489patch8.3.0_PTR Cinematic
+ { 0x3FE91B3FD7F18B37ULL, { 0xC9, 0x13, 0xB1, 0xC2, 0x0D, 0xAE, 0xC8, 0x04, 0xE9, 0xF8, 0xD3, 0x52, 0x7F, 0x2A, 0x05, 0xF7 } }, // 296 WOW-32489patch8.3.0_PTR Cinematic
+// { 0xF7BECC6682B9EF36ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 297 WOW-33978patch9.0.1_Beta
+// { 0xDCB5C5DC78520BD6ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 298 WOW-33978patch9.0.1_Beta
+// { 0x566DF4A5A9E3341FULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 299 WOW-33978patch9.0.1_Beta
+// { 0x9183F8AAA603704DULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 300 WOW-33978patch9.0.1_Beta
+// { 0x856D38B447512C51ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 301 WOW-33978patch9.0.1_Beta
+// { 0x1D0614B43A9D6DF9ULL, { 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x??, 0x?? } }, // 302 WOW-33978patch9.0.1_Beta
+ { 0x00179EB433442A73ULL, { 0xD4, 0x1D, 0x69, 0x4C, 0x0D, 0xF8, 0x63, 0x10, 0x5C, 0x53, 0x49, 0xFD, 0x4F, 0xFB, 0xC2, 0x56 } }, // WOW-33978patch9.0.1_Beta
+ { 0x033DBFE564685CF6ULL, { 0xA1, 0xE3, 0xB2, 0x4B, 0xFE, 0x85, 0x78, 0xC0, 0x3D, 0x0F, 0xCC, 0x7F, 0x19, 0xE6, 0xD0, 0x69 } }, // WOW-33978patch9.0.1_Beta
+ { 0x05EC085870DF2AF0ULL, { 0x31, 0xE6, 0xAB, 0x03, 0xA0, 0x9E, 0x68, 0xC8, 0xFB, 0x55, 0xBF, 0x19, 0x5E, 0x1F, 0x1B, 0x99 } }, // WOW-33978patch9.0.1_Beta
+ { 0x0626C885AF0EEF65ULL, { 0x55, 0x7E, 0xC9, 0x97, 0xAD, 0x64, 0x62, 0x1C, 0xFE, 0x2B, 0x3D, 0x79, 0xA5, 0xB7, 0x50, 0x65 } }, // WOW-33978patch9.0.1_Beta
+ { 0x070994B8FE881897ULL, { 0xA5, 0x4A, 0x65, 0x23, 0x5D, 0x6D, 0x64, 0x87, 0x27, 0x7C, 0x36, 0x10, 0xBA, 0x84, 0xAB, 0xF5 } }, // WOW-33978patch9.0.1_Beta
+ { 0x0811E03FCFB84903ULL, { 0x6E, 0x56, 0x77, 0x05, 0x1E, 0xE0, 0x92, 0xA5, 0x7C, 0xF6, 0x56, 0xE1, 0xC5, 0x00, 0x2F, 0xFC } }, // WOW-33978patch9.0.1_Beta
+ { 0x0993C8311127F20EULL, { 0xE9, 0x53, 0xC3, 0x57, 0x4C, 0x3E, 0xE5, 0x43, 0xD9, 0xF5, 0x52, 0xED, 0xC8, 0x2F, 0x20, 0xE9 } }, // WOW-33978patch9.0.1_Beta
+ { 0x0A5E25A024FBA6B1ULL, { 0xBB, 0x8F, 0x7B, 0x18, 0x15, 0x09, 0xA9, 0x31, 0x7B, 0xE1, 0x59, 0x26, 0x34, 0x62, 0xF2, 0x8D } }, // WOW-33978patch9.0.1_Beta
+ { 0x0C15F03D0FE27E48ULL, { 0x74, 0x33, 0x79, 0x1B, 0xF3, 0x45, 0x89, 0xEB, 0x64, 0x32, 0x99, 0x7E, 0x10, 0xA2, 0x54, 0x22 } }, // WOW-33978patch9.0.1_Beta
+ { 0x0C2D617E60368120ULL, { 0x94, 0xB8, 0x12, 0x27, 0x1D, 0x6D, 0xE6, 0xC3, 0x18, 0x14, 0x40, 0xD0, 0xAA, 0x27, 0x65, 0x3D } }, // WOW-33978patch9.0.1_Beta
+ { 0x0C49BD78283973B0ULL, { 0x34, 0xB5, 0xBC, 0x69, 0xC1, 0x2A, 0xA3, 0x7A, 0xD7, 0x12, 0x9B, 0x7E, 0x28, 0xC1, 0xDA, 0x58 } }, // WOW-33978patch9.0.1_Beta
+ { 0x0CA696AE84A34281ULL, { 0x9E, 0x0C, 0xBF, 0x53, 0x20, 0x5A, 0x20, 0x64, 0x3A, 0x92, 0x30, 0xE9, 0x4E, 0xCB, 0x0E, 0x3E } }, // WOW-33978patch9.0.1_Beta
+ { 0x0D069101292C9EF9ULL, { 0x11, 0x6A, 0x8D, 0x4C, 0x1B, 0xA6, 0x65, 0xE1, 0x55, 0x52, 0xCA, 0x69, 0xCD, 0x7C, 0xB3, 0x67 } }, // WOW-33978patch9.0.1_Beta
+ { 0x0DE2CF914415467AULL, { 0xAF, 0x90, 0xC0, 0x00, 0x65, 0x47, 0xCA, 0x72, 0x72, 0x34, 0xC7, 0xAF, 0xA3, 0xAB, 0xA8, 0xA7 } }, // WOW-33978patch9.0.1_Beta
+ { 0x0DFACE33557D5092ULL, { 0x61, 0x54, 0x99, 0x41, 0x94, 0x26, 0x6E, 0xEF, 0x93, 0xD7, 0x5F, 0x2C, 0x23, 0xEA, 0x52, 0xB5 } }, // WOW-33978patch9.0.1_Beta
+ { 0x0FC6144903CFC12BULL, { 0x3B, 0x15, 0xF8, 0x9E, 0x91, 0x2F, 0xE4, 0x3D, 0x89, 0x64, 0x3D, 0xCB, 0xA9, 0x45, 0xE5, 0xCD } }, // WOW-33978patch9.0.1_Beta
+ { 0x100C57C7D8B42E58ULL, { 0x24, 0xF7, 0x54, 0x23, 0x09, 0x73, 0x46, 0xC7, 0x92, 0x7F, 0x14, 0x51, 0x93, 0xB6, 0xD5, 0xFE } }, // WOW-33978patch9.0.1_Beta
+ { 0x1108F594E9F5BCB7ULL, { 0x47, 0x80, 0xC7, 0xB3, 0x7A, 0x42, 0xFA, 0x64, 0xD4, 0x90, 0xFB, 0xB6, 0xDE, 0xE9, 0x30, 0xDC } }, // WOW-33978patch9.0.1_Beta
+ { 0x13DA86340D87FEB9ULL, { 0x55, 0x24, 0xD9, 0x49, 0x18, 0x52, 0x37, 0x1F, 0x19, 0x15, 0xCC, 0x1F, 0xDF, 0xD0, 0x53, 0xD1 } }, // WOW-33978patch9.0.1_Beta
+ { 0x141A5383D3AEEB59ULL, { 0xD5, 0xDF, 0xE7, 0x38, 0x99, 0xD2, 0x86, 0xE3, 0x02, 0x2F, 0xAC, 0xAD, 0x3E, 0x70, 0x4B, 0xE3 } }, // WOW-33978patch9.0.1_Beta
+ { 0x1423888694CDE5FCULL, { 0xE7, 0xFA, 0x1C, 0xD3, 0x4A, 0xEA, 0xB1, 0xB6, 0x1B, 0x0A, 0x6C, 0x9E, 0xA6, 0xA9, 0x04, 0x08 } }, // WOW-33978patch9.0.1_Beta
+ { 0x153616FF38D5E460ULL, { 0x0A, 0x94, 0x08, 0xA4, 0x9A, 0x1C, 0xE0, 0x5B, 0x90, 0x30, 0x4D, 0x01, 0x7D, 0xE7, 0x58, 0x92 } }, // WOW-33978patch9.0.1_Beta
+ { 0x15D5A13976DCBD05ULL, { 0xD1, 0x7D, 0x19, 0xEE, 0x14, 0xF7, 0xDD, 0x88, 0x0F, 0x0E, 0xF6, 0xCE, 0x64, 0x44, 0x54, 0xBE } }, // WOW-33978patch9.0.1_Beta
+ { 0x15FA2DA0B33C39EEULL, { 0xA2, 0x94, 0x10, 0xBB, 0x93, 0x1D, 0xA3, 0xE7, 0x84, 0x85, 0x96, 0xFB, 0xA7, 0x7F, 0x50, 0x37 } }, // WOW-33978patch9.0.1_Beta
+ { 0x17ABC9D27E24B4D7ULL, { 0xFA, 0x41, 0x45, 0x70, 0x62, 0x60, 0x5A, 0x17, 0x3D, 0x10, 0xFB, 0x90, 0xE0, 0x77, 0x9A, 0x44 } }, // WOW-33978patch9.0.1_Beta
+ { 0x188E37F5AB501082ULL, { 0xE5, 0x66, 0x96, 0x36, 0x09, 0x3C, 0xE1, 0xB8, 0x99, 0x75, 0x6B, 0xE6, 0x9B, 0x8C, 0x2C, 0x58 } }, // WOW-33978patch9.0.1_Beta
+ { 0x18C32E5601F89AC3ULL, { 0xC8, 0x64, 0x03, 0x2D, 0x3E, 0x9D, 0xA9, 0x29, 0xF9, 0xFE, 0xC6, 0xE5, 0xB5, 0x38, 0x94, 0xA1 } }, // WOW-33978patch9.0.1_Beta
+ { 0x1A16C07D5F35124FULL, { 0x34, 0xAB, 0xF6, 0xA4, 0x68, 0x69, 0xE0, 0x0C, 0xBB, 0x83, 0x94, 0x7C, 0xFD, 0x6A, 0x39, 0x47 } }, // WOW-33978patch9.0.1_Beta
+ { 0x1A4F317C88C93C04ULL, { 0xFF, 0x16, 0x9D, 0x5A, 0xB8, 0x13, 0x5D, 0x38, 0xEC, 0x92, 0xFE, 0xAB, 0xEE, 0x0E, 0x39, 0x7B } }, // WOW-33978patch9.0.1_Beta
+ { 0x1ABF6A7265BBC7AFULL, { 0x9E, 0x12, 0x7C, 0xE7, 0x16, 0x69, 0x1C, 0x50, 0xB5, 0xD4, 0x95, 0x9D, 0xAD, 0xA8, 0xEB, 0xEC } }, // WOW-33978patch9.0.1_Beta
+ { 0x1BD281160FB552FDULL, { 0xEA, 0x57, 0x6F, 0x20, 0xAA, 0x9A, 0xF5, 0x8A, 0x76, 0xF4, 0xB8, 0x43, 0xF5, 0x3A, 0x8E, 0x5D } }, // WOW-33978patch9.0.1_Beta
+ { 0x1BE9A4EEC5B455C5ULL, { 0xBA, 0xFC, 0x5C, 0xC3, 0x9B, 0xDD, 0xC1, 0xD8, 0x02, 0xBA, 0x07, 0x46, 0x41, 0x42, 0x7D, 0x68 } }, // WOW-33978patch9.0.1_Beta
+ { 0x1DCF36E171124EFCULL, { 0xC6, 0x59, 0x7A, 0xA9, 0x76, 0x98, 0x8B, 0xD4, 0xCF, 0x57, 0xB8, 0x33, 0x04, 0xDA, 0x19, 0x34 } }, // WOW-33978patch9.0.1_Beta
+ { 0x1E47BD8DB4D6032FULL, { 0x0F, 0x81, 0x0C, 0x27, 0xE9, 0x10, 0xA5, 0xFF, 0xD1, 0x47, 0x79, 0x27, 0xE2, 0x40, 0x64, 0x59 } }, // WOW-33978patch9.0.1_Beta
+ { 0x1FB4F1C56721C87EULL, { 0x64, 0x8C, 0x26, 0x55, 0xE0, 0xAF, 0x50, 0xF4, 0x26, 0xC5, 0xCD, 0x2C, 0x4F, 0xD2, 0x21, 0xE7 } }, // WOW-33978patch9.0.1_Beta
+ { 0x225902F0EC8BF0FCULL, { 0x09, 0x81, 0x25, 0xBC, 0x75, 0x9E, 0x47, 0xA4, 0x4F, 0x46, 0x7E, 0xCC, 0x28, 0x48, 0x07, 0x47 } }, // WOW-33978patch9.0.1_Beta
+ { 0x225EADE089BA38D8ULL, { 0xFD, 0x5D, 0x6A, 0x9A, 0xDA, 0x76, 0xC7, 0x06, 0x7A, 0x83, 0xBF, 0x5E, 0x56, 0x92, 0xC6, 0xC3 } }, // WOW-33978patch9.0.1_Beta
+ { 0x22EE6101A078F310ULL, { 0xEC, 0x43, 0x74, 0x15, 0xFA, 0x5B, 0xC5, 0x98, 0x79, 0xBB, 0xAA, 0x5C, 0x5F, 0xF3, 0x6A, 0xCD } }, // WOW-33978patch9.0.1_Beta
+ { 0x23457E4AB5352E38ULL, { 0xEE, 0x3F, 0xDC, 0xA7, 0x8B, 0x42, 0xC0, 0x75, 0x03, 0xEF, 0x98, 0x86, 0xF9, 0x8B, 0xB0, 0x28 } }, // WOW-33978patch9.0.1_Beta
+ { 0x236B38CBE43FC318ULL, { 0x14, 0x89, 0xB7, 0x05, 0x62, 0xD5, 0x6A, 0x60, 0x76, 0x00, 0xFA, 0xA8, 0x0A, 0x5A, 0xFD, 0xEF } }, // WOW-33978patch9.0.1_Beta
+ { 0x264DB70A1A6CC720ULL, { 0x94, 0x88, 0x48, 0x13, 0x6B, 0xDD, 0x11, 0xD9, 0x95, 0xF3, 0xC4, 0x16, 0x9B, 0x8A, 0x9C, 0xAF } }, // WOW-33978patch9.0.1_Beta
+ { 0x2678A2608A95FAAEULL, { 0xDB, 0x72, 0x2D, 0x47, 0x18, 0xB8, 0xB2, 0xC3, 0x13, 0x17, 0xB8, 0x43, 0xF6, 0x2D, 0x5F, 0xA8 } }, // WOW-33978patch9.0.1_Beta
+ { 0x27683B8282673916ULL, { 0x9A, 0x06, 0x02, 0xC6, 0x62, 0x4A, 0xD2, 0xB1, 0x85, 0x18, 0x7C, 0x8B, 0xD7, 0xAF, 0x81, 0x7A } }, // WOW-33978patch9.0.1_Beta
+ { 0x278A558C1E4C9789ULL, { 0x7C, 0xCF, 0xEE, 0xF6, 0x2E, 0xD5, 0x65, 0x60, 0xFD, 0x12, 0x94, 0xBB, 0x79, 0x7E, 0xC0, 0x0C } }, // WOW-33978patch9.0.1_Beta
+ { 0x29C4474FA5A650C2ULL, { 0xB4, 0x5A, 0x3E, 0x43, 0xB8, 0x18, 0x52, 0xD2, 0x69, 0x70, 0x0D, 0x11, 0xCA, 0xAA, 0x52, 0x74 } }, // WOW-33978patch9.0.1_Beta
+ { 0x29E553202112D688ULL, { 0xBB, 0x29, 0xC4, 0x2B, 0x23, 0xD1, 0x0E, 0xBE, 0x4E, 0xC7, 0x33, 0xC0, 0x4F, 0xB1, 0x9E, 0x0C } }, // WOW-33978patch9.0.1_Beta
+ { 0x2A50EBBA4B44FBF5ULL, { 0x7F, 0x1F, 0xA1, 0x12, 0x4C, 0xC3, 0xF4, 0x70, 0xAD, 0x48, 0x30, 0xB6, 0xD6, 0xA1, 0xF5, 0x13 } }, // WOW-33978patch9.0.1_Beta
+ { 0x2AFA1E90F5548DADULL, { 0x76, 0x6F, 0x2A, 0x52, 0x49, 0x29, 0xD9, 0x97, 0x83, 0x5D, 0xAE, 0x83, 0xC9, 0xB3, 0xDF, 0x4B } }, // WOW-33978patch9.0.1_Beta
+ { 0x2CDD202075F2BB7BULL, { 0x8B, 0x78, 0x02, 0x28, 0xAD, 0x85, 0xC5, 0xB0, 0x26, 0x53, 0xB9, 0x0E, 0x6A, 0x98, 0x28, 0x44 } }, // WOW-33978patch9.0.1_Beta
+ { 0x2D5511A1586B85BDULL, { 0x3A, 0x2A, 0x7A, 0x6B, 0x63, 0xE6, 0xA7, 0x0E, 0x26, 0x52, 0xDB, 0x45, 0x1C, 0x80, 0xA8, 0x78 } }, // WOW-33978patch9.0.1_Beta
+ { 0x2D6ADB0D7D20DA8FULL, { 0x39, 0x5C, 0xD9, 0xDF, 0xCF, 0x86, 0xA5, 0xF5, 0x53, 0x1A, 0x1C, 0xA3, 0xDE, 0x43, 0x96, 0x04 } }, // WOW-33978patch9.0.1_Beta
+ { 0x323E310D6BD63AC9ULL, { 0x52, 0x19, 0xD6, 0xB2, 0x0E, 0x8E, 0xA3, 0xF9, 0x72, 0xFD, 0x85, 0xD3, 0x55, 0xD3, 0x30, 0xD8 } }, // WOW-33978patch9.0.1_Beta
+ { 0x337A168A21969F6CULL, { 0x67, 0x03, 0x67, 0x8A, 0x02, 0x29, 0x4E, 0x8E, 0x8B, 0xCF, 0xC4, 0x23, 0xF0, 0xFF, 0xF9, 0x35 } }, // WOW-33978patch9.0.1_Beta
+ { 0x33801621A7C885FDULL, { 0x93, 0xBE, 0xD4, 0x71, 0xDD, 0x0C, 0xF9, 0x02, 0xA3, 0xA2, 0x43, 0xD8, 0xA3, 0x44, 0x11, 0xC5 } }, // WOW-33978patch9.0.1_Beta
+ { 0x34487D8CF061757AULL, { 0x33, 0x26, 0x12, 0x28, 0xE6, 0x94, 0xDD, 0x95, 0x9A, 0xC9, 0xA6, 0x8B, 0x73, 0x6F, 0x6A, 0xF3 } }, // WOW-33978patch9.0.1_Beta
+ { 0x35FC62C0E25BFA2CULL, { 0x69, 0x0D, 0x5E, 0xC1, 0xE5, 0x6A, 0xA0, 0x50, 0x49, 0x5B, 0x7B, 0xAE, 0x51, 0x3C, 0xAB, 0xCF } }, // WOW-33978patch9.0.1_Beta
+ { 0x3692291361CDD66BULL, { 0x87, 0x81, 0x36, 0x91, 0xB2, 0xFA, 0xEA, 0xBC, 0x9A, 0x28, 0x26, 0x5B, 0xE0, 0x3F, 0xAE, 0x7E } }, // WOW-33978patch9.0.1_Beta
+ { 0x38138436341EB55EULL, { 0xCD, 0x0D, 0xF8, 0x43, 0x30, 0x6C, 0x37, 0xB5, 0x17, 0x68, 0x91, 0xFC, 0x56, 0xDF, 0x7D, 0x57 } }, // WOW-33978patch9.0.1_Beta
+ { 0x390336A9AC1ADBD3ULL, { 0xF1, 0x93, 0xE1, 0xAC, 0x0A, 0x1C, 0x80, 0x93, 0xF2, 0x31, 0x82, 0x47, 0xF1, 0xED, 0xC6, 0xA4 } }, // WOW-33978patch9.0.1_Beta
+ { 0x41A0F110F49EB86AULL, { 0xDF, 0x50, 0xC9, 0x44, 0xB4, 0x2E, 0xF1, 0x6B, 0x4E, 0x6F, 0xA3, 0xE3, 0xF2, 0x8E, 0x70, 0xF7 } }, // WOW-33978patch9.0.1_Beta
+ { 0x41BDEA4884539B22ULL, { 0x14, 0xC6, 0xE1, 0xA2, 0xC0, 0xBB, 0xCF, 0x1E, 0x6D, 0x21, 0xA2, 0x1F, 0x39, 0xD5, 0x51, 0xCA } }, // WOW-33978patch9.0.1_Beta
+ { 0x41E698459DAD7101ULL, { 0xBF, 0xE8, 0x76, 0x01, 0x16, 0x60, 0xAD, 0x32, 0xA5, 0x72, 0x7E, 0x48, 0x9F, 0x83, 0x64, 0x68 } }, // WOW-33978patch9.0.1_Beta
+ { 0x4223772617A3212AULL, { 0xC4, 0x09, 0x63, 0x17, 0x1B, 0x49, 0x6B, 0xB7, 0x65, 0xA5, 0x6E, 0xC3, 0xF2, 0x2D, 0xD6, 0x48 } }, // WOW-33978patch9.0.1_Beta
+ { 0x422ABA4AE3E43AC5ULL, { 0xA0, 0xAE, 0x8D, 0xA9, 0x66, 0x39, 0x3F, 0x20, 0x60, 0x12, 0xA6, 0x1A, 0xE8, 0x19, 0xBD, 0xEA } }, // WOW-33978patch9.0.1_Beta
+ { 0x429E445F8823DE47ULL, { 0xCB, 0x10, 0x47, 0x34, 0xDC, 0x4A, 0xDE, 0x45, 0x4A, 0x7A, 0x1A, 0x17, 0x96, 0x42, 0x3B, 0x21 } }, // WOW-33978patch9.0.1_Beta
+ { 0x43855C4ABC59CD03ULL, { 0x91, 0xA3, 0x74, 0xB1, 0xE8, 0xCF, 0xE4, 0x6D, 0x2B, 0x82, 0xC7, 0x69, 0x52, 0x2D, 0x7F, 0xAF } }, // WOW-33978patch9.0.1_Beta
+ { 0x44324FEB63BAD71BULL, { 0xBA, 0xA7, 0xA3, 0x31, 0x1F, 0x36, 0xD3, 0xF6, 0xC1, 0x58, 0x9F, 0xBF, 0x34, 0xF1, 0x63, 0xAF } }, // WOW-33978patch9.0.1_Beta
+ { 0x445C444DDCB144D0ULL, { 0xE1, 0x1F, 0x30, 0x61, 0x10, 0xA2, 0x47, 0xAC, 0x08, 0x7E, 0x44, 0x66, 0xE8, 0x50, 0x5A, 0xC2 } }, // WOW-33978patch9.0.1_Beta
+ { 0x4570E5C612AD4680ULL, { 0xC7, 0x5A, 0x72, 0x40, 0xBF, 0x08, 0x89, 0xBD, 0xB5, 0x0D, 0xB2, 0x14, 0x7C, 0xAE, 0xC2, 0x9F } }, // WOW-33978patch9.0.1_Beta
+ { 0x463B8AC09861DBF2ULL, { 0x85, 0x14, 0x8A, 0x61, 0x6B, 0x3D, 0x2C, 0x0F, 0x3B, 0x50, 0x22, 0xB8, 0x71, 0xE4, 0xAB, 0x2F } }, // WOW-33978patch9.0.1_Beta
+ { 0x46B9652048C5B9EBULL, { 0x42, 0xAD, 0x0B, 0xE5, 0x4B, 0xCF, 0xED, 0x59, 0x75, 0xC3, 0x5B, 0xC8, 0x00, 0xF6, 0x94, 0x4B } }, // WOW-33978patch9.0.1_Beta
+ { 0x477AF884E1779F04ULL, { 0x81, 0xE7, 0x36, 0x61, 0x9B, 0x2A, 0xA8, 0xD3, 0xBE, 0xB3, 0x80, 0x01, 0x8C, 0x04, 0xC0, 0x97 } }, // WOW-33978patch9.0.1_Beta
+ { 0x49E4DB410ACD71E4ULL, { 0xEC, 0xAD, 0x54, 0xE4, 0xCC, 0x6A, 0xE5, 0xA2, 0xB1, 0xCD, 0xFC, 0x94, 0xDC, 0xC4, 0xA7, 0xE0 } }, // WOW-33978patch9.0.1_Beta
+ { 0x4BA04135745B0C77ULL, { 0x48, 0xAC, 0x8F, 0x63, 0xF9, 0xF6, 0xD4, 0xFC, 0x7B, 0xBE, 0xF2, 0xF8, 0x97, 0x40, 0xB7, 0x3F } }, // WOW-33978patch9.0.1_Beta
+ { 0x4C3638A33B225E20ULL, { 0x85, 0xB3, 0x19, 0x7B, 0x10, 0x55, 0x03, 0xD9, 0xBC, 0x11, 0x76, 0xA6, 0xCE, 0x90, 0xB2, 0x1B } }, // WOW-33978patch9.0.1_Beta
+ { 0x4CA3E38A5F339D85ULL, { 0x65, 0xDA, 0x28, 0xD6, 0x97, 0xE8, 0x2F, 0x7F, 0xB3, 0x26, 0x98, 0xF5, 0xDC, 0x13, 0xFE, 0x67 } }, // WOW-33978patch9.0.1_Beta
+ { 0x4D356B23BBB63ABFULL, { 0x5B, 0x31, 0xF5, 0xD4, 0x37, 0x18, 0x20, 0xE0, 0x86, 0xD1, 0x59, 0x1F, 0x20, 0x96, 0x3C, 0x6F } }, // WOW-33978patch9.0.1_Beta
+ { 0x4D81CA32AF4851B8ULL, { 0x2F, 0xAF, 0x21, 0x8D, 0x81, 0x0A, 0x5D, 0x2C, 0x5B, 0xCD, 0x6E, 0xBE, 0x7A, 0xF6, 0x7C, 0x66 } }, // WOW-33978patch9.0.1_Beta
+ { 0x4E8FD51F7FDCB494ULL, { 0x6F, 0x19, 0x66, 0x48, 0xE9, 0xE0, 0xBD, 0x75, 0xC4, 0xC9, 0x63, 0x21, 0x4F, 0xBF, 0x43, 0x53 } }, // WOW-33978patch9.0.1_Beta
+ { 0x4F29CD1DBFF6A704ULL, { 0x19, 0xF0, 0x45, 0x81, 0x27, 0x1E, 0xB2, 0x56, 0xF1, 0x05, 0x34, 0xE5, 0x0C, 0x82, 0x9D, 0x30 } }, // WOW-33978patch9.0.1_Beta
+ { 0x50BDE6C6B138D920ULL, { 0x86, 0x3D, 0xE7, 0xEA, 0x7E, 0xDE, 0x52, 0x18, 0xCE, 0x92, 0x86, 0x36, 0x0D, 0xD5, 0x4C, 0xE3 } }, // WOW-33978patch9.0.1_Beta
+ { 0x51C45371AA62A30DULL, { 0x80, 0x29, 0x74, 0xB8, 0x2D, 0x99, 0x83, 0xCD, 0x78, 0xB6, 0x65, 0x33, 0x20, 0xD3, 0xDA, 0xA5 } }, // WOW-33978patch9.0.1_Beta
+ { 0x53422759826BCE28ULL, { 0x46, 0x7F, 0x7B, 0xB8, 0x45, 0xB5, 0x0A, 0xBE, 0x1B, 0x0B, 0xD7, 0x18, 0x95, 0xFD, 0x78, 0x38 } }, // WOW-33978patch9.0.1_Beta
+ { 0x54E0E8C0E9A4CEE7ULL, { 0x41, 0x8D, 0x3F, 0xA2, 0xCB, 0xA3, 0xD9, 0x72, 0x29, 0x36, 0x1E, 0x2D, 0xE7, 0x96, 0x79, 0x28 } }, // WOW-33978patch9.0.1_Beta
+ { 0x550AB6D42C0118D3ULL, { 0xBF, 0x50, 0x7B, 0x7E, 0xAC, 0x67, 0x29, 0x55, 0x0E, 0x87, 0xBD, 0x44, 0x4B, 0xB7, 0x0F, 0x35 } }, // WOW-33978patch9.0.1_Beta
+ { 0x577E78AECCE3D388ULL, { 0x19, 0x6B, 0x59, 0x45, 0x39, 0x36, 0x4E, 0xCC, 0xFF, 0xD9, 0x2E, 0x71, 0xD9, 0x19, 0x30, 0x20 } }, // WOW-33978patch9.0.1_Beta
+ { 0x587E8D3EB9594F4AULL, { 0x0E, 0xDE, 0x7A, 0x2C, 0x7B, 0xE8, 0xA1, 0x9A, 0x98, 0x73, 0x88, 0xC3, 0xF6, 0x04, 0x67, 0x55 } }, // WOW-33978patch9.0.1_Beta
+ { 0x591C8211EE53BFDBULL, { 0x46, 0xA6, 0x19, 0xF7, 0xA6, 0xC4, 0xE0, 0xCE, 0x54, 0x2B, 0xB1, 0xA9, 0xE4, 0x71, 0x3F, 0x34 } }, // WOW-33978patch9.0.1_Beta
+ { 0x597B3EA295C88FA7ULL, { 0x2D, 0x36, 0x4A, 0xE4, 0xD4, 0x6C, 0xEF, 0x42, 0x2A, 0x6F, 0x53, 0x1D, 0x9B, 0x1A, 0x7A, 0xD2 } }, // WOW-33978patch9.0.1_Beta
+ { 0x59CBA5A49554EB2FULL, { 0x4B, 0x5F, 0xF9, 0xC6, 0x7E, 0x02, 0x1C, 0x5E, 0x2A, 0xA3, 0xB0, 0x5A, 0xC9, 0xE0, 0x50, 0x96 } }, // WOW-33978patch9.0.1_Beta
+ { 0x5B1A3C7FC9D58D21ULL, { 0xA4, 0x8B, 0xA8, 0xE3, 0x19, 0x20, 0x7B, 0x2C, 0x04, 0xE8, 0x2B, 0x25, 0xC0, 0xF3, 0xC1, 0x49 } }, // WOW-33978patch9.0.1_Beta
+ { 0x5B256C6230E168FFULL, { 0x89, 0xF3, 0x1D, 0x0F, 0xA3, 0x81, 0xD7, 0x23, 0x55, 0x56, 0x6B, 0x01, 0x24, 0xB8, 0xE1, 0xF2 } }, // WOW-33978patch9.0.1_Beta
+ { 0x5B657AE4D191AAFBULL, { 0xF8, 0x84, 0xAA, 0xC1, 0xE2, 0xAB, 0x1C, 0x41, 0x3F, 0x7B, 0xAD, 0xDD, 0x14, 0x9D, 0x09, 0x61 } }, // WOW-33978patch9.0.1_Beta
+ { 0x5B93089CD9316EFEULL, { 0x95, 0x76, 0x53, 0xD3, 0x4A, 0xBF, 0x29, 0x88, 0x46, 0xFF, 0x56, 0x04, 0xC1, 0xEB, 0x06, 0xD0 } }, // WOW-33978patch9.0.1_Beta
+ { 0x5C172612CB60DEF2ULL, { 0xF5, 0x10, 0xBF, 0xEF, 0xFF, 0x2F, 0x87, 0x0B, 0x08, 0x93, 0x1B, 0x62, 0x52, 0x6F, 0x01, 0xFE } }, // WOW-33978patch9.0.1_Beta
+ { 0x5E6EB3F5C47183FFULL, { 0x73, 0xEC, 0xB7, 0xAE, 0x15, 0x19, 0xE3, 0x9C, 0xC8, 0xBB, 0xD8, 0xF9, 0x90, 0xF3, 0xAC, 0xFB } }, // WOW-33978patch9.0.1_Beta
+ { 0x5E7181FBA91F3766ULL, { 0x2F, 0x6A, 0xAB, 0xDC, 0x38, 0x9E, 0xA1, 0x0A, 0x11, 0xA9, 0xF1, 0x83, 0x58, 0x04, 0xF8, 0x6C } }, // WOW-33978patch9.0.1_Beta
+ { 0x5E7B9DCD0092888BULL, { 0x6F, 0xE5, 0xA1, 0x40, 0x39, 0x93, 0xAE, 0x2A, 0x22, 0xA4, 0xF1, 0xAD, 0x31, 0x14, 0x4D, 0xAB } }, // WOW-33978patch9.0.1_Beta
+ { 0x5F1C8C3CFABDC578ULL, { 0xEA, 0x5A, 0x36, 0x31, 0x46, 0x09, 0xC6, 0x70, 0x84, 0xDB, 0x63, 0xCF, 0xF7, 0x87, 0xDF, 0xCA } }, // WOW-33978patch9.0.1_Beta
+ { 0x62EDE4DE7880CC68ULL, { 0xEA, 0xAA, 0x8D, 0x5C, 0x76, 0xEA, 0x95, 0x76, 0x31, 0x52, 0xAE, 0x50, 0x3C, 0xF5, 0x67, 0x45 } }, // WOW-33978patch9.0.1_Beta
+ { 0x637AD198DBD985ECULL, { 0xA8, 0x31, 0xE0, 0x85, 0xC7, 0xA0, 0x98, 0x45, 0x57, 0xE7, 0x97, 0x30, 0x5C, 0xB2, 0xA2, 0x63 } }, // WOW-33978patch9.0.1_Beta
+ { 0x6444A004E5F352B9ULL, { 0x76, 0x8A, 0x1C, 0x07, 0x02, 0x50, 0xD1, 0x70, 0x95, 0x02, 0x3D, 0xBD, 0xBD, 0x02, 0x3B, 0xC7 } }, // WOW-33978patch9.0.1_Beta
+ { 0x649F6483822B8C3EULL, { 0xDB, 0xD9, 0x35, 0x20, 0x0A, 0x22, 0xE7, 0x89, 0x75, 0x89, 0x40, 0xE9, 0x1E, 0x1C, 0xFC, 0xAE } }, // WOW-33978patch9.0.1_Beta
+ { 0x650E0558CFE68DBDULL, { 0xE4, 0x98, 0x29, 0x4E, 0x3A, 0x2C, 0xB7, 0xF1, 0x0B, 0x0F, 0x1A, 0xC8, 0x98, 0xF3, 0x79, 0xB6 } }, // WOW-33978patch9.0.1_Beta
+ { 0x667C9AD6F57610C7ULL, { 0xF7, 0xF9, 0x8E, 0xFE, 0x5D, 0xB2, 0x27, 0x92, 0x8F, 0x97, 0x02, 0x85, 0x20, 0xD9, 0x7F, 0xC3 } }, // WOW-33978patch9.0.1_Beta
+ { 0x67AD32C6DFF4B640ULL, { 0x03, 0x32, 0x11, 0xB8, 0x92, 0xF5, 0x2C, 0xBE, 0x56, 0x10, 0x51, 0xEB, 0xAA, 0xC8, 0xCE, 0x2F } }, // WOW-33978patch9.0.1_Beta
+ { 0x6870068DF23BA71BULL, { 0x58, 0x97, 0x6C, 0xEA, 0xF5, 0xE2, 0xAB, 0x19, 0x38, 0x01, 0xD7, 0x13, 0xAB, 0xEC, 0x60, 0x5B } }, // WOW-33978patch9.0.1_Beta
+ { 0x69CADB492EBF739EULL, { 0x63, 0xA4, 0x2B, 0xB5, 0x28, 0x05, 0x0C, 0x59, 0x47, 0x73, 0x5C, 0x18, 0x36, 0x60, 0x5C, 0x95 } }, // WOW-33978patch9.0.1_Beta
+ { 0x6B20D9D506B930E6ULL, { 0xA4, 0x2E, 0xEC, 0xB7, 0x63, 0xC8, 0x79, 0xC3, 0x9C, 0xFC, 0xC3, 0x82, 0x0C, 0xC0, 0x57, 0x13 } }, // WOW-33978patch9.0.1_Beta
+ { 0x6BF0360FC30A1651ULL, { 0x7A, 0x69, 0xDC, 0x9A, 0x2E, 0xF9, 0x6E, 0x9E, 0xFA, 0x1F, 0x4E, 0xE3, 0x75, 0x44, 0xD0, 0x60 } }, // WOW-33978patch9.0.1_Beta
+ { 0x6C3380DB72AFCF88ULL, { 0xC5, 0xED, 0xF5, 0x55, 0xCE, 0x52, 0xF6, 0x71, 0x7B, 0x38, 0x28, 0x1C, 0x1B, 0x46, 0xCC, 0xDC } }, // WOW-33978patch9.0.1_Beta
+ { 0x6CEAD213E31A6F01ULL, { 0x1D, 0x26, 0x3C, 0xFB, 0x4B, 0xD4, 0xDE, 0x9E, 0xBF, 0x59, 0xB1, 0x28, 0x7E, 0x39, 0x7F, 0xFE } }, // WOW-33978patch9.0.1_Beta
+ { 0x6D6AD51EAA144766ULL, { 0x3E, 0xDD, 0x69, 0x0A, 0x09, 0x18, 0xA4, 0x2B, 0x49, 0xCB, 0xE2, 0x14, 0xBC, 0x90, 0x5D, 0x22 } }, // WOW-33978patch9.0.1_Beta
+ { 0x6E92CDCE4FEA3B27ULL, { 0xE9, 0x88, 0x05, 0xA6, 0xB0, 0xD4, 0xEA, 0x3C, 0x28, 0x0A, 0x4E, 0xF4, 0x9A, 0xE5, 0x10, 0x11 } }, // WOW-33978patch9.0.1_Beta
+ { 0x6EA6B9E529B29CC8ULL, { 0x7D, 0x8F, 0xE7, 0x88, 0xCA, 0x9A, 0xF0, 0x7F, 0x99, 0xC3, 0xDC, 0xA6, 0x1E, 0x1F, 0xBA, 0xC7 } }, // WOW-33978patch9.0.1_Beta
+ { 0x72337416FD82C794ULL, { 0xF4, 0x78, 0x2D, 0x77, 0xEA, 0xDA, 0x33, 0x0A, 0x2D, 0xD1, 0x78, 0x9D, 0x64, 0x7F, 0x27, 0xBF } }, // WOW-33978patch9.0.1_Beta
+ { 0x725E3CA857E0D99FULL, { 0x91, 0xD3, 0xAB, 0xCC, 0xDE, 0xE7, 0x20, 0xF4, 0xBA, 0xD5, 0xB9, 0x0E, 0xFA, 0xB9, 0x04, 0xFC } }, // WOW-33978patch9.0.1_Beta
+ { 0x747A16FD3A3F6970ULL, { 0x16, 0x26, 0xFE, 0x4D, 0x37, 0x25, 0xE1, 0xD1, 0x7D, 0xEE, 0xE1, 0xC2, 0xDF, 0xEE, 0x85, 0xD4 } }, // WOW-33978patch9.0.1_Beta
+ { 0x75BD0F89A7DF7076ULL, { 0x9A, 0x4F, 0x51, 0xF7, 0xDB, 0x21, 0xD0, 0x49, 0x32, 0xAF, 0x81, 0x86, 0x42, 0xCC, 0x7B, 0xEC } }, // WOW-33978patch9.0.1_Beta
+ { 0x75E2B6A4145B00DBULL, { 0xE0, 0x9B, 0x5A, 0x79, 0xB5, 0xFB, 0xAD, 0xE1, 0x9D, 0x1D, 0x97, 0x9B, 0x2C, 0x32, 0xE4, 0xB7 } }, // WOW-33978patch9.0.1_Beta
+ { 0x77F0A6FE6BE42E62ULL, { 0x35, 0xBA, 0xB9, 0x29, 0x81, 0xF6, 0x04, 0xEF, 0x4C, 0x3C, 0x22, 0x53, 0xC0, 0x3D, 0x36, 0xCE } }, // WOW-33978patch9.0.1_Beta
+ { 0x7810113EF44E92B2ULL, { 0xA2, 0x18, 0x6B, 0x58, 0x6A, 0xE6, 0x86, 0xF3, 0xE1, 0x57, 0x9F, 0xFA, 0x9D, 0xDF, 0x17, 0x03 } }, // WOW-33978patch9.0.1_Beta
+ { 0x78B7C378F1424152ULL, { 0xDF, 0x20, 0xB3, 0xFA, 0x41, 0x5B, 0x16, 0x25, 0xAA, 0x7D, 0x82, 0x22, 0x61, 0x2F, 0x75, 0xA0 } }, // WOW-33978patch9.0.1_Beta
+ { 0x79383B3295AA93C4ULL, { 0xEF, 0xDE, 0x6A, 0xEB, 0xDA, 0x6A, 0xBE, 0xD6, 0x5B, 0x2F, 0xE9, 0x1F, 0x33, 0x95, 0xDA, 0x4E } }, // WOW-33978patch9.0.1_Beta
+ { 0x7AD23E997C77CBEBULL, { 0x05, 0x6F, 0x35, 0x4E, 0xA0, 0x86, 0x41, 0x26, 0x53, 0x44, 0x33, 0x6C, 0xEF, 0x0C, 0xDB, 0x8D } }, // WOW-33978patch9.0.1_Beta
+ { 0x7C86AE10DE9A2D24ULL, { 0x7B, 0x0A, 0x70, 0xD0, 0xD1, 0x6E, 0xA7, 0x34, 0x5B, 0xFF, 0xDD, 0x56, 0xF6, 0x5E, 0xA2, 0x7F } }, // WOW-33978patch9.0.1_Beta
+ { 0x7CD6AC9BD4B6C2F1ULL, { 0x20, 0xE7, 0x93, 0x06, 0x6B, 0x7D, 0x48, 0x94, 0x6B, 0xCE, 0x64, 0xA1, 0x6E, 0x72, 0x31, 0xD7 } }, // WOW-33978patch9.0.1_Beta
+ { 0x7E1F1D367C75D4E3ULL, { 0x37, 0x15, 0xB8, 0x5F, 0x6E, 0xCD, 0xBD, 0x3B, 0x1D, 0x85, 0x89, 0x60, 0x22, 0x53, 0xDC, 0x75 } }, // WOW-33978patch9.0.1_Beta
+ { 0x7E4C540FC51875ECULL, { 0x36, 0x71, 0xFC, 0xCE, 0xDF, 0xF2, 0x7D, 0x9F, 0x46, 0x3F, 0x6A, 0x5B, 0xED, 0xE5, 0xE2, 0x2D } }, // WOW-33978patch9.0.1_Beta
+ { 0x7E766271DF1A2F90ULL, { 0x2C, 0xEC, 0x2B, 0x76, 0xCF, 0x05, 0x63, 0x4D, 0xFB, 0xC4, 0xCB, 0x1F, 0xB9, 0x8C, 0xBC, 0x4F } }, // WOW-33978patch9.0.1_Beta
+ { 0x7F7D6EDEF8F5BCFCULL, { 0xF1, 0xD5, 0x9F, 0xEC, 0x5C, 0xB7, 0x4B, 0x2E, 0x66, 0x38, 0x00, 0xB7, 0xDA, 0xBF, 0x32, 0x16 } }, // WOW-33978patch9.0.1_Beta
+ { 0x801FD0E0D505C316ULL, { 0x91, 0x30, 0x64, 0x6A, 0xD7, 0x52, 0x44, 0xBB, 0x44, 0x5B, 0x66, 0x88, 0xA5, 0x00, 0x7B, 0x5C } }, // WOW-33978patch9.0.1_Beta
+ { 0x8281CFAEB6AE6182ULL, { 0xC3, 0x25, 0x34, 0xB1, 0x97, 0x5C, 0x71, 0x07, 0xB6, 0x38, 0xD4, 0x77, 0x94, 0xA9, 0xF3, 0xF2 } }, // WOW-33978patch9.0.1_Beta
+ { 0x834E863E91A946E0ULL, { 0xFF, 0xC4, 0x7E, 0x87, 0xFA, 0xD8, 0x8A, 0x87, 0x24, 0xE2, 0xCF, 0x3E, 0xAE, 0xE1, 0xAA, 0x06 } }, // WOW-33978patch9.0.1_Beta
+ { 0x85B1F0C5AFA7684AULL, { 0x7A, 0x29, 0xDC, 0xA9, 0x90, 0xAA, 0x0A, 0x7D, 0xF1, 0x99, 0x4E, 0xAF, 0x00, 0x04, 0x54, 0xB8 } }, // WOW-33978patch9.0.1_Beta
+ { 0x85CB9DF9FC580C0EULL, { 0xD1, 0x70, 0xBC, 0xFC, 0x13, 0xB1, 0xA2, 0x18, 0x5C, 0x4F, 0xE1, 0x3C, 0x5F, 0x55, 0x5E, 0x2D } }, // WOW-33978patch9.0.1_Beta
+ { 0x867D98DC263C7AE1ULL, { 0xD6, 0xC5, 0xAE, 0x41, 0x33, 0xA0, 0xD3, 0x2F, 0x6A, 0x33, 0x39, 0x19, 0xC9, 0x95, 0xC2, 0x9F } }, // WOW-33978patch9.0.1_Beta
+ { 0x86ACAF9277898823ULL, { 0xE6, 0x3D, 0xFD, 0x69, 0x16, 0xBD, 0xDE, 0x96, 0x32, 0x63, 0x3B, 0x25, 0x5B, 0xEE, 0x73, 0x10 } }, // WOW-33978patch9.0.1_Beta
+ { 0x87413DE10A58AB14ULL, { 0x0B, 0x08, 0x32, 0x50, 0x17, 0x72, 0x9F, 0xD1, 0xBF, 0x2B, 0xA6, 0xC9, 0xEC, 0x03, 0xB0, 0x91 } }, // WOW-33978patch9.0.1_Beta
+ { 0x8831955158E50488ULL, { 0x12, 0x5E, 0x99, 0x2B, 0x50, 0xDD, 0x3C, 0x1D, 0x9B, 0xD5, 0xA4, 0x7D, 0xCA, 0xD7, 0x4F, 0x63 } }, // WOW-33978patch9.0.1_Beta
+ { 0x8A34D884566690F3ULL, { 0xD7, 0x7E, 0x4B, 0x5D, 0x2D, 0x5F, 0x2A, 0x07, 0xD1, 0xB7, 0x4C, 0x77, 0x2C, 0x7B, 0x9E, 0x1D } }, // WOW-33978patch9.0.1_Beta
+ { 0x8AA33E951B061C6CULL, { 0x45, 0xF8, 0xA8, 0x73, 0x94, 0x61, 0xA1, 0x5B, 0x5E, 0xEC, 0xDB, 0x8E, 0xD6, 0xD6, 0x68, 0x20 } }, // WOW-33978patch9.0.1_Beta
+ { 0x8AB2DCD201956FF5ULL, { 0xF4, 0x91, 0x31, 0x04, 0x7B, 0x25, 0xA7, 0xD3, 0x00, 0x67, 0xC7, 0xCB, 0x31, 0xF4, 0xB7, 0xC8 } }, // WOW-33978patch9.0.1_Beta
+ { 0x8AFF128B2C44402FULL, { 0x09, 0x28, 0x59, 0x7D, 0xDA, 0x06, 0x1C, 0xCA, 0x27, 0x72, 0x63, 0x9B, 0x18, 0x15, 0x3B, 0xBA } }, // WOW-33978patch9.0.1_Beta
+ { 0x929399E254952F89ULL, { 0x76, 0x23, 0x36, 0xB5, 0x0C, 0xBB, 0x8C, 0xBF, 0xA6, 0xEC, 0x6F, 0xF2, 0x97, 0x00, 0x96, 0x40 } }, // WOW-33978patch9.0.1_Beta
+ { 0x93A98F82D5B5FA3DULL, { 0x9A, 0x84, 0x56, 0x3A, 0xC7, 0xF1, 0x9E, 0x66, 0xAC, 0x4F, 0x63, 0x34, 0x6D, 0x58, 0xCB, 0xBC } }, // WOW-33978patch9.0.1_Beta
+ { 0x9440B38F8FC83801ULL, { 0xF2, 0x35, 0xB5, 0x29, 0x24, 0x61, 0xAD, 0xD2, 0xCD, 0x58, 0x27, 0x5F, 0xDA, 0xBF, 0x2D, 0x91 } }, // WOW-33978patch9.0.1_Beta
+ { 0x953B60DFAAD53C53ULL, { 0x0F, 0xFD, 0xE3, 0x48, 0xDB, 0xBF, 0x68, 0x28, 0x10, 0x38, 0x61, 0xE7, 0xC2, 0x02, 0xEE, 0x03 } }, // WOW-33978patch9.0.1_Beta
+ { 0x96CDB729EF5FF4D8ULL, { 0x9D, 0x5C, 0xD0, 0x16, 0x7D, 0xA6, 0x0B, 0x4A, 0x5D, 0x5B, 0x7E, 0xB1, 0x0F, 0x1F, 0x44, 0x02 } }, // WOW-33978patch9.0.1_Beta
+ { 0x96D55B6111ADB046ULL, { 0x7D, 0x8B, 0x9D, 0x2B, 0x57, 0x88, 0xCF, 0x14, 0x94, 0xE1, 0xBE, 0x73, 0xA3, 0x2A, 0x0A, 0xEB } }, // WOW-33978patch9.0.1_Beta
+ { 0x994C40C879819D41ULL, { 0x88, 0xA3, 0x28, 0x44, 0xB2, 0x2E, 0xB1, 0xE8, 0x36, 0x2B, 0x72, 0x8A, 0xE5, 0x1F, 0x66, 0x63 } }, // WOW-33978patch9.0.1_Beta
+ { 0x9A4F5BC0D2DF3E7CULL, { 0x27, 0x5D, 0x03, 0x60, 0xE8, 0x11, 0xEE, 0x2F, 0x3E, 0xB3, 0xBC, 0xCA, 0x96, 0xFA, 0x39, 0x88 } }, // WOW-33978patch9.0.1_Beta
+ { 0x9BB64D7C24F7F570ULL, { 0xA5, 0xF5, 0x27, 0xB1, 0x2A, 0x7C, 0x54, 0x49, 0x01, 0x30, 0x1F, 0x0C, 0xC4, 0xF7, 0x5A, 0xC6 } }, // WOW-33978patch9.0.1_Beta
+ { 0x9CAE05184985E6FAULL, { 0x7D, 0x79, 0xCA, 0x06, 0x09, 0xB2, 0xA9, 0xF5, 0x2C, 0x17, 0xB4, 0x91, 0xB2, 0x2F, 0xF2, 0x95 } }, // WOW-33978patch9.0.1_Beta
+ { 0x9DE3C22E44D3D817ULL, { 0x2A, 0xD1, 0x8A, 0xE6, 0x65, 0x74, 0xB1, 0x78, 0x4A, 0x9B, 0x52, 0xC4, 0xE4, 0x5C, 0x47, 0x0C } }, // WOW-33978patch9.0.1_Beta
+ { 0x9E10A1C6E2156E96ULL, { 0xA1, 0x4F, 0x9D, 0x5B, 0x4B, 0x8E, 0x6F, 0xFC, 0x17, 0x33, 0x48, 0xA8, 0x16, 0x89, 0x88, 0x2D } }, // WOW-33978patch9.0.1_Beta
+ { 0x9E84167C7BCCAECFULL, { 0xBB, 0x28, 0xC7, 0x41, 0x89, 0x32, 0x7B, 0xEC, 0x53, 0xC1, 0xF1, 0xD9, 0x0D, 0x62, 0xBD, 0xA6 } }, // WOW-33978patch9.0.1_Beta
+ { 0xA1651FBBB33533C8ULL, { 0xAB, 0x1E, 0x3D, 0x12, 0x8C, 0x6E, 0xC9, 0x4E, 0x6C, 0x7E, 0x0B, 0xAB, 0x3F, 0xF9, 0x6B, 0x54 } }, // WOW-33978patch9.0.1_Beta
+ { 0xA1F082630668B975ULL, { 0xA0, 0xC9, 0xAB, 0x98, 0x7F, 0x54, 0x4D, 0xAD, 0x86, 0x73, 0x5E, 0xEC, 0x3A, 0xB7, 0x0C, 0xBC } }, // WOW-33978patch9.0.1_Beta
+ { 0xA2A3787CEE9A05EEULL, { 0x2F, 0xAA, 0x35, 0x7F, 0x63, 0xC7, 0x2E, 0x74, 0x9B, 0x42, 0x3E, 0x45, 0xA7, 0x21, 0xE5, 0x49 } }, // WOW-33978patch9.0.1_Beta
+ { 0xA6D012ADD54A30CEULL, { 0x22, 0xE1, 0x30, 0x2E, 0xEB, 0xD9, 0x98, 0xCB, 0x7F, 0x05, 0xBC, 0xAF, 0x1D, 0x85, 0x39, 0xC6 } }, // WOW-33978patch9.0.1_Beta
+ { 0xA7E2CEFD0280FD3AULL, { 0x08, 0x90, 0x89, 0x66, 0x8F, 0xD4, 0xF2, 0xCA, 0x94, 0xE0, 0x28, 0xCE, 0x0E, 0x8F, 0x0E, 0xAD } }, // WOW-33978patch9.0.1_Beta
+ { 0xA8E1094D80B82D21ULL, { 0x8F, 0xA8, 0xB2, 0xEE, 0x12, 0xF4, 0x5E, 0xD0, 0xF2, 0x40, 0x1C, 0x03, 0x3B, 0x32, 0x43, 0x8C } }, // WOW-33978patch9.0.1_Beta
+ { 0xAA15EAD581169812ULL, { 0x60, 0xAA, 0x2D, 0x1C, 0xB7, 0xC2, 0x92, 0x84, 0xDD, 0x63, 0x6E, 0x35, 0x77, 0xAF, 0x3E, 0xFD } }, // WOW-33978patch9.0.1_Beta
+ { 0xAA3EB38B572073F9ULL, { 0xE5, 0xBC, 0x7A, 0x03, 0x54, 0xB6, 0x45, 0x39, 0xCA, 0x59, 0xB6, 0x78, 0x70, 0x3C, 0xE4, 0x72 } }, // WOW-33978patch9.0.1_Beta
+ { 0xAA7119519C968451ULL, { 0x57, 0x84, 0xAC, 0xD6, 0x7A, 0xAD, 0xFF, 0xA5, 0xA3, 0x50, 0x84, 0xC8, 0xB7, 0x97, 0x4B, 0x7E } }, // WOW-33978patch9.0.1_Beta
+ { 0xAAAD5C17B34A935FULL, { 0xB0, 0x95, 0x4F, 0x6A, 0x29, 0x14, 0x19, 0x10, 0x81, 0x00, 0x93, 0x49, 0xAF, 0x44, 0x43, 0xC3 } }, // WOW-33978patch9.0.1_Beta
+ { 0xABA6C1AFDB427F54ULL, { 0x29, 0x75, 0xC6, 0x9D, 0xA6, 0x14, 0xC3, 0xFF, 0x32, 0xEE, 0xC3, 0xFE, 0xD8, 0x47, 0x29, 0xDE } }, // WOW-33978patch9.0.1_Beta
+ { 0xADC58189215E1C48ULL, { 0x1F, 0xFB, 0xD3, 0xB8, 0xE6, 0x2A, 0x10, 0x24, 0x92, 0xDC, 0x30, 0x73, 0x21, 0x16, 0xF1, 0x62 } }, // WOW-33978patch9.0.1_Beta
+ { 0xAFEE51897035872EULL, { 0xF0, 0x85, 0xEA, 0xBC, 0x11, 0xE2, 0x92, 0xD2, 0x0C, 0x77, 0x8B, 0x6D, 0x89, 0x2A, 0xBD, 0x1E } }, // WOW-33978patch9.0.1_Beta
+ { 0xAFFFA5791F73520AULL, { 0xA9, 0x67, 0xF2, 0xF4, 0x7E, 0x7C, 0xC0, 0x05, 0xCB, 0x8D, 0x7E, 0x92, 0x84, 0x78, 0x15, 0x8E } }, // WOW-33978patch9.0.1_Beta
+ { 0xB032F43502EDFA5AULL, { 0x4B, 0x0E, 0xF7, 0x9E, 0x47, 0x2D, 0x00, 0x2F, 0x8E, 0x71, 0x7E, 0xED, 0x75, 0xB0, 0x3E, 0x69 } }, // WOW-33978patch9.0.1_Beta
+ { 0xB23472311441BF43ULL, { 0x3E, 0xE4, 0x12, 0x48, 0xB9, 0x9B, 0xF6, 0xA1, 0x7E, 0xF9, 0x63, 0xC2, 0xD6, 0x88, 0x7B, 0xF5 } }, // WOW-33978patch9.0.1_Beta
+ { 0xB4582D7E642035F5ULL, { 0xCA, 0x5B, 0x90, 0xA2, 0x8C, 0x7D, 0xAE, 0xF5, 0xAC, 0x8B, 0xA2, 0x6A, 0x3B, 0x7E, 0xB2, 0x6F } }, // WOW-33978patch9.0.1_Beta
+ { 0xB46B23A8B047E71AULL, { 0x5F, 0xD3, 0xB3, 0xE6, 0xFF, 0x1B, 0xEB, 0x79, 0x6B, 0x13, 0xA0, 0x44, 0x7C, 0x8C, 0x9E, 0xCE } }, // WOW-33978patch9.0.1_Beta
+ { 0xB62985BE1B0E820CULL, { 0x7B, 0xCB, 0x7A, 0x3A, 0x7A, 0x7F, 0xE6, 0x72, 0xD7, 0xBB, 0x8D, 0xAB, 0x4C, 0x32, 0x66, 0xCA } }, // WOW-33978patch9.0.1_Beta
+ { 0xB76D3CD9FA80EF23ULL, { 0x43, 0x2F, 0xDE, 0xF3, 0x70, 0xE6, 0x84, 0x73, 0xCE, 0xB7, 0x5B, 0xE4, 0x80, 0x28, 0x71, 0x49 } }, // WOW-33978patch9.0.1_Beta
+ { 0xB881ACD9C433C39BULL, { 0x41, 0x5B, 0xEC, 0x80, 0x13, 0x4B, 0x91, 0xEB, 0xA7, 0xA8, 0x94, 0xE8, 0x11, 0x1F, 0x16, 0xED } }, // WOW-33978patch9.0.1_Beta
+ { 0xB8F711CD1BCCCB5AULL, { 0x06, 0x8D, 0xA8, 0x49, 0x5F, 0x4F, 0x87, 0x05, 0x08, 0xDF, 0xAF, 0xCE, 0xFA, 0xB3, 0x4F, 0x6C } }, // WOW-33978patch9.0.1_Beta
+ { 0xBA2586D5321809C9ULL, { 0x37, 0x08, 0xFF, 0xBC, 0xD5, 0xDE, 0x8B, 0xA1, 0x1E, 0x7A, 0xE2, 0xF2, 0x10, 0x88, 0xF5, 0xE0 } }, // WOW-33978patch9.0.1_Beta
+ { 0xBB56A0BAE42B0A58ULL, { 0x36, 0xF6, 0x57, 0xC6, 0x27, 0x16, 0xEA, 0x72, 0xEB, 0x46, 0x44, 0x6C, 0xD3, 0x6E, 0xF0, 0x81 } }, // WOW-33978patch9.0.1_Beta
+ { 0xBBC9FAFBFB8A476EULL, { 0xDF, 0x8F, 0x45, 0x6C, 0xE6, 0xF4, 0x2B, 0x83, 0x29, 0xD6, 0xAB, 0x75, 0x44, 0x5E, 0x93, 0x47 } }, // WOW-33978patch9.0.1_Beta
+ { 0xBDE676123BBB010AULL, { 0x9A, 0x68, 0x26, 0xB6, 0x35, 0x2B, 0xF4, 0x47, 0xC5, 0x52, 0x6F, 0x3D, 0x80, 0xB2, 0xA4, 0x2A } }, // WOW-33978patch9.0.1_Beta
+ { 0xBE78B15D2D2FFC28ULL, { 0x18, 0x63, 0x5E, 0xA1, 0xEA, 0x0D, 0x52, 0xA8, 0x04, 0x34, 0x5D, 0x74, 0x2E, 0x47, 0xE7, 0xFF } }, // WOW-33978patch9.0.1_Beta
+ { 0xBF0DA6AAE66E25A0ULL, { 0xFB, 0x2D, 0xEA, 0x41, 0xD6, 0x00, 0xF3, 0x95, 0xB4, 0x1F, 0x1D, 0x21, 0x9C, 0x2F, 0xDE, 0x4D } }, // WOW-33978patch9.0.1_Beta
+ { 0xBF26C727BFC92EAFULL, { 0x5E, 0xD5, 0x02, 0xEE, 0xFB, 0x92, 0x1A, 0x27, 0xC1, 0x83, 0x6A, 0x8E, 0x5E, 0x4A, 0x15, 0x92 } }, // WOW-33978patch9.0.1_Beta
+ { 0xBF874CF500A50632ULL, { 0x87, 0xB9, 0x5B, 0xE0, 0x9C, 0xEE, 0x36, 0xDC, 0x91, 0x43, 0x04, 0x70, 0x95, 0x2E, 0xF3, 0x26 } }, // WOW-33978patch9.0.1_Beta
+ { 0xBF87DE9EFBA3E7E7ULL, { 0x2A, 0x2C, 0x1E, 0x9A, 0xCA, 0x4F, 0xCD, 0x01, 0xF8, 0xF6, 0x40, 0x66, 0x76, 0x70, 0x63, 0x79 } }, // WOW-33978patch9.0.1_Beta
+ { 0xC132034A5F2F7E10ULL, { 0x27, 0x3B, 0xA2, 0x00, 0x5D, 0x7C, 0xDE, 0xDD, 0xB1, 0x67, 0x5C, 0x8C, 0x0F, 0x74, 0x1B, 0x7A } }, // WOW-33978patch9.0.1_Beta
+ { 0xC16F60A6BAD360C0ULL, { 0xBB, 0x8E, 0xF0, 0x39, 0x32, 0xAC, 0x38, 0xC6, 0xCE, 0x11, 0xFE, 0x67, 0x96, 0xEB, 0xBD, 0xEC } }, // WOW-33978patch9.0.1_Beta
+ { 0xC2BCD68E7A2AE4AFULL, { 0x89, 0x48, 0x11, 0x50, 0x8B, 0x28, 0xE9, 0x0B, 0xFA, 0xB0, 0x28, 0x4D, 0xA2, 0x3E, 0xE5, 0x06 } }, // WOW-33978patch9.0.1_Beta
+ { 0xC312DAF915B31117ULL, { 0xDA, 0xB0, 0x06, 0x6B, 0x4F, 0x8C, 0xD0, 0x79, 0x54, 0x8C, 0xE7, 0x52, 0x88, 0x4E, 0x19, 0x49 } }, // WOW-33978patch9.0.1_Beta
+ { 0xC63B911BD06869D3ULL, { 0xCB, 0x82, 0xD1, 0x56, 0x11, 0xA0, 0x96, 0xAA, 0xD6, 0xB2, 0xD9, 0x48, 0x8A, 0x87, 0x93, 0x9A } }, // WOW-33978patch9.0.1_Beta
+ { 0xC65443D5AB354639ULL, { 0xA9, 0x85, 0x72, 0x55, 0xBB, 0x6E, 0x5A, 0x75, 0xFA, 0x9A, 0xFE, 0xC8, 0xDA, 0xC2, 0xB0, 0x7A } }, // WOW-33978patch9.0.1_Beta
+ { 0xC8167C2D20426AD8ULL, { 0xF4, 0xF7, 0x7B, 0x2C, 0xA8, 0x36, 0xA4, 0xF9, 0xBE, 0x53, 0x61, 0x6E, 0xC6, 0x2D, 0x61, 0x84 } }, // WOW-33978patch9.0.1_Beta
+ { 0xC88BB3653C3C964FULL, { 0x7B, 0x61, 0xCA, 0x6E, 0x9C, 0x98, 0x29, 0xF2, 0xF4, 0x52, 0xD2, 0x17, 0x37, 0xD9, 0xD7, 0x23 } }, // WOW-33978patch9.0.1_Beta
+ { 0xC926C2CBE0DFF9BEULL, { 0x9D, 0x29, 0x47, 0x37, 0xAB, 0x13, 0xC3, 0x6B, 0x02, 0xEC, 0x0E, 0x0B, 0x77, 0x65, 0x7B, 0x13 } }, // WOW-33978patch9.0.1_Beta
+ { 0xC9A159E7B047AE82ULL, { 0xE4, 0x3C, 0x35, 0x49, 0xE6, 0x0E, 0xB1, 0x2C, 0x49, 0xF9, 0xE9, 0x57, 0x38, 0x61, 0xA5, 0xE0 } }, // WOW-33978patch9.0.1_Beta
+ { 0xC9F63551DC0A7DD3ULL, { 0xAA, 0xD6, 0xE9, 0xB5, 0x71, 0x97, 0x1E, 0x0A, 0xE9, 0x21, 0x22, 0xE9, 0x77, 0x28, 0x96, 0xDC } }, // WOW-33978patch9.0.1_Beta
+ { 0xC9FDAB91F9DABA18ULL, { 0x02, 0x5D, 0xF3, 0x9D, 0x8B, 0xF6, 0x32, 0xE6, 0x8B, 0x0A, 0x4E, 0x74, 0xC1, 0x44, 0x2A, 0x24 } }, // WOW-33978patch9.0.1_Beta
+ { 0xCA9C5B912FFBCAC7ULL, { 0xAF, 0xEE, 0xA5, 0xF1, 0x64, 0xC4, 0x0C, 0xF3, 0x84, 0x98, 0xD8, 0xBC, 0x5A, 0x0C, 0x6B, 0x8F } }, // WOW-33978patch9.0.1_Beta
+ { 0xCB4D2A3F81E1794EULL, { 0x12, 0x0C, 0x6B, 0x4A, 0x25, 0x41, 0xB5, 0xA9, 0x79, 0x81, 0x0C, 0x35, 0x38, 0x8C, 0x56, 0xF1 } }, // WOW-33978patch9.0.1_Beta
+ { 0xCBBACF102B89411FULL, { 0xE0, 0x4C, 0x71, 0x77, 0x15, 0xB0, 0x06, 0x11, 0xAC, 0x7E, 0xA9, 0x7D, 0x0B, 0x45, 0xAA, 0x0C } }, // WOW-33978patch9.0.1_Beta
+ { 0xD0C5486A7AD05CF9ULL, { 0x54, 0x84, 0xBE, 0x9C, 0xB3, 0x7D, 0xE9, 0x51, 0x12, 0xA1, 0x8B, 0x60, 0x52, 0xC5, 0xA7, 0xE5 } }, // WOW-33978patch9.0.1_Beta
+ { 0xD362C01C25B71B50ULL, { 0x08, 0xFB, 0x22, 0xF6, 0xA9, 0x52, 0x2A, 0x48, 0xCA, 0x24, 0x79, 0xCD, 0xED, 0x66, 0xA1, 0x75 } }, // WOW-33978patch9.0.1_Beta
+ { 0xD3CD986A5533AE96ULL, { 0x56, 0x70, 0x8F, 0x30, 0x77, 0xB7, 0x24, 0x88, 0x10, 0xC7, 0xB8, 0x7E, 0xDA, 0xCF, 0x25, 0xC2 } }, // WOW-33978patch9.0.1_Beta
+ { 0xD628DFD6FD4C4629ULL, { 0x30, 0x0F, 0x61, 0x98, 0xF8, 0xD3, 0x4F, 0x71, 0x81, 0x11, 0x61, 0x52, 0x13, 0x31, 0x4E, 0x07 } }, // WOW-33978patch9.0.1_Beta
+ { 0xD843A7FFCE96C7AEULL, { 0x08, 0xF1, 0xDE, 0x2D, 0x96, 0xEB, 0x99, 0x9C, 0x89, 0xA1, 0xD4, 0xE3, 0xBD, 0x22, 0x34, 0x3D } }, // WOW-33978patch9.0.1_Beta
+ { 0xD8EDA6A4C2799AFCULL, { 0x82, 0xD9, 0x7B, 0x8F, 0x98, 0x6A, 0xF1, 0x57, 0x66, 0xC8, 0x9F, 0x61, 0x1C, 0x14, 0x68, 0x88 } }, // WOW-33978patch9.0.1_Beta
+ { 0xDB37969AE172E0A2ULL, { 0xE0, 0x71, 0xBF, 0xF3, 0x31, 0x7D, 0x6F, 0xCC, 0x61, 0x12, 0xE8, 0xCB, 0xF0, 0x4B, 0x9E, 0x84 } }, // WOW-33978patch9.0.1_Beta
+ { 0xDBD4F370AE374627ULL, { 0x0D, 0x78, 0x08, 0xF6, 0x29, 0xBE, 0x2E, 0x0B, 0xE2, 0x80, 0x73, 0x1F, 0x9C, 0xCD, 0x51, 0xAE } }, // WOW-33978patch9.0.1_Beta
+ { 0xDC692CF534CF6094ULL, { 0xA6, 0x41, 0xD3, 0x32, 0xCE, 0x02, 0xCF, 0x14, 0x71, 0x42, 0x9F, 0xA3, 0x5B, 0x9C, 0xC2, 0x2A } }, // WOW-33978patch9.0.1_Beta
+ { 0xDE7D8C810DEBCCBBULL, { 0x39, 0xBD, 0x23, 0xF7, 0xBA, 0x29, 0x73, 0xCF, 0x57, 0x36, 0xE8, 0xA4, 0xD1, 0x37, 0xA2, 0x59 } }, // WOW-33978patch9.0.1_Beta
+ { 0xDFDBE74EFD0C1D9AULL, { 0x80, 0xA6, 0x40, 0x5D, 0xCA, 0x4A, 0xDB, 0x58, 0x04, 0xDF, 0xF3, 0x9E, 0x25, 0xAA, 0x6A, 0xF0 } }, // WOW-33978patch9.0.1_Beta
+ { 0xE186FB75B0C94A7CULL, { 0x9F, 0x7B, 0x27, 0xC6, 0xD8, 0x4C, 0x80, 0x59, 0xEF, 0xD8, 0x81, 0x56, 0x0C, 0x84, 0xFB, 0xF2 } }, // WOW-33978patch9.0.1_Beta
+ { 0xE26933D3B03457B8ULL, { 0xE4, 0xE9, 0x79, 0x3A, 0x4B, 0x0F, 0xFA, 0x09, 0xC6, 0x9A, 0x2F, 0xB3, 0xC4, 0x86, 0xE4, 0x5C } }, // WOW-33978patch9.0.1_Beta
+ { 0xE2D4CD545D19C5B3ULL, { 0x5F, 0x4D, 0xC6, 0x65, 0x17, 0xB5, 0x26, 0xCF, 0x48, 0x18, 0xDD, 0xDA, 0x50, 0xAE, 0xD6, 0x2A } }, // WOW-33978patch9.0.1_Beta
+ { 0xE321D1E0F5FD72D1ULL, { 0x39, 0x7A, 0xB9, 0x76, 0xC9, 0xFF, 0x03, 0x78, 0x37, 0xF9, 0x26, 0x00, 0xBE, 0x75, 0x4C, 0x63 } }, // WOW-33978patch9.0.1_Beta
+ { 0xE50F70F06A579FCCULL, { 0xE2, 0xB1, 0x53, 0x8D, 0x2C, 0x14, 0xAD, 0x00, 0xC9, 0xF2, 0xB1, 0xFE, 0x56, 0xC1, 0xF0, 0xD2 } }, // WOW-33978patch9.0.1_Beta
+ { 0xE6DE529515D5322EULL, { 0x1D, 0x58, 0x84, 0x6A, 0x1C, 0x87, 0x1B, 0xA0, 0x8C, 0x2E, 0xCD, 0x7B, 0x32, 0xFA, 0xCA, 0x41 } }, // WOW-33978patch9.0.1_Beta
+ { 0xE6F58B08B45D7A12ULL, { 0x18, 0xF3, 0x4D, 0xA5, 0xA6, 0x91, 0xF6, 0xAA, 0xF1, 0xF9, 0xA7, 0x05, 0xB6, 0x56, 0xE0, 0x1F } }, // WOW-33978patch9.0.1_Beta
+ { 0xE7357F7B88B8338DULL, { 0x9B, 0xAC, 0x5D, 0x21, 0x9C, 0xE7, 0x19, 0x84, 0xCB, 0xD6, 0xBE, 0x98, 0xE7, 0x2A, 0xB8, 0x3C } }, // WOW-33978patch9.0.1_Beta
+ { 0xE8F494F7E371D157ULL, { 0x4E, 0x2C, 0xDA, 0xA4, 0x18, 0x44, 0x03, 0x48, 0xE4, 0x39, 0x99, 0x5D, 0x64, 0x28, 0x4B, 0x73 } }, // WOW-33978patch9.0.1_Beta
+ { 0xE995E22AF7111D57ULL, { 0x33, 0xE8, 0xD6, 0x3D, 0xF4, 0xA8, 0xCE, 0x36, 0xD1, 0x88, 0xEC, 0x07, 0x22, 0x09, 0xD1, 0x84 } }, // WOW-33978patch9.0.1_Beta
+ { 0xEA9589F00A338035ULL, { 0xEC, 0xCB, 0x9C, 0xA5, 0x7C, 0xA0, 0x30, 0x33, 0x9B, 0x2D, 0xBA, 0x74, 0x5B, 0x5C, 0x14, 0x9B } }, // WOW-33978patch9.0.1_Beta
+ { 0xEAC344DACB040496ULL, { 0x51, 0x22, 0xD6, 0x18, 0x1F, 0x79, 0x71, 0x9A, 0x81, 0x7B, 0xBF, 0x84, 0xA2, 0xB5, 0x7B, 0xA1 } }, // WOW-33978patch9.0.1_Beta
+ { 0xEB5B9AA992D0582BULL, { 0x3A, 0xC4, 0xA8, 0x0F, 0x38, 0x66, 0x3F, 0xB3, 0xAD, 0xEB, 0x1C, 0xE5, 0x5E, 0xD3, 0xC1, 0x4D } }, // WOW-33978patch9.0.1_Beta
+ { 0xEB824892D843D365ULL, { 0x39, 0x4F, 0xCE, 0x26, 0x76, 0x68, 0x05, 0xA7, 0x68, 0x14, 0xB2, 0x5B, 0x4B, 0x72, 0xB4, 0xD8 } }, // WOW-33978patch9.0.1_Beta
+ { 0xEC434CD731FF1D6EULL, { 0x84, 0xC4, 0x3B, 0x20, 0xA6, 0x33, 0x66, 0x82, 0xB5, 0xAA, 0x1D, 0x7C, 0xFA, 0x00, 0xDA, 0xE3 } }, // WOW-33978patch9.0.1_Beta
+ { 0xED4548400C6CD9B3ULL, { 0xDD, 0xAE, 0x53, 0x8A, 0x39, 0x59, 0x16, 0x11, 0xBF, 0x1D, 0x2E, 0xEE, 0x97, 0x34, 0xF8, 0xDD } }, // WOW-33978patch9.0.1_Beta
+ { 0xED85FA32ABE4D31AULL, { 0xC9, 0x35, 0xBB, 0xCB, 0x24, 0x70, 0xF2, 0x97, 0xEA, 0x61, 0xF8, 0x66, 0x9D, 0xE7, 0x38, 0x10 } }, // WOW-33978patch9.0.1_Beta
+ { 0xEDB14BC9682C3EC7ULL, { 0x07, 0x63, 0x2A, 0xA3, 0x73, 0xD5, 0x08, 0xD9, 0x94, 0x81, 0x64, 0x6E, 0xF5, 0x2C, 0x6F, 0x21 } }, // WOW-33978patch9.0.1_Beta
+ { 0xEFD8CF7039C9E3ABULL, { 0x6B, 0xA7, 0x1A, 0xEC, 0x7C, 0xF7, 0xED, 0x83, 0xE7, 0xD4, 0x7A, 0x47, 0xE1, 0xAA, 0x97, 0x58 } }, // WOW-33978patch9.0.1_Beta
+ { 0xEFF36C5D384458ADULL, { 0x9F, 0x0B, 0x12, 0x0C, 0x9D, 0x86, 0xB5, 0x9B, 0x2C, 0x8B, 0x5E, 0xB0, 0x6C, 0xE0, 0x33, 0xC2 } }, // WOW-33978patch9.0.1_Beta
+ { 0xF04AF4C9E8BD1063ULL, { 0x62, 0xDB, 0x73, 0x69, 0x77, 0x96, 0x60, 0xE4, 0xAC, 0x83, 0xB1, 0xAF, 0x77, 0xCD, 0x86, 0x0A } }, // WOW-33978patch9.0.1_Beta
+ { 0xF0C135866D740895ULL, { 0x44, 0xAD, 0xC9, 0xAC, 0xBE, 0xD5, 0x0F, 0x49, 0x0A, 0xD8, 0xD5, 0xEE, 0xA8, 0x13, 0xDB, 0x69 } }, // WOW-33978patch9.0.1_Beta
+ { 0xF399E2091BB4EB3DULL, { 0xC3, 0x8C, 0x68, 0x01, 0x59, 0xE6, 0x3F, 0x03, 0x65, 0xFF, 0x10, 0xC6, 0xB4, 0x8C, 0xF6, 0xBC } }, // WOW-33978patch9.0.1_Beta
+ { 0xF4941ADAEFD62B50ULL, { 0x4E, 0x37, 0xCC, 0x48, 0xF5, 0x1E, 0x3B, 0x5F, 0x73, 0xCC, 0xD7, 0x41, 0x90, 0x91, 0xE3, 0xB6 } }, // WOW-33978patch9.0.1_Beta
+ { 0xF4A0D7C6BE16E9E6ULL, { 0xB9, 0x6B, 0x07, 0x4E, 0x60, 0xBB, 0x6B, 0x0C, 0x3F, 0xFD, 0x1F, 0xBC, 0x87, 0x77, 0x36, 0x7C } }, // WOW-33978patch9.0.1_Beta
+ { 0xF5BC79A1093D4297ULL, { 0xE1, 0x18, 0x0A, 0x55, 0xA6, 0x7B, 0x29, 0xAC, 0xDA, 0x9B, 0x6A, 0x3A, 0x70, 0x4C, 0x90, 0x27 } }, // WOW-33978patch9.0.1_Beta
+ { 0xF88CD79C16ED40C1ULL, { 0xED, 0x5B, 0xC5, 0xBF, 0x5D, 0x1E, 0xD1, 0x69, 0x51, 0x9F, 0x85, 0x9F, 0x4C, 0xEB, 0xAB, 0xA9 } }, // WOW-33978patch9.0.1_Beta
+ { 0xF9B971BF3BAE0F5FULL, { 0x41, 0x6A, 0x38, 0x03, 0x5B, 0xAD, 0xD4, 0xC2, 0x7A, 0x14, 0xF1, 0xE8, 0x74, 0xB1, 0x0F, 0xFC } }, // WOW-33978patch9.0.1_Beta
+ { 0xFA6C85CFB99D0738ULL, { 0x41, 0xFA, 0x48, 0x6B, 0x2F, 0xEB, 0x68, 0xFB, 0x96, 0x64, 0xD4, 0x22, 0xAA, 0xF1, 0x71, 0x38 } }, // WOW-33978patch9.0.1_Beta
+ { 0xFB90D71D100E9595ULL, { 0xB7, 0xA7, 0x6E, 0x35, 0x33, 0x75, 0x11, 0xB4, 0xA2, 0x6E, 0xE9, 0xBE, 0x0E, 0xCA, 0xD3, 0xD0 } }, // WOW-33978patch9.0.1_Beta
+ { 0xFD06442092131C5EULL, { 0x3E, 0x55, 0xE1, 0x47, 0xB6, 0x53, 0xB5, 0xF9, 0xE6, 0x8E, 0xAB, 0x44, 0x90, 0x8F, 0xBD, 0xC1 } }, // WOW-33978patch9.0.1_Beta
+ { 0xFD0BA919048A69AAULL, { 0x66, 0xE4, 0x75, 0xF4, 0x60, 0x26, 0xB0, 0x91, 0xAD, 0xD4, 0xA3, 0xE1, 0xBC, 0x61, 0x96, 0x91 } }, // WOW-33978patch9.0.1_Beta
+ { 0xFF08D3B90FB93B8CULL, { 0xD4, 0x27, 0x97, 0x22, 0xFB, 0x8B, 0xDD, 0x2A, 0xA8, 0xB3, 0xA4, 0xC7, 0x4E, 0xFD, 0x44, 0xCA } }, // WOW-33978patch9.0.1_Beta
+ { 0xFF7C9A1B789D0D42ULL, { 0xA9, 0xEC, 0x27, 0x53, 0x3B, 0x7D, 0x9D, 0xB1, 0xE2, 0x39, 0xEC, 0x68, 0x8B, 0xA6, 0x53, 0xF4 } }, // WOW-33978patch9.0.1_Beta
};
//-----------------------------------------------------------------------------
// Local functions
-static DWORD Rol32(DWORD dwValue, DWORD dwRolCount)
-{
- return (dwValue << dwRolCount) | (dwValue >> (32 - dwRolCount));
-}
-
static void Initialize(PCASC_SALSA20 pState, LPBYTE pbKey, DWORD cbKeyLength, LPBYTE pbVector)
{
const char * szConstants = (cbKeyLength == 32) ? szKeyConstant32 : szKeyConstant16;
diff --git a/dep/CascLib/src/CascDumpData.cpp b/dep/CascLib/src/CascDumpData.cpp
index 40e791f7a15..e29ad66bf63 100644
--- a/dep/CascLib/src/CascDumpData.cpp
+++ b/dep/CascLib/src/CascDumpData.cpp
@@ -25,7 +25,7 @@ int CaptureDownloadTag(CASC_DOWNLOAD_HEADER & DlHeader, CASC_TAG_ENTRY1 & DlTag,
//-----------------------------------------------------------------------------
// Local functions
-static char * StringFromLPTSTR(const TCHAR * szString, char * szBuffer, size_t cchBuffer)
+static char * StringFromLPTSTR(LPCTSTR szString, char * szBuffer, size_t cchBuffer)
{
char * szSaveBuffer = szBuffer;
char * szBufferEnd = szBuffer + cchBuffer - 1;
diff --git a/dep/CascLib/src/CascFiles.cpp b/dep/CascLib/src/CascFiles.cpp
index f47b8316693..c1a9e648c72 100644
--- a/dep/CascLib/src/CascFiles.cpp
+++ b/dep/CascLib/src/CascFiles.cpp
@@ -27,7 +27,7 @@ typedef DWORD (*PARSE_VARIABLE)(TCascStorage * hs, const char * szVariableName,
struct TBuildFileInfo
{
- const TCHAR * szFileName;
+ LPCTSTR szFileName;
CBLD_TYPE BuildFileType;
};
@@ -45,7 +45,7 @@ static const TBuildFileInfo BuildTypes[] =
{NULL, CascBuildNone}
};
-static const TCHAR * DataDirs[] =
+static LPCTSTR DataDirs[] =
{
_T("data") _T(PATH_SEP_STRING) _T("casc"), // Overwatch
_T("data"), // TACT casc (for Linux systems)
@@ -494,23 +494,17 @@ static int LoadQueryKey(const CASC_CSV_COLUMN & Column, QUERY_KEY & Key)
static void SetProductCodeName(TCascStorage * hs, LPCSTR szCodeName)
{
- TCHAR szCodeNameT[0x40];
-
if(hs->szCodeName == NULL && szCodeName != NULL)
{
- CascStrCopy(szCodeNameT, _countof(szCodeNameT), szCodeName);
- hs->szCodeName = CascNewStr(szCodeNameT);
+ hs->szCodeName = CascNewStrA2T(szCodeName);
}
}
static DWORD GetDefaultCdnPath(TCascStorage * hs, const CASC_CSV_COLUMN & Column)
{
- TCHAR szCdnPath[MAX_PATH];
-
if(hs->szCdnPath == NULL && Column.nLength != 0)
{
- CascStrCopy(szCdnPath, _countof(szCdnPath), Column.szValue);
- hs->szCdnPath = CascNewStr(szCdnPath);
+ hs->szCdnPath = CascNewStrA2T(Column.szValue);
}
return ERROR_SUCCESS;
@@ -544,8 +538,6 @@ static DWORD GetDefaultLocaleMask(TCascStorage * hs, const CASC_CSV_COLUMN & Col
static DWORD ParseFile_CDNS(TCascStorage * hs, CASC_CSV & Csv)
{
const char * szWantedRegion = hs->szRegion;
- TCHAR szCdnServers[MAX_PATH];
- TCHAR szCdnPath[MAX_PATH];
size_t nLineCount;
// Fix the region
@@ -562,12 +554,10 @@ static DWORD ParseFile_CDNS(TCascStorage * hs, CASC_CSV & Csv)
if(!strcmp(Csv[i]["Name!STRING:0"].szValue, szWantedRegion))
{
// Save the list of CDN servers
- CascStrCopy(szCdnServers, _countof(szCdnServers), Csv[i]["Hosts!STRING:0"].szValue);
- hs->szCdnServers = CascNewStr(szCdnServers);
+ hs->szCdnServers = CascNewStrA2T(Csv[i]["Hosts!STRING:0"].szValue);
// Save the CDN subpath
- CascStrCopy(szCdnPath, _countof(szCdnPath), Csv[i]["Path!STRING:0"].szValue);
- hs->szCdnPath = CascNewStr(szCdnPath);
+ hs->szCdnPath = CascNewStrA2T(Csv[i]["Path!STRING:0"].szValue);
// Check and return result
return (hs->szCdnServers && hs->szCdnPath) ? ERROR_SUCCESS : ERROR_BAD_FORMAT;
@@ -698,7 +688,7 @@ static DWORD ParseFile_BuildInfo(TCascStorage * hs, CASC_CSV & Csv)
static DWORD ParseFile_VersionsDb(TCascStorage * hs, CASC_CSV & Csv)
{
size_t nLineCount = Csv.GetLineCount();
- DWORD dwErrCode;
+ DWORD dwErrCode = ERROR_SUCCESS;
// Find the active config
for (size_t i = 0; i < nLineCount; i++)
@@ -723,7 +713,15 @@ static DWORD ParseFile_VersionsDb(TCascStorage * hs, CASC_CSV & Csv)
}
// Verify all variables
- return (hs->CdnBuildKey.pbData != NULL && hs->CdnConfigKey.pbData != NULL) ? ERROR_SUCCESS : ERROR_BAD_FORMAT;
+ if(hs->CdnBuildKey.pbData != NULL && hs->CdnConfigKey.pbData != NULL)
+ {
+ // If we have manually given build key, override the value
+ if(hs->szBuildKey != NULL)
+ dwErrCode = ConvertStringToBinary(hs->szBuildKey, MD5_STRING_SIZE, hs->CdnBuildKey.pbData);
+ return dwErrCode;
+ }
+
+ return ERROR_BAD_FORMAT;
}
}
@@ -860,9 +858,9 @@ static DWORD ParseFile_CdnBuild(TCascStorage * hs, void * pvListFile)
return dwErrCode;
}
-static DWORD CheckDataDirectory(TCascStorage * hs, TCHAR * szDirectory)
+static DWORD CheckDataDirectory(TCascStorage * hs, LPTSTR szDirectory)
{
- TCHAR * szDataPath;
+ LPTSTR szDataPath;
DWORD dwErrCode = ERROR_FILE_NOT_FOUND;
// Try all known subdirectories
@@ -888,7 +886,7 @@ static DWORD CheckDataDirectory(TCascStorage * hs, TCHAR * szDirectory)
return dwErrCode;
}
-static DWORD LoadCsvFile(TCascStorage * hs, const TCHAR * szFileName, PARSECSVFILE PfnParseProc, bool bHasHeader)
+static DWORD LoadCsvFile(TCascStorage * hs, LPCTSTR szFileName, PARSECSVFILE PfnParseProc, bool bHasHeader)
{
CASC_CSV Csv(0x40, bHasHeader);
DWORD dwErrCode;
@@ -899,9 +897,9 @@ static DWORD LoadCsvFile(TCascStorage * hs, const TCHAR * szFileName, PARSECSVFI
return dwErrCode;
}
-static const TCHAR * ExtractCdnServerName(TCHAR * szServerName, size_t cchServerName, const TCHAR * szCdnServers)
+static LPCTSTR ExtractCdnServerName(LPTSTR szServerName, size_t cchServerName, LPCTSTR szCdnServers)
{
- const TCHAR * szSeparator;
+ LPCTSTR szSeparator;
if(szCdnServers[0] != 0)
{
@@ -982,9 +980,9 @@ static void CreateRemoteAndLocalPath(TCascStorage * hs, CASC_CDN_DOWNLOAD & Cdns
LocalPath.AppendString(CdnsInfo.szExtension, false);
}
-static DWORD ForcePathExist(const TCHAR * szFileName, bool bIsFileName)
+static DWORD ForcePathExist(LPCTSTR szFileName, bool bIsFileName)
{
- TCHAR * szLocalPath;
+ LPTSTR szLocalPath;
size_t nIndex;
bool bFirstSeparator = false;
DWORD dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
@@ -1046,6 +1044,21 @@ static DWORD ForcePathExist(const TCHAR * szFileName, bool bIsFileName)
return dwErrCode;
}
+static bool FileAlreadyExists(LPCTSTR szFileName)
+{
+ TFileStream * pStream;
+ ULONGLONG FileSize = 0;
+
+ // The file open must succeed and also must be of non-zero size
+ if((pStream = FileStream_OpenFile(szFileName, 0)) != NULL)
+ {
+ FileStream_GetSize(pStream, &FileSize);
+ FileStream_Close(pStream);
+ }
+
+ return (FileSize != 0);
+}
+
static DWORD DownloadFile(
LPCTSTR szRemoteName,
LPCTSTR szLocalName,
@@ -1118,7 +1131,7 @@ static DWORD DownloadFileFromCDN2(TCascStorage * hs, CASC_CDN_DOWNLOAD & CdnsInf
CreateRemoteAndLocalPath(hs, CdnsInfo, RemotePath, LocalPath);
// Check whether the local file exists
- if((CdnsInfo.Flags & CASC_CDN_FORCE_DOWNLOAD) || (_taccess(LocalPath, 0) == -1))
+ if((CdnsInfo.Flags & CASC_CDN_FORCE_DOWNLOAD) || !FileAlreadyExists(LocalPath))
{
// Make sure that the path exists
dwErrCode = ForcePathExist(LocalPath, true);
@@ -1267,10 +1280,10 @@ DWORD GetFileSpanInfo(PCASC_CKEY_ENTRY pCKeyEntry, PULONGLONG PtrContentSize, PU
// Checks whether there is a ".build.info" or ".build.db".
// If yes, the function sets "szDataPath" and "szIndexPath"
// in the storage structure and returns ERROR_SUCCESS
-DWORD CheckGameDirectory(TCascStorage * hs, TCHAR * szDirectory)
+DWORD CheckGameDirectory(TCascStorage * hs, LPTSTR szDirectory)
{
TFileStream * pStream;
- TCHAR * szBuildFile;
+ LPTSTR szBuildFile;
DWORD dwErrCode = ERROR_FILE_NOT_FOUND;
// Try to find any of the root files used in the history
@@ -1504,8 +1517,7 @@ LPBYTE LoadFileToMemory(LPCTSTR szFileName, DWORD * pcbFileData)
DWORD cbFileData = 0;
// Open the stream for read-only access and read the file
- // Note that this fails when the game is running (sharing violation).
- pStream = FileStream_OpenFile(szFileName, STREAM_FLAG_READ_ONLY | STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE);
+ pStream = FileStream_OpenFile(szFileName, STREAM_FLAG_READ_ONLY | STREAM_FLAG_WRITE_SHARE | STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE);
if(pStream != NULL)
{
// Retrieve the file size
diff --git a/dep/CascLib/src/CascFindFile.cpp b/dep/CascLib/src/CascFindFile.cpp
index f33541f07d0..9694ae5e878 100644
--- a/dep/CascLib/src/CascFindFile.cpp
+++ b/dep/CascLib/src/CascFindFile.cpp
@@ -138,7 +138,7 @@ static bool DoStorageSearch_CKey(TCascSearch * pSearch, PCASC_FIND_DATA pFindDat
{
// Locate the n-th CKey entry.
pCKeyEntry = (PCASC_CKEY_ENTRY)hs->CKeyArray.ItemAt(pSearch->nFileIndex++);
-// BREAK_ON_XKEY3(pCKeyEntry->CKey, 0x2B, 0xfc, 0xe4);
+ //BREAK_ON_XKEY3(pCKeyEntry->CKey, 0x2B, 0xfc, 0xe4);
// Only report files that are unreferenced by the ROOT handler
if(pCKeyEntry->IsFile() && pCKeyEntry->RefCount == 0)
diff --git a/dep/CascLib/src/CascIndexFiles.cpp b/dep/CascLib/src/CascIndexFiles.cpp
index eddbdb67b0d..bfcee15330b 100644
--- a/dep/CascLib/src/CascIndexFiles.cpp
+++ b/dep/CascLib/src/CascIndexFiles.cpp
@@ -28,7 +28,7 @@ typedef bool (*EKEY_ENTRY_CALLBACK)(TCascStorage * hs, CASC_INDEX_HEADER & InHea
// Local functions
// "data.iXY"
-static bool IsIndexFileName_V1(const TCHAR * szFileName)
+static bool IsIndexFileName_V1(LPCTSTR szFileName)
{
// Check if the name looks like a valid index file
return (_tcslen(szFileName) == 8 &&
@@ -36,7 +36,7 @@ static bool IsIndexFileName_V1(const TCHAR * szFileName)
_tcsspn(szFileName + 6, szAllowedHexChars) == 2);
}
-static bool IsIndexFileName_V2(const TCHAR * szFileName)
+static bool IsIndexFileName_V2(LPCTSTR szFileName)
{
// Check if the name looks like a valid index file
return (_tcslen(szFileName) == 14 &&
@@ -116,7 +116,7 @@ static bool IndexDirectory_OnFileFound(
return true;
}
-static TCHAR * CreateIndexFileName(TCascStorage * hs, DWORD IndexValue, DWORD IndexVersion)
+static LPTSTR CreateIndexFileName(TCascStorage * hs, DWORD IndexValue, DWORD IndexVersion)
{
TCHAR szPlainName[0x40];
@@ -167,6 +167,7 @@ static LPBYTE CaptureGuardedBlock2(LPBYTE pbFileData, LPBYTE pbFileEnd, size_t E
PFILE_INDEX_GUARDED_BLOCK pBlock = (PFILE_INDEX_GUARDED_BLOCK)pbFileData;
LPBYTE pbEntryPtr;
size_t EntryCount;
+ unsigned int HashBlizzGet = 0;
unsigned int HashHigh = 0;
unsigned int HashLow = 0;
@@ -177,7 +178,10 @@ static LPBYTE CaptureGuardedBlock2(LPBYTE pbFileData, LPBYTE pbFileEnd, size_t E
if (pBlock->BlockSize == 0 || (pbFileData + sizeof(FILE_INDEX_GUARDED_BLOCK) + pBlock->BlockSize) > pbFileEnd)
return NULL;
- // Compute the hash entry-by-entry
+ //
+ // Verify the hash from the Blizzard Downloader
+ //
+
pbEntryPtr = pbFileData + sizeof(FILE_INDEX_GUARDED_BLOCK);
EntryCount = pBlock->BlockSize / EntryLength;
for (size_t i = 0; i < EntryCount; i++)
@@ -187,13 +191,39 @@ static LPBYTE CaptureGuardedBlock2(LPBYTE pbFileData, LPBYTE pbFileEnd, size_t E
}
// Verify hash
- if (HashHigh != pBlock->BlockHash)
- return NULL;
+ if (HashHigh == pBlock->BlockHash)
+ {
+ // Give the output
+ if (PtrBlockSize != NULL)
+ PtrBlockSize[0] = pBlock->BlockSize;
+ return (LPBYTE)(pBlock + 1);
+ }
- // Give the output
- if (PtrBlockSize != NULL)
- PtrBlockSize[0] = pBlock->BlockSize;
- return (LPBYTE)(pBlock + 1);
+ //
+ // Verify the hash from the Blizzget tool, which calculates the hash differently
+ // https://github.com/d07RiV/blizzget/blob/master/src/ngdp.cpp
+ // Function void DataStorage::writeIndex()
+ //
+
+ pbEntryPtr = pbFileData + sizeof(FILE_INDEX_GUARDED_BLOCK);
+ EntryCount = pBlock->BlockSize / EntryLength;
+ for (size_t i = 0; i < EntryCount; i++)
+ {
+ HashBlizzGet = hashlittle(pbEntryPtr, EntryLength, HashBlizzGet);
+ pbEntryPtr += EntryLength;
+ }
+
+ // Verify hash
+ if (HashBlizzGet == pBlock->BlockHash)
+ {
+ // Give the output
+ if (PtrBlockSize != NULL)
+ PtrBlockSize[0] = pBlock->BlockSize;
+ return (LPBYTE)(pBlock + 1);
+ }
+
+ // Hash mismatch
+ return NULL;
}
// Third method of checking a guarded block; There is 32-bit hash, followed by EKey entry
@@ -286,8 +316,11 @@ static DWORD LoadIndexItems(TCascStorage * hs, CASC_INDEX_HEADER & InHeader, EKE
while((pbEKeyEntry + EntryLength) <= pbEKeyEnd)
{
- // DOWNLOAD in HOTS
- //BREAK_ON_XKEY3(EKeyEntry.EKey, 0x09, 0xF3, 0xCD);
+ // ENCODING, DOWNLOAD, ROOT in Warcraft III Reforged build 14481
+ BREAK_ON_XKEY3(pbEKeyEntry, 0xcd, 0x3b, 0xd8);
+ BREAK_ON_XKEY3(pbEKeyEntry, 0xdb, 0xfa, 0x35);
+ BREAK_ON_XKEY3(pbEKeyEntry, 0x5c, 0xe8, 0x48);
+
if(!PfnEKeyEntry(hs, InHeader, pbEKeyEntry))
return ERROR_INDEX_PARSING_DONE;
@@ -487,17 +520,17 @@ static bool InsertEncodingEKeyToMap(TCascStorage * hs, CASC_INDEX_HEADER &, LPBY
return true;
}
-static DWORD ProcessLocalIndexFiles(TCascStorage * hs, EKEY_ENTRY_CALLBACK PfnEKeyEntry)
+static DWORD ProcessLocalIndexFiles(TCascStorage * hs, EKEY_ENTRY_CALLBACK PfnEKeyEntry, DWORD dwIndexCount)
{
DWORD dwErrCode = ERROR_SUCCESS;
// Load each index file
- for(DWORD i = 0; i < CASC_INDEX_COUNT; i++)
+ for(DWORD i = 0; i < dwIndexCount; i++)
{
CASC_INDEX & IndexFile = hs->IndexFiles[i];
// Inform the user about what we are doing
- if(InvokeProgressCallback(hs, "Loading index files", NULL, i, CASC_INDEX_COUNT))
+ if(InvokeProgressCallback(hs, "Loading index files", NULL, i, dwIndexCount))
{
dwErrCode = ERROR_CANCELLED;
break;
@@ -520,6 +553,7 @@ static DWORD ProcessLocalIndexFiles(TCascStorage * hs, EKEY_ENTRY_CALLBACK PfnEK
static DWORD LoadLocalIndexFiles(TCascStorage * hs)
{
ULONGLONG TotalSize = 0;
+ DWORD dwIndexCount = 0;
DWORD dwErrCode;
// Inform the user about what we are doing
@@ -529,6 +563,10 @@ static DWORD LoadLocalIndexFiles(TCascStorage * hs)
// Perform the directory scan
if((dwErrCode = ScanIndexDirectory(hs->szIndexPath, IndexDirectory_OnFileFound, hs)) == ERROR_SUCCESS)
{
+ // If no index file was found, we cannot load anything
+ if(hs->szIndexFormat == NULL)
+ return ERROR_FILE_NOT_FOUND;
+
// Load each index file
for(DWORD i = 0; i < CASC_INDEX_COUNT; i++)
{
@@ -541,16 +579,28 @@ static DWORD LoadLocalIndexFiles(TCascStorage * hs)
// WoW6 actually reads THE ENTIRE file to memory. Verified on Mac build (x64).
if((IndexFile.pbFileData = LoadFileToMemory(IndexFile.szFileName, &cbFileData)) == NULL)
- return ERROR_NOT_ENOUGH_MEMORY;
+ {
+ // Storages downloaded by Blizzget tool don't have all index files present
+ if((dwErrCode = GetLastError()) == ERROR_FILE_NOT_FOUND)
+ {
+ dwErrCode = ERROR_SUCCESS;
+ break;
+ }
+
+ return dwErrCode;
+ }
+
+ // Add to the total size of the index files
IndexFile.cbFileData = cbFileData;
TotalSize += cbFileData;
+ dwIndexCount++;
}
// Build the map of EKey -> IndexEKeyEntry
dwErrCode = hs->IndexEKeyMap.Create((size_t)(TotalSize / sizeof(FILE_EKEY_ENTRY)), CASC_EKEY_SIZE, 0);
if(dwErrCode == ERROR_SUCCESS)
{
- dwErrCode = ProcessLocalIndexFiles(hs, InsertEncodingEKeyToMap);
+ dwErrCode = ProcessLocalIndexFiles(hs, InsertEncodingEKeyToMap, dwIndexCount);
}
}
diff --git a/dep/CascLib/src/CascLib.h b/dep/CascLib/src/CascLib.h
index 8bf515abca9..b9a3ef7de0d 100644
--- a/dep/CascLib/src/CascLib.h
+++ b/dep/CascLib/src/CascLib.h
@@ -34,41 +34,43 @@ extern "C" {
//
// X - D for Debug version, R for Release version
// Y - A for ANSI version, U for Unicode version
-// Z - S for static-linked CRT library, D for multithreaded DLL CRT library
+// Z - S for static-linked CRT library, D for dynamic CRT library (dll)
//
-#if defined(_MSC_VER) && !defined(__CASCLIB_SELF__) && !defined(CASCLIB_NO_AUTO_LINK_LIBRARY)
- #ifdef _DEBUG // DEBUG VERSIONS
- #ifndef _UNICODE
- #ifdef _DLL
- #pragma comment(lib, "CascLibDAD.lib") // Debug Ansi CRT-DLL version
- #else
- #pragma comment(lib, "CascLibDAS.lib") // Debug Ansi CRT-LIB version
- #endif
- #else
- #ifdef _DLL
- #pragma comment(lib, "CascLibDUD.lib") // Debug Unicode CRT-DLL version
- #else
- #pragma comment(lib, "CascLibDUS.lib") // Debug Unicode CRT-LIB version
- #endif
- #endif
- #else // RELEASE VERSIONS
- #ifndef _UNICODE
- #ifdef _DLL
- #pragma comment(lib, "CascLibRAD.lib") // Release Ansi CRT-DLL version
+#if defined(_MSC_VER) && !defined(__CASCLIB_SELF__) && !defined(CASCLIB_NO_AUTO_LINK_LIBRARY)
+ #ifndef WDK_BUILD
+ #ifdef _DEBUG // DEBUG VERSIONS
+ #ifndef _UNICODE
+ #ifdef _DLL
+ #pragma comment(lib, "CascLibDAD.lib") // Debug Ansi CRT-DLL version
+ #else
+ #pragma comment(lib, "CascLibDAS.lib") // Debug Ansi CRT-LIB version
+ #endif
#else
- #pragma comment(lib, "CascLibRAS.lib") // Release Ansi CRT-LIB version
+ #ifdef _DLL
+ #pragma comment(lib, "CascLibDUD.lib") // Debug Unicode CRT-DLL version
+ #else
+ #pragma comment(lib, "CascLibDUS.lib") // Debug Unicode CRT-LIB version
+ #endif
#endif
- #else
- #ifdef _DLL
- #pragma comment(lib, "CascLibRUD.lib") // Release Unicode CRT-DLL version
+ #else // RELEASE VERSIONS
+ #ifndef _UNICODE
+ #ifdef _DLL
+ #pragma comment(lib, "CascLibRAD.lib") // Release Ansi CRT-DLL version
+ #else
+ #pragma comment(lib, "CascLibRAS.lib") // Release Ansi CRT-LIB version
+ #endif
#else
- #pragma comment(lib, "CascLibRUS.lib") // Release Unicode CRT-LIB version
+ #ifdef _DLL
+ #pragma comment(lib, "CascLibRUD.lib") // Release Unicode CRT-DLL version
+ #else
+ #pragma comment(lib, "CascLibRUS.lib") // Release Unicode CRT-LIB version
+ #endif
#endif
#endif
#endif
-
#endif
+
//-----------------------------------------------------------------------------
// Defines
@@ -159,7 +161,7 @@ typedef enum _CASC_STORAGE_INFO_CLASS
// Returns the total file count, including the offline files
CascStorageTotalFileCount,
-
+
CascStorageFeatures, // Returns the features flag
CascStorageInstalledLocales, // Not supported
CascStorageProduct, // Gives CASC_STORAGE_PRODUCT
@@ -187,7 +189,7 @@ typedef enum _CASC_NAME_TYPE
CascNameDataId, // Name created from file data id (FILE%08X.dat)
CascNameCKey, // Name created as string representation of CKey
CascNameEKey // Name created as string representation of EKey
-} CASC_NAME_TYPE, *PCASC_NAME_TYPE;
+} CASC_NAME_TYPE, *PCASC_NAME_TYPE;
// Structure for SFileFindFirstFile and SFileFindNextFile
typedef struct _CASC_FIND_DATA
@@ -195,7 +197,7 @@ typedef struct _CASC_FIND_DATA
// Full name of the found file. In case when this is CKey/EKey,
// this will be just string representation of the key stored in 'FileKey'
char szFileName[MAX_PATH];
-
+
// Content key. This is present if the CASC_FEATURE_ROOT_CKEY is present
BYTE CKey[MD5_HASH_SIZE];
@@ -213,7 +215,7 @@ typedef struct _CASC_FIND_DATA
// File data ID. Only valid if the storage supports file data IDs, otherwise CASC_INVALID_ID
DWORD dwFileDataId;
-
+
// Locale flags. Only valid if the storage supports locale flags, otherwise CASC_INVALID_ID
DWORD dwLocaleFlags;
@@ -246,7 +248,7 @@ typedef struct _CASC_STORAGE_TAGS
CASC_STORAGE_TAG Tags[1]; // Array of CASC tags
-} CASC_STORAGE_TAGS, *PCASC_STORAGE_TAGS;
+} CASC_STORAGE_TAGS, *PCASC_STORAGE_TAGS;
typedef struct _CASC_STORAGE_PRODUCT
{
@@ -333,10 +335,12 @@ typedef struct _CASC_OPEN_STORAGE_ARGS
// Any additional member from here on must be checked for availability using the ExtractVersionedArgument function.
// Example:
//
- // DWORD dwMyExtraMember = 0;
- // ExtractVersionedArgument(pArgs, offsetof(CASC_OPEN_STORAGE_ARGS, dwMyExtraMember), &dwMyExtraMember);
+ // LPCTSTR szBuildKey = NULL;
+ // ExtractVersionedArgument(pArgs, offsetof(CASC_OPEN_STORAGE_ARGS, szBuildId), &szBuildKey);
//
+ LPCTSTR szBuildKey; // If non-null, this will specify a build key (aka MD5 of build config that is different that current online version)
+
} CASC_OPEN_STORAGE_ARGS, *PCASC_OPEN_STORAGE_ARGS;
//-----------------------------------------------------------------------------
diff --git a/dep/CascLib/src/CascOpenStorage.cpp b/dep/CascLib/src/CascOpenStorage.cpp
index aab10d2c88a..d48ae50342f 100644
--- a/dep/CascLib/src/CascOpenStorage.cpp
+++ b/dep/CascLib/src/CascOpenStorage.cpp
@@ -14,6 +14,10 @@
#include "CascLib.h"
#include "CascCommon.h"
+#ifdef INTERLOCKED_NOT_SUPPORTED
+#pragma error Interlocked operations are not supported on this architecture. Multi-threaded access to CASC storages will not work properly.
+#endif
+
//-----------------------------------------------------------------------------
// Local defines
@@ -23,15 +27,21 @@
//-----------------------------------------------------------------------------
// DEBUG functions
-//#define CHECKED_KEY "2a378c"
+#define CHECKED_KEY {0x00, 0x00, 0x0F, 0x84}
#if defined(_DEBUG) && defined(CHECKED_KEY)
inline bool CheckForXKey(LPBYTE XKey)
{
- BYTE CheckedKey[4];
- ConvertStringToBinary(CHECKED_KEY, 6, CheckedKey);
- return (XKey[0] == CheckedKey[0] && XKey[1] == CheckedKey[1] && XKey[2] == CheckedKey[2]);
+ BYTE CheckedKey[] = CHECKED_KEY;
+
+ for(size_t i = 0; i < _countof(CheckedKey); i++)
+ {
+ if(XKey[i] != CheckedKey[i])
+ return false;
+ }
+
+ return true;
}
#define BREAK_ON_WATCHED(XKey) if(CheckForXKey((LPBYTE)XKey)) { __debugbreak(); }
@@ -54,14 +64,19 @@ TCascStorage::TCascStorage()
szRootPath = szDataPath = szIndexPath = szBuildFile = szCdnServers = szCdnPath = szCodeName = NULL;
szIndexFormat = NULL;
szRegion = NULL;
-
+ szBuildKey = NULL;
+
memset(DataFiles, 0, sizeof(DataFiles));
memset(IndexFiles, 0, sizeof(IndexFiles));
+ CascInitLock(StorageLock);
+ dwDefaultLocale = 0;
dwBuildNumber = 0;
dwFeatures = 0;
BuildFileType = CascBuildNone;
+ LastFailKeyName = 0;
LocalFiles = TotalFiles = EKeyEntries = EKeyLength = FileOffsetBits = 0;
+ pArgs = NULL;
}
TCascStorage::~TCascStorage()
@@ -81,6 +96,9 @@ TCascStorage::~TCascStorage()
// Cleanup space occupied by index files
FreeIndexFiles(this);
+ // Cleanup the lock
+ CascFreeLock(StorageLock);
+
// Free the file paths
CASC_FREE(szDataPath);
CASC_FREE(szRootPath);
@@ -90,6 +108,7 @@ TCascStorage::~TCascStorage()
CASC_FREE(szCdnPath);
CASC_FREE(szCodeName);
CASC_FREE(szRegion);
+ CASC_FREE(szBuildKey);
// Free the blobs
FreeCascBlob(&CdnConfigKey);
@@ -105,12 +124,15 @@ TCascStorage::~TCascStorage()
TCascStorage * TCascStorage::AddRef()
{
+ // Need this to be atomic to make multi-threaded file opens work
CascInterlockedIncrement(&dwRefCount);
return this;
}
TCascStorage * TCascStorage::Release()
{
+ // If the reference count reached zero, we close the archive
+ // Need this to be atomic to make multi-threaded file opens work
if(CascInterlockedDecrement(&dwRefCount) == 0)
{
delete this;
@@ -362,8 +384,6 @@ static DWORD InitCKeyArray(TCascStorage * hs)
if(dwErrCode != ERROR_SUCCESS)
return dwErrCode;
- // Insert the entry of ENCODING file. This is vital for its opening and loading
- InsertCKeyEntry(hs, hs->EncodingCKey);
return ERROR_SUCCESS;
}
@@ -433,9 +453,10 @@ static int LoadEncodingManifest(TCascStorage * hs)
if(InvokeProgressCallback(hs, "Loading ENCODING manifest", NULL, 0, 0))
return ERROR_CANCELLED;
- // Fill-in the information from the index entry
+ // Fill-in the information from the index entry and insert it to the file tree
if(!CopyEKeyEntry(hs, &CKeyEntry))
return ERROR_FILE_NOT_FOUND;
+ InsertCKeyEntry(hs, CKeyEntry);
// Load the entire encoding file to memory
pbEncodingFile = LoadInternalFileToMemory(hs, &hs->EncodingCKey, &cbEncodingFile);
@@ -809,7 +830,9 @@ static bool InsertWellKnownFile(TCascStorage * hs, const char * szFileName, CASC
// Insert the key to the root handler. Note that the file can already be referenced
// ("index" vs "vfs-root" in Warcraft III storages)
hs->pRootHandler->Insert(szFileName, pCKeyEntry);
- pCKeyEntry->Flags |= (CASC_CE_IN_BUILD | dwFlags);
+
+ // Copy some flags
+ pCKeyEntry->Flags |= (dwFlags | CASC_CE_IN_BUILD);
return true;
}
}
@@ -823,7 +846,7 @@ static bool InsertWellKnownFile(TCascStorage * hs, const char * szFileName, CASC
if(pCKeyEntry != NULL)
{
hs->pRootHandler->Insert(szFileName, pCKeyEntry);
- pCKeyEntry->Flags |= (CASC_CE_IN_BUILD | dwFlags);
+ pCKeyEntry->Flags |= (dwFlags | CASC_CE_IN_BUILD);
return true;
}
}
@@ -1123,7 +1146,7 @@ static DWORD LoadCascStorage(TCascStorage * hs, PCASC_OPEN_STORAGE_ARGS pArgs)
{
LPCTSTR szCodeName = NULL;
LPCTSTR szRegion = NULL;
- char szRegionA[0x40];
+ LPCTSTR szBuildKey = NULL;
DWORD dwLocaleMask = 0;
DWORD dwErrCode = ERROR_SUCCESS;
@@ -1131,18 +1154,19 @@ static DWORD LoadCascStorage(TCascStorage * hs, PCASC_OPEN_STORAGE_ARGS pArgs)
hs->pArgs = pArgs;
// Extract optional arguments
- ExtractVersionedArgument(pArgs, offsetof(CASC_OPEN_STORAGE_ARGS, dwLocaleMask), &dwLocaleMask);
+ ExtractVersionedArgument(pArgs, FIELD_OFFSET(CASC_OPEN_STORAGE_ARGS, dwLocaleMask), &dwLocaleMask);
// Extract the product code name
- if(ExtractVersionedArgument(pArgs, offsetof(CASC_OPEN_STORAGE_ARGS, szCodeName), &szCodeName) && szCodeName != NULL)
+ if(ExtractVersionedArgument(pArgs, FIELD_OFFSET(CASC_OPEN_STORAGE_ARGS, szCodeName), &szCodeName) && szCodeName != NULL)
hs->szCodeName = CascNewStr(szCodeName);
// Extract the region (optional)
- if(ExtractVersionedArgument(pArgs, offsetof(CASC_OPEN_STORAGE_ARGS, szRegion), &szRegion) && szRegion != NULL)
- {
- CascStrCopy(szRegionA, _countof(szRegionA), szRegion);
- hs->szRegion = CascNewStr(szRegionA);
- }
+ if(ExtractVersionedArgument(pArgs, FIELD_OFFSET(CASC_OPEN_STORAGE_ARGS, szRegion), &szRegion) && szRegion != NULL)
+ hs->szRegion = CascNewStrT2A(szRegion);
+
+ // Extract the build key (optional)
+ if(ExtractVersionedArgument(pArgs, FIELD_OFFSET(CASC_OPEN_STORAGE_ARGS, szBuildKey), &szBuildKey) && szBuildKey != NULL)
+ hs->szBuildKey = CascNewStrT2A(szBuildKey);
// For online storages, we need to load CDN servers
if ((dwErrCode == ERROR_SUCCESS) && (hs->dwFeatures & CASC_FEATURE_ONLINE))
@@ -1271,6 +1295,7 @@ static LPTSTR ParseOpenParams(LPCTSTR szParams, PCASC_OPEN_STORAGE_ARGS pArgs)
pArgs->szLocalPath = szParamsCopy;
pArgs->szCodeName = NULL;
pArgs->szRegion = NULL;
+ pArgs->szBuildKey = NULL;
// Find the first ":". This will indicate the end of local path and also begin of product code
if((szSeparator = _tcschr(szPlainName, _T(':'))) != NULL)
@@ -1284,6 +1309,13 @@ static LPTSTR ParseOpenParams(LPCTSTR szParams, PCASC_OPEN_STORAGE_ARGS pArgs)
{
pArgs->szRegion = szSeparator + 1;
szSeparator[0] = 0;
+
+ // Try again. If found, it is a build key (MD5 of a build file)
+ if((szSeparator = _tcschr(szSeparator + 1, _T(':'))) != NULL)
+ {
+ pArgs->szBuildKey = szSeparator + 1;
+ szSeparator[0] = 0;
+ }
}
}
}
diff --git a/dep/CascLib/src/CascPort.h b/dep/CascLib/src/CascPort.h
index 9f401f80b2e..8a296505c7e 100644
--- a/dep/CascLib/src/CascPort.h
+++ b/dep/CascLib/src/CascPort.h
@@ -37,11 +37,11 @@
#define WIN32_LEAN_AND_MEAN
#endif
-//#pragma warning(disable:4995) // warning C4995: 'sprintf': name was marked as #pragma deprecated
+ // Suppress definitions of `min` and `max` macros by <windows.h>:
+ #define NOMINMAX 1
#include <tchar.h>
#include <assert.h>
- #include <intrin.h> // Support for intrinsic functions
#include <ctype.h>
#include <io.h>
#include <stdio.h>
@@ -63,14 +63,21 @@
#define URL_SEP_CHAR '/'
#define PATH_SEP_CHAR '\\'
#define PATH_SEP_STRING "\\"
-
- #pragma intrinsic(memcmp, memcpy)
#define PLATFORM_WINDOWS
#define PLATFORM_DEFINED // The platform is known now
#endif
+#if _MSC_VER >= 1500
+ #include <intrin.h> // Support for intrinsic functions
+ #pragma intrinsic(memcmp, memcpy)
+#endif
+
+#ifndef FIELD_OFFSET
+#define FIELD_OFFSET(type, field) ((LONG)(size_t)&(((type *)0)->field))
+#endif
+
//-----------------------------------------------------------------------------
// Defines for Mac
@@ -93,6 +100,7 @@
#include <wchar.h>
#include <cassert>
#include <errno.h>
+ #include <pthread.h>
// Support for PowerPC on Max OS X
#if (__ppc__ == 1) || (__POWERPC__ == 1) || (_ARCH_PPC == 1)
@@ -111,11 +119,10 @@
#define URL_SEP_CHAR '/'
#define PATH_SEP_CHAR '/'
#define PATH_SEP_STRING "/"
-
+
#define PLATFORM_MAC
#define PLATFORM_DEFINED // The platform is known now
- #define FIELD_OFFSET(t,f) offsetof(t,f)
#endif
//-----------------------------------------------------------------------------
@@ -138,16 +145,16 @@
#include <wchar.h>
#include <assert.h>
#include <errno.h>
+ #include <pthread.h>
#define URL_SEP_CHAR '/'
#define PATH_SEP_CHAR '/'
#define PATH_SEP_STRING "/"
-
+
#define PLATFORM_LITTLE_ENDIAN
#define PLATFORM_LINUX
#define PLATFORM_DEFINED
- #define FIELD_OFFSET(t,f) offsetof(t,f)
#endif
//-----------------------------------------------------------------------------
@@ -270,9 +277,9 @@
#endif
#ifndef _countof
-#define _countof(x) (sizeof(x) / sizeof(x[0]))
+#define _countof(x) (sizeof(x) / sizeof(x[0]))
#endif
-
+
//-----------------------------------------------------------------------------
// Swapping functions
@@ -317,25 +324,51 @@
//-----------------------------------------------------------------------------
// Interlocked operations
-inline DWORD CascInterlockedIncrement(PDWORD PtrValue)
+inline DWORD CascInterlockedIncrement(DWORD * PtrValue)
{
#ifdef PLATFORM_WINDOWS
return (DWORD)InterlockedIncrement((LONG *)(PtrValue));
+#elif defined(__GNUC__)
+ return __sync_add_and_fetch(PtrValue, 1);
#else
- return ++PtrValue[0];
+ #define INTERLOCKED_NOT_SUPPORTED
+ return ++(*PtrValue);
#endif
}
-inline DWORD CascInterlockedDecrement(PDWORD PtrValue)
+inline DWORD CascInterlockedDecrement(DWORD * PtrValue)
{
#ifdef PLATFORM_WINDOWS
return (DWORD)InterlockedDecrement((LONG *)(PtrValue));
+#elif defined(__GNUC__)
+ return __sync_sub_and_fetch(PtrValue, 1);
#else
- return --PtrValue[0];
+ return --(*PtrValue);
#endif
}
//-----------------------------------------------------------------------------
+// Lock functions
+
+#ifdef PLATFORM_WINDOWS
+
+typedef RTL_CRITICAL_SECTION CASC_LOCK;
+#define CascInitLock(Lock) InitializeCriticalSection(&Lock);
+#define CascFreeLock(Lock) DeleteCriticalSection(&Lock);
+#define CascLock(Lock) EnterCriticalSection(&Lock);
+#define CascUnlock(Lock) LeaveCriticalSection(&Lock);
+
+#else
+
+typedef pthread_mutex_t CASC_LOCK;
+#define CascInitLock(Lock) pthread_mutex_init(&Lock, NULL);
+#define CascFreeLock(Lock) pthread_mutex_destroy(&Lock);
+#define CascLock(Lock) pthread_mutex_lock(&Lock);
+#define CascUnlock(Lock) pthread_mutex_unlock(&Lock);
+
+#endif
+
+//-----------------------------------------------------------------------------
// Forbidden functions, do not use
#ifdef __CASCLIB_SELF__
diff --git a/dep/CascLib/src/CascReadFile.cpp b/dep/CascLib/src/CascReadFile.cpp
index aa2a718198c..5bfc4f654a0 100644
--- a/dep/CascLib/src/CascReadFile.cpp
+++ b/dep/CascLib/src/CascReadFile.cpp
@@ -40,7 +40,10 @@ static DWORD OpenDataStream(TCascFile * hf, PCASC_FILE_SPAN pFileSpan, PCASC_CKE
{
DWORD dwArchiveIndex = pFileSpan->ArchiveIndex;
- // If the file is not open yet, do it
+ // Lock the storage to make the operation thread-safe
+ CascLock(hs->StorageLock);
+
+ // If the data archive is not open yet, open it now.
if(hs->DataFiles[dwArchiveIndex] == NULL)
{
// Prepare the name of the data file
@@ -53,6 +56,9 @@ static DWORD OpenDataStream(TCascFile * hf, PCASC_FILE_SPAN pFileSpan, PCASC_CKE
hs->DataFiles[dwArchiveIndex] = pStream;
}
+ // Unlock the storage
+ CascUnlock(hs->StorageLock);
+
// Return error or success
pFileSpan->pStream = hs->DataFiles[dwArchiveIndex];
return (pFileSpan->pStream != NULL) ? ERROR_SUCCESS : ERROR_FILE_NOT_FOUND;
@@ -257,7 +263,7 @@ static LPBYTE CaptureBlteFileFrame(CASC_FILE_FRAME & Frame, LPBYTE pbFramePtr, L
return pbFramePtr + sizeof(BLTE_FRAME);
}
-static DWORD LoadSpanFrames(PCASC_FILE_SPAN pFileSpan, PCASC_CKEY_ENTRY pCKeyEntry, DWORD DataFileOffset, LPBYTE pbFramePtr, LPBYTE pbFrameEnd, size_t cbHeaderSize)
+static DWORD LoadSpanFrames(PCASC_FILE_SPAN pFileSpan, PCASC_CKEY_ENTRY pCKeyEntry, ULONGLONG DataFileOffset, LPBYTE pbFramePtr, LPBYTE pbFrameEnd, size_t cbHeaderSize)
{
PCASC_FILE_FRAME pFrames = NULL;
DWORD ContentSize = 0;
@@ -420,8 +426,8 @@ static DWORD LoadEncodedHeaderAndSpanFrames(PCASC_FILE_SPAN pFileSpan, PCASC_CKE
// Load the array of frame headers
if (dwErrCode == ERROR_SUCCESS)
{
- assert((DWORD)(ReadOffset + cbHeaderSize) > (DWORD)ReadOffset);
- dwErrCode = LoadSpanFrames(pFileSpan, pCKeyEntry, (DWORD)(ReadOffset + cbHeaderSize), pbEncodedBuffer + cbHeaderSize, pbEncodedBuffer + cbEncodedBuffer, cbHeaderSize);
+ assert((ReadOffset + cbHeaderSize) > ReadOffset);
+ dwErrCode = LoadSpanFrames(pFileSpan, pCKeyEntry, ReadOffset + cbHeaderSize, pbEncodedBuffer + cbHeaderSize, pbEncodedBuffer + cbEncodedBuffer, cbHeaderSize);
}
}
else
@@ -821,7 +827,6 @@ static DWORD ReadFile_FrameCached(TCascFile * hf, LPBYTE pbBuffer, ULONGLONG Sta
PCASC_CKEY_ENTRY pCKeyEntry = hf->pCKeyEntry;
PCASC_FILE_SPAN pFileSpan = hf->pFileSpan;
PCASC_FILE_FRAME pFileFrame = NULL;
- ULONGLONG ByteOffset;
LPBYTE pbSaveBuffer = pbBuffer;
LPBYTE pbEncoded = NULL;
LPBYTE pbDecoded = NULL;
@@ -876,8 +881,7 @@ static DWORD ReadFile_FrameCached(TCascFile * hf, LPBYTE pbBuffer, ULONGLONG Sta
}
// Load the frame to the encoded buffer
- ByteOffset = pFileFrame->DataFileOffset;
- if(FileStream_Read(pFileSpan->pStream, &ByteOffset, pbEncoded, pFileFrame->EncodedSize))
+ if(FileStream_Read(pFileSpan->pStream, &pFileFrame->DataFileOffset, pbEncoded, pFileFrame->EncodedSize))
{
ULONGLONG EndOfCopy = CASCLIB_MIN(pFileFrame->EndOffset, EndOffset);
DWORD dwBytesToCopy = (DWORD)(EndOfCopy - StartOffset);
@@ -1143,7 +1147,7 @@ bool WINAPI CascSetFilePointer64(HANDLE hFile, LONGLONG DistanceToMove, PULONGLO
}
// Do not allow the file pointer to move to negative values
- if((FilePosition = FilePosition + DistanceToMove) < 0)
+ if((LONGLONG)(FilePosition = FilePosition + DistanceToMove) < 0)
FilePosition = 0;
hf->FilePointer = FilePosition;
}
@@ -1269,6 +1273,8 @@ bool WINAPI CascReadFile(HANDLE hFile, void * pvBuffer, DWORD dwBytesToRead, PDW
if(PtrBytesRead != NULL)
PtrBytesRead[0] = 0;
hf->FilePointer = SaveFilePointer;
- return false;
+
+ // If 0 bytes were requested, it's actually a success
+ return (dwBytesToRead == 0);
}
}
diff --git a/dep/CascLib/src/DllMain.rc b/dep/CascLib/src/DllMain.rc
index a6243d2540b..7007a24ab65 100644
--- a/dep/CascLib/src/DllMain.rc
+++ b/dep/CascLib/src/DllMain.rc
@@ -25,8 +25,8 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,50,0,181
- PRODUCTVERSION 1,50,0,181
+ FILEVERSION 1,50,0,197
+ PRODUCTVERSION 1,50,0,197
FILEFLAGSMASK 0x17L
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -42,12 +42,12 @@ BEGIN
BLOCK "040504b0"
BEGIN
VALUE "FileDescription", "CascLib library for reading Blizzard CASC storages"
- VALUE "FileVersion", "1, 50, 0, 181\0"
+ VALUE "FileVersion", "1, 50, 0, 197\0"
VALUE "InternalName", "CascLib"
VALUE "LegalCopyright", "Copyright (c) 2014 - 2019 Ladislav Zezula"
VALUE "OriginalFilename", "CascLib.dll"
VALUE "ProductName", "CascLib"
- VALUE "ProductVersion", "1, 50, 0, 181\0"
+ VALUE "ProductVersion", "1, 50, 0, 197\0"
END
END
BLOCK "VarFileInfo"
diff --git a/dep/CascLib/src/common/Common.cpp b/dep/CascLib/src/common/Common.cpp
index 1fc6cc977b4..c16323e0f5e 100644
--- a/dep/CascLib/src/common/Common.cpp
+++ b/dep/CascLib/src/common/Common.cpp
@@ -356,6 +356,44 @@ wchar_t * CascNewStr(const wchar_t * szString, size_t nCharsToReserve)
return szNewString;
}
+LPSTR CascNewStrT2A(LPCTSTR szString, size_t nCharsToReserve)
+{
+ LPSTR szNewString = NULL;
+ size_t nLength;
+
+ if(szString != NULL)
+ {
+ nLength = _tcslen(szString);
+ szNewString = CASC_ALLOC<char>(nLength + nCharsToReserve + 1);
+ if(szNewString != NULL)
+ {
+ CascStrCopy(szNewString, nLength + nCharsToReserve + 1, szString, nLength);
+// szNewString[nLength] = 0;
+ }
+ }
+
+ return szNewString;
+}
+
+LPTSTR CascNewStrA2T(LPCSTR szString, size_t nCharsToReserve)
+{
+ LPTSTR szNewString = NULL;
+ size_t nLength;
+
+ if(szString != NULL)
+ {
+ nLength = strlen(szString);
+ szNewString = CASC_ALLOC<TCHAR>(nLength + nCharsToReserve + 1);
+ if(szNewString != NULL)
+ {
+ CascStrCopy(szNewString, nLength + nCharsToReserve + 1, szString, nLength);
+// szNewString[nLength] = 0;
+ }
+ }
+
+ return szNewString;
+}
+
//-----------------------------------------------------------------------------
// String merging
@@ -387,7 +425,7 @@ LPTSTR GetLastPathPart(LPTSTR szWorkPath)
return NULL;
}
-bool CutLastPathPart(TCHAR * szWorkPath)
+bool CutLastPathPart(LPTSTR szWorkPath)
{
// Get the last part of the path
szWorkPath = GetLastPathPart(szWorkPath);
@@ -482,7 +520,7 @@ ULONGLONG CalcFileNameHash(const char * szFileName)
return CalcNormNameHash(szNormName, nLength);
}
-int ConvertDigitToInt32(const TCHAR * szString, PDWORD PtrValue)
+DWORD ConvertDigitToInt32(LPCTSTR szString, PDWORD PtrValue)
{
BYTE Digit;
@@ -494,7 +532,7 @@ int ConvertDigitToInt32(const TCHAR * szString, PDWORD PtrValue)
return (Digit > 0x0F) ? ERROR_BAD_FORMAT : ERROR_SUCCESS;
}
-int ConvertStringToInt08(const char * szString, PDWORD PtrValue)
+DWORD ConvertStringToInt08(LPCSTR szString, PDWORD PtrValue)
{
BYTE DigitOne = AsciiToUpperTable_BkSlash[szString[0]] - '0';
BYTE DigitTwo = AsciiToUpperTable_BkSlash[szString[1]] - '0';
@@ -510,7 +548,7 @@ int ConvertStringToInt08(const char * szString, PDWORD PtrValue)
return (DigitOne <= 0x0F && DigitTwo <= 0x0F) ? ERROR_SUCCESS : ERROR_BAD_FORMAT;
}
-int ConvertStringToInt32(const TCHAR * szString, size_t nMaxDigits, PDWORD PtrValue)
+DWORD ConvertStringToInt32(LPCTSTR szString, size_t nMaxDigits, PDWORD PtrValue)
{
// The number of digits must be even
assert((nMaxDigits & 0x01) == 0);
@@ -545,8 +583,8 @@ int ConvertStringToInt32(const TCHAR * szString, size_t nMaxDigits, PDWORD PtrVa
}
// Converts string blob to binary blob.
-int ConvertStringToBinary(
- const char * szString,
+DWORD ConvertStringToBinary(
+ LPCSTR szString,
size_t nMaxDigits,
LPBYTE pbBinary)
{
diff --git a/dep/CascLib/src/common/Common.h b/dep/CascLib/src/common/Common.h
index ddf8e136c9b..0037293f53d 100644
--- a/dep/CascLib/src/common/Common.h
+++ b/dep/CascLib/src/common/Common.h
@@ -166,6 +166,14 @@ void CASC_FREE(T *& ptr)
}
//-----------------------------------------------------------------------------
+// 32-bit ROL
+
+inline DWORD Rol32(DWORD dwValue, DWORD dwRolCount)
+{
+ return (dwValue << dwRolCount) | (dwValue >> (32 - dwRolCount));
+}
+
+//-----------------------------------------------------------------------------
// Big endian number manipulation
inline DWORD ConvertBytesToInteger_2(LPBYTE ValueAsBytes)
@@ -246,18 +254,18 @@ inline ULONGLONG ConvertBytesToInteger_5(LPBYTE ValueAsBytes)
inline void ConvertIntegerToBytes_4(DWORD Value, LPBYTE ValueAsBytes)
{
- ValueAsBytes[0] = (Value >> 0x18) & 0xFF;
- ValueAsBytes[1] = (Value >> 0x10) & 0xFF;
- ValueAsBytes[2] = (Value >> 0x08) & 0xFF;
- ValueAsBytes[3] = (Value >> 0x00) & 0xFF;
+ ValueAsBytes[0] = (BYTE)((Value >> 0x18) & 0xFF);
+ ValueAsBytes[1] = (BYTE)((Value >> 0x10) & 0xFF);
+ ValueAsBytes[2] = (BYTE)((Value >> 0x08) & 0xFF);
+ ValueAsBytes[3] = (BYTE)((Value >> 0x00) & 0xFF);
}
inline void ConvertIntegerToBytes_4_LE(DWORD Value, LPBYTE ValueAsBytes)
{
- ValueAsBytes[0] = (Value >> 0x00) & 0xFF;
- ValueAsBytes[1] = (Value >> 0x08) & 0xFF;
- ValueAsBytes[2] = (Value >> 0x10) & 0xFF;
- ValueAsBytes[3] = (Value >> 0x18) & 0xFF;
+ ValueAsBytes[0] = (BYTE)((Value >> 0x00) & 0xFF);
+ ValueAsBytes[1] = (BYTE)((Value >> 0x08) & 0xFF);
+ ValueAsBytes[2] = (BYTE)((Value >> 0x10) & 0xFF);
+ ValueAsBytes[3] = (BYTE)((Value >> 0x18) & 0xFF);
}
// Faster than memset(Buffer, 0, 0x10)
@@ -313,14 +321,17 @@ size_t CascStrPrintf(wchar_t * buffer, size_t nCount, const wchar_t * format, ..
//-----------------------------------------------------------------------------
// String allocation
-char * CascNewStr(const char * szString, size_t nCharsToReserve = 0);
+char * CascNewStr(const char * szString, size_t nCharsToReserve = 0);
wchar_t * CascNewStr(const wchar_t * szString, size_t nCharsToReserve = 0);
+LPSTR CascNewStrT2A(LPCTSTR szString, size_t nCharsToReserve = 0);
+LPTSTR CascNewStrA2T(LPCSTR szString, size_t nCharsToReserve = 0);
+
size_t CombinePath(LPTSTR szBuffer, size_t nMaxChars, char chSeparator, va_list argList);
size_t CombinePath(LPTSTR szBuffer, size_t nMaxChars, char chSeparator, ...);
LPTSTR CombinePath(LPCTSTR szPath, LPCTSTR szSubDir);
LPTSTR GetLastPathPart(LPTSTR szWorkPath);
-bool CutLastPathPart(TCHAR * szWorkPath);
+bool CutLastPathPart(LPTSTR szWorkPath);
size_t NormalizeFileName_UpperBkSlash(char * szNormName, const char * szFileName, size_t cchMaxChars);
size_t NormalizeFileName_LowerSlash(char * szNormName, const char * szFileName, size_t cchMaxChars);
@@ -328,10 +339,10 @@ size_t NormalizeFileName_LowerSlash(char * szNormName, const char * szFileName,
ULONGLONG CalcNormNameHash(const char * szNormName, size_t nLength);
ULONGLONG CalcFileNameHash(const char * szFileName);
-int ConvertDigitToInt32(const TCHAR * szString, PDWORD PtrValue);
-int ConvertStringToInt08(const char * szString, PDWORD PtrValue);
-int ConvertStringToInt32(const TCHAR * szString, size_t nMaxDigits, PDWORD PtrValue);
-int ConvertStringToBinary(const char * szString, size_t nMaxDigits, LPBYTE pbBinary);
+DWORD ConvertDigitToInt32(LPCTSTR szString, PDWORD PtrValue);
+DWORD ConvertStringToInt08(LPCSTR szString, PDWORD PtrValue);
+DWORD ConvertStringToInt32(LPCTSTR szString, size_t nMaxDigits, PDWORD PtrValue);
+DWORD ConvertStringToBinary(LPCSTR szString, size_t nMaxDigits, LPBYTE pbBinary);
//-----------------------------------------------------------------------------
// Conversion from binary array to string. The caller must ensure that
diff --git a/dep/CascLib/src/common/Csv.cpp b/dep/CascLib/src/common/Csv.cpp
index c665fc00c4c..818973e9603 100644
--- a/dep/CascLib/src/common/Csv.cpp
+++ b/dep/CascLib/src/common/Csv.cpp
@@ -185,7 +185,7 @@ CASC_CSV::~CASC_CSV()
m_szCsvFile = NULL;
}
-DWORD CASC_CSV::Load(const TCHAR * szFileName)
+DWORD CASC_CSV::Load(LPCTSTR szFileName)
{
DWORD cbFileData = 0;
DWORD dwErrCode = ERROR_SUCCESS;
diff --git a/dep/CascLib/src/common/Csv.h b/dep/CascLib/src/common/Csv.h
index 394eab1e2f0..2fcee847703 100644
--- a/dep/CascLib/src/common/Csv.h
+++ b/dep/CascLib/src/common/Csv.h
@@ -70,7 +70,7 @@ class CASC_CSV
~CASC_CSV();
DWORD Load(LPBYTE pbData, size_t cbData);
- DWORD Load(const TCHAR * szFileName);
+ DWORD Load(LPCTSTR szFileName);
bool LoadNextLine();
const CASC_CSV_COLUMN & operator[](const char * szColumnName) const;
diff --git a/dep/CascLib/src/common/Directory.cpp b/dep/CascLib/src/common/Directory.cpp
index 387ca3a8ea4..57c7d552733 100644
--- a/dep/CascLib/src/common/Directory.cpp
+++ b/dep/CascLib/src/common/Directory.cpp
@@ -15,7 +15,7 @@
//-----------------------------------------------------------------------------
// Public functions
-bool DirectoryExists(const TCHAR * szDirectory)
+bool DirectoryExists(LPCTSTR szDirectory)
{
#ifdef PLATFORM_WINDOWS
@@ -38,7 +38,7 @@ bool DirectoryExists(const TCHAR * szDirectory)
return false;
}
-bool MakeDirectory(const TCHAR * szDirectory)
+bool MakeDirectory(LPCTSTR szDirectory)
{
#ifdef PLATFORM_WINDOWS
@@ -60,7 +60,7 @@ int ScanIndexDirectory(
#ifdef PLATFORM_WINDOWS
WIN32_FIND_DATA wf;
- TCHAR * szSearchMask;
+ LPTSTR szSearchMask;
HANDLE hFind;
// Prepare the search mask
diff --git a/dep/CascLib/src/common/FileStream.cpp b/dep/CascLib/src/common/FileStream.cpp
index ab591a2e3f1..350b0540cf4 100644
--- a/dep/CascLib/src/common/FileStream.cpp
+++ b/dep/CascLib/src/common/FileStream.cpp
@@ -89,7 +89,7 @@ static bool BaseFile_Create(TFileStream * pStream)
return true;
}
-static bool BaseFile_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD dwStreamFlags)
+static bool BaseFile_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStreamFlags)
{
#ifdef PLATFORM_WINDOWS
{
@@ -160,66 +160,72 @@ static bool BaseFile_Read(
void * pvBuffer, // Pointer to data to be read
DWORD dwBytesToRead) // Number of bytes to read from the file
{
- ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
DWORD dwBytesRead = 0; // Must be set by platform-specific code
-#ifdef PLATFORM_WINDOWS
+ // Synchronize the access to the TFileStream structure
+ CascLock(pStream->Lock);
{
- // Note: We no longer support Windows 9x.
- // Thus, we can use the OVERLAPPED structure to specify
- // file offset to read from file. This allows us to skip
- // one system call to SetFilePointer
-
- // Update the byte offset
- pStream->Base.File.FilePos = ByteOffset;
+ ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
- // Read the data
- if(dwBytesToRead != 0)
+#ifdef PLATFORM_WINDOWS
{
- OVERLAPPED Overlapped;
+ // Note: We no longer support Windows 9x.
+ // Thus, we can use the OVERLAPPED structure to specify
+ // file offset to read from file. This allows us to skip
+ // one system call to SetFilePointer
- Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
- Overlapped.Offset = (DWORD)ByteOffset;
- Overlapped.hEvent = NULL;
- if(!ReadFile(pStream->Base.File.hFile, pvBuffer, dwBytesToRead, &dwBytesRead, &Overlapped))
- return false;
+ // Update the byte offset
+ pStream->Base.File.FilePos = ByteOffset;
+
+ // Read the data
+ if (dwBytesToRead != 0)
+ {
+ OVERLAPPED Overlapped;
+
+ Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
+ Overlapped.Offset = (DWORD)ByteOffset;
+ Overlapped.hEvent = NULL;
+ if (!ReadFile(pStream->Base.File.hFile, pvBuffer, dwBytesToRead, &dwBytesRead, &Overlapped))
+ return false;
+ }
}
- }
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
- {
- ssize_t bytes_read;
-
- // If the byte offset is different from the current file position,
- // we have to update the file position
- if(ByteOffset != pStream->Base.File.FilePos)
{
- if(lseek64((intptr_t)pStream->Base.File.hFile, (off64_t)(ByteOffset), SEEK_SET) == (off64_t)-1)
+ ssize_t bytes_read;
+
+ // If the byte offset is different from the current file position,
+ // we have to update the file position
+ if (ByteOffset != pStream->Base.File.FilePos)
{
- SetLastError(errno);
- return false;
+ if (lseek64((intptr_t)pStream->Base.File.hFile, (off64_t)(ByteOffset), SEEK_SET) == (off64_t)-1)
+ {
+ SetLastError(errno);
+ return false;
+ }
+ pStream->Base.File.FilePos = ByteOffset;
}
- pStream->Base.File.FilePos = ByteOffset;
- }
- // Perform the read operation
- if(dwBytesToRead != 0)
- {
- bytes_read = read((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToRead);
- if(bytes_read == -1)
+ // Perform the read operation
+ if (dwBytesToRead != 0)
{
- SetLastError(errno);
- return false;
- }
+ bytes_read = read((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToRead);
+ if (bytes_read == -1)
+ {
+ SetLastError(errno);
+ return false;
+ }
- dwBytesRead = (DWORD)(size_t)bytes_read;
+ dwBytesRead = (DWORD)(size_t)bytes_read;
+ }
}
- }
#endif
- // Increment the current file position by number of bytes read
- pStream->Base.File.FilePos = ByteOffset + dwBytesRead;
+ // Increment the current file position by number of bytes read
+ pStream->Base.File.FilePos = ByteOffset + dwBytesRead;
+ }
+ CascUnlock(pStream->Lock);
// If the number of bytes read doesn't match to required amount, return false
// However, Blizzard's CASC handlers read encoded data so that if less than expected
@@ -249,67 +255,73 @@ static bool BaseFile_Read(
static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void * pvBuffer, DWORD dwBytesToWrite)
{
- ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
DWORD dwBytesWritten = 0; // Must be set by platform-specific code
-#ifdef PLATFORM_WINDOWS
+ // Synchronize the access to the TFileStream structure
+ CascLock(pStream->Lock);
{
- // Note: We no longer support Windows 9x.
- // Thus, we can use the OVERLAPPED structure to specify
- // file offset to read from file. This allows us to skip
- // one system call to SetFilePointer
-
- // Update the byte offset
- pStream->Base.File.FilePos = ByteOffset;
+ ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
- // Read the data
- if(dwBytesToWrite != 0)
+#ifdef PLATFORM_WINDOWS
{
- OVERLAPPED Overlapped;
+ // Note: We no longer support Windows 9x.
+ // Thus, we can use the OVERLAPPED structure to specify
+ // file offset to read from file. This allows us to skip
+ // one system call to SetFilePointer
- Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
- Overlapped.Offset = (DWORD)ByteOffset;
- Overlapped.hEvent = NULL;
- if(!WriteFile(pStream->Base.File.hFile, pvBuffer, dwBytesToWrite, &dwBytesWritten, &Overlapped))
- return false;
+ // Update the byte offset
+ pStream->Base.File.FilePos = ByteOffset;
+
+ // Read the data
+ if (dwBytesToWrite != 0)
+ {
+ OVERLAPPED Overlapped;
+
+ Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
+ Overlapped.Offset = (DWORD)ByteOffset;
+ Overlapped.hEvent = NULL;
+ if (!WriteFile(pStream->Base.File.hFile, pvBuffer, dwBytesToWrite, &dwBytesWritten, &Overlapped))
+ return false;
+ }
}
- }
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
- {
- ssize_t bytes_written;
-
- // If the byte offset is different from the current file position,
- // we have to update the file position
- if(ByteOffset != pStream->Base.File.FilePos)
{
- if(lseek64((intptr_t)pStream->Base.File.hFile, (off64_t)(ByteOffset), SEEK_SET) == (off64_t)-1)
+ ssize_t bytes_written;
+
+ // If the byte offset is different from the current file position,
+ // we have to update the file position
+ if (ByteOffset != pStream->Base.File.FilePos)
+ {
+ if (lseek64((intptr_t)pStream->Base.File.hFile, (off64_t)(ByteOffset), SEEK_SET) == (off64_t)-1)
+ {
+ SetLastError(errno);
+ return false;
+ }
+ pStream->Base.File.FilePos = ByteOffset;
+ }
+
+ // Perform the read operation
+ bytes_written = write((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToWrite);
+ if (bytes_written == -1)
{
SetLastError(errno);
return false;
}
- pStream->Base.File.FilePos = ByteOffset;
- }
- // Perform the read operation
- bytes_written = write((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToWrite);
- if(bytes_written == -1)
- {
- SetLastError(errno);
- return false;
+ dwBytesWritten = (DWORD)(size_t)bytes_written;
}
-
- dwBytesWritten = (DWORD)(size_t)bytes_written;
- }
#endif
- // Increment the current file position by number of bytes read
- pStream->Base.File.FilePos = ByteOffset + dwBytesWritten;
+ // Increment the current file position by number of bytes read
+ pStream->Base.File.FilePos = ByteOffset + dwBytesWritten;
- // Also modify the file size, if needed
- if(pStream->Base.File.FilePos > pStream->Base.File.FileSize)
- pStream->Base.File.FileSize = pStream->Base.File.FilePos;
+ // Also modify the file size, if needed
+ if(pStream->Base.File.FilePos > pStream->Base.File.FileSize)
+ pStream->Base.File.FileSize = pStream->Base.File.FilePos;
+ }
+ CascUnlock(pStream->Lock);
if(dwBytesWritten != dwBytesToWrite)
SetLastError(ERROR_DISK_FULL);
@@ -383,12 +395,8 @@ static bool BaseFile_GetPos(TFileStream * pStream, ULONGLONG * pByteOffset)
static bool BaseFile_Replace(TFileStream * pStream, TFileStream * pNewStream)
{
#ifdef PLATFORM_WINDOWS
- // Delete the original stream file. Don't check the result value,
- // because if the file doesn't exist, it would fail
- DeleteFile(pStream->szFileName);
-
// Rename the new file to the old stream's file
- return (bool)MoveFile(pNewStream->szFileName, pStream->szFileName);
+ return (bool)MoveFileEx(pNewStream->szFileName, pStream->szFileName, MOVEFILE_COPY_ALLOWED | MOVEFILE_REPLACE_EXISTING);
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
@@ -405,19 +413,24 @@ static bool BaseFile_Replace(TFileStream * pStream, TFileStream * pNewStream)
static void BaseFile_Close(TFileStream * pStream)
{
- if(pStream->Base.File.hFile != INVALID_HANDLE_VALUE)
+ // Synchronize the access to multiple threads
+ CascLock(pStream->Lock);
{
+ if(pStream->Base.File.hFile != INVALID_HANDLE_VALUE)
+ {
#ifdef PLATFORM_WINDOWS
- CloseHandle(pStream->Base.File.hFile);
+ CloseHandle(pStream->Base.File.hFile);
#endif
#if defined(PLATFORM_MAC) || defined(PLATFORM_LINUX)
- close((intptr_t)pStream->Base.File.hFile);
+ close((intptr_t)pStream->Base.File.hFile);
#endif
- }
+ }
- // Also invalidate the handle
- pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
+ // Also invalidate the handle
+ pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
+ }
+ CascUnlock(pStream->Lock);
}
// Initializes base functions for the disk file
@@ -436,7 +449,7 @@ static void BaseFile_Init(TFileStream * pStream)
//-----------------------------------------------------------------------------
// Local functions - base memory-mapped file support
-static bool BaseMap_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD dwStreamFlags)
+static bool BaseMap_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStreamFlags)
{
#ifdef PLATFORM_WINDOWS
@@ -584,7 +597,7 @@ static void BaseMap_Init(TFileStream * pStream)
//-----------------------------------------------------------------------------
// Local functions - base HTTP file support
-static const TCHAR * BaseHttp_ExtractServerName(const TCHAR * szFileName, TCHAR * szServerName)
+static LPCTSTR BaseHttp_ExtractServerName(LPCTSTR szFileName, LPTSTR szServerName)
{
// Check for HTTP
if(!_tcsnicmp(szFileName, _T("http://"), 7))
@@ -607,7 +620,7 @@ static const TCHAR * BaseHttp_ExtractServerName(const TCHAR * szFileName, TCHAR
return szFileName;
}
-static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD dwStreamFlags)
+static bool BaseHttp_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStreamFlags)
{
#ifdef PLATFORM_WINDOWS
@@ -1018,13 +1031,13 @@ static STREAM_INIT StreamBaseInit[4] =
// The stream structure is created as flat block, variable length
// The file name is placed after the end of the stream structure data
static TFileStream * AllocateFileStream(
- const TCHAR * szFileName,
+ LPCTSTR szFileName,
size_t StreamSize,
DWORD dwStreamFlags)
{
TFileStream * pMaster = NULL;
TFileStream * pStream;
- const TCHAR * szNextFile = szFileName;
+ LPCTSTR szNextFile = szFileName;
size_t FileNameSize;
// Sanity check
@@ -1063,10 +1076,13 @@ static TFileStream * AllocateFileStream(
pStream->dwFlags = dwStreamFlags;
// Initialize the file name
- pStream->szFileName = (TCHAR *)((BYTE *)pStream + StreamSize);
+ pStream->szFileName = (LPTSTR)((BYTE *)pStream + StreamSize);
memcpy(pStream->szFileName, szFileName, FileNameSize);
pStream->szFileName[FileNameSize / sizeof(TCHAR)] = 0;
+ // Initialize the stream lock
+ CascInitLock(pStream->Lock);
+
// Initialize the stream functions
StreamBaseInit[dwStreamFlags & 0x03](pStream);
}
@@ -1367,7 +1383,7 @@ static bool FlatStream_CreateMirror(TBlockStream * pStream)
return true;
}
-static TFileStream * FlatStream_Open(const TCHAR * szFileName, DWORD dwStreamFlags)
+static TFileStream * FlatStream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
{
TBlockStream * pStream;
ULONGLONG ByteOffset = 0;
@@ -1788,7 +1804,7 @@ static bool PartStream_CreateMirror(TBlockStream * pStream)
return true;
}
-static TFileStream * PartStream_Open(const TCHAR * szFileName, DWORD dwStreamFlags)
+static TFileStream * PartStream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
{
TBlockStream * pStream;
@@ -1898,13 +1914,6 @@ static const char * AuthCodeArray[] =
NULL
};
-static DWORD Rol32(DWORD dwValue, DWORD dwRolCount)
-{
- DWORD dwShiftRight = 32 - dwRolCount;
-
- return (dwValue << dwRolCount) | (dwValue >> dwShiftRight);
-}
-
static void CreateKeyFromAuthCode(
LPBYTE pbKeyBuffer,
const char * szAuthCode)
@@ -2105,7 +2114,7 @@ static bool EncrStream_BlockRead(
return true;
}
-static TFileStream * EncrStream_Open(const TCHAR * szFileName, DWORD dwStreamFlags)
+static TFileStream * EncrStream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
{
TEncryptedStream * pStream;
@@ -2232,14 +2241,14 @@ static void Block4Stream_Close(TBlockStream * pStream)
return;
}
-static TFileStream * Block4Stream_Open(const TCHAR * szFileName, DWORD dwStreamFlags)
+static TFileStream * Block4Stream_Open(LPCTSTR szFileName, DWORD dwStreamFlags)
{
TBaseProviderData * NewBaseArray = NULL;
ULONGLONG RemainderBlock;
ULONGLONG BlockCount;
ULONGLONG FileSize;
TBlockStream * pStream;
- TCHAR * szNameBuff;
+ LPTSTR szNameBuff;
size_t nNameLength;
DWORD dwBaseFiles = 0;
DWORD dwBaseFlags;
@@ -2458,7 +2467,7 @@ TFileStream * FileStream_OpenFile(
*
* \a pStream Pointer to an open stream
*/
-const TCHAR * FileStream_GetFileName(TFileStream * pStream)
+LPCTSTR FileStream_GetFileName(TFileStream * pStream)
{
assert(pStream != NULL);
return pStream->szFileName;
@@ -2754,6 +2763,9 @@ void FileStream_Close(TFileStream * pStream)
else if(pStream->BaseClose != NULL)
pStream->BaseClose(pStream);
+ // Free the stream lock
+ CascFreeLock(pStream->Lock);
+
// Free the stream itself
CASC_FREE(pStream);
}
diff --git a/dep/CascLib/src/common/FileStream.h b/dep/CascLib/src/common/FileStream.h
index e934cca062f..acd0683a596 100644
--- a/dep/CascLib/src/common/FileStream.h
+++ b/dep/CascLib/src/common/FileStream.h
@@ -48,7 +48,7 @@ typedef bool (*STREAM_CREATE)(
typedef bool (*STREAM_OPEN)(
struct TFileStream * pStream, // Pointer to an unopened stream
- const TCHAR * szFileName, // Pointer to file name to be open
+ LPCTSTR szFileName, // Pointer to file name to be open
DWORD dwStreamFlags // Stream flags
);
@@ -205,11 +205,12 @@ struct TFileStream
STREAM_CLOSE BaseClose; // Pointer to function closing the stream
// Base provider data (file size, file position)
- TBaseProviderData Base;
+ TBaseProviderData Base; // Stream information, like size or current position
+ CASC_LOCK Lock; // For multi-threaded synchronization
// Stream provider data
TFileStream * pMaster; // Master stream (e.g. MPQ on a web server)
- TCHAR * szFileName; // File name (self-relative pointer)
+ LPTSTR szFileName; // File name (self-relative pointer)
ULONGLONG StreamSize; // Stream size (can be less than file size)
ULONGLONG StreamPos; // Stream position
@@ -249,7 +250,7 @@ struct TEncryptedStream : public TBlockStream
TFileStream * FileStream_CreateFile(LPCTSTR szFileName, DWORD dwStreamFlags);
TFileStream * FileStream_OpenFile(LPCTSTR szFileName, DWORD dwStreamFlags);
-const TCHAR * FileStream_GetFileName(TFileStream * pStream);
+LPCTSTR FileStream_GetFileName(TFileStream * pStream);
size_t FileStream_Prefix(LPCTSTR szFileName, DWORD * pdwProvider);
bool FileStream_SetCallback(TFileStream * pStream, STREAM_DOWNLOAD_CALLBACK pfnCallback, void * pvUserData);
diff --git a/dep/CascLib/src/common/FileTree.cpp b/dep/CascLib/src/common/FileTree.cpp
index ceb578cf578..6a44940bd8a 100644
--- a/dep/CascLib/src/common/FileTree.cpp
+++ b/dep/CascLib/src/common/FileTree.cpp
@@ -293,13 +293,7 @@ PCASC_FILE_NODE CASC_FILE_TREE::InsertByName(PCASC_CKEY_ENTRY pCKeyEntry, const
assert(szFileName != NULL && szFileName[0] != 0);
assert(pCKeyEntry != NULL);
- //char szCKey[MD5_STRING_SIZE+1];
- //char szEKey[MD5_STRING_SIZE+1];
- //StringFromBinary(pCKeyEntry->CKey, MD5_HASH_SIZE, szCKey);
- //StringFromBinary(pCKeyEntry->EKey, MD5_HASH_SIZE, szEKey);
- //printf("%s\t%s\t%s\n", szCKey, szEKey, szFileName);
-
- //BREAK_ON_XKEY3(pCKeyEntry->EKey, 0x03, 0xDC, 0x7D);
+ //BREAK_ON_XKEY3(pCKeyEntry->EKey, 0x00, 0x00, 0x0F);
// Calculate the file name hash
FileNameHash = CalcFileNameHash(szFileName);
diff --git a/dep/CascLib/src/common/ListFile.cpp b/dep/CascLib/src/common/ListFile.cpp
index bcca8b7177a..a284ef2db10 100644
--- a/dep/CascLib/src/common/ListFile.cpp
+++ b/dep/CascLib/src/common/ListFile.cpp
@@ -121,7 +121,7 @@ static int ListFile_GetFileDataId(PLISTFILE_CACHE pCache, PDWORD PtrFileDataId)
//-----------------------------------------------------------------------------
// Functions for parsing an external listfile
-void * ListFile_OpenExternal(const TCHAR * szListFile)
+void * ListFile_OpenExternal(LPCTSTR szListFile)
{
PLISTFILE_CACHE pCache = NULL;
TFileStream * pStream;
diff --git a/dep/CascLib/src/common/ListFile.h b/dep/CascLib/src/common/ListFile.h
index 1333b52c2b5..7710b269cef 100644
--- a/dep/CascLib/src/common/ListFile.h
+++ b/dep/CascLib/src/common/ListFile.h
@@ -14,7 +14,7 @@
//-----------------------------------------------------------------------------
// Functions for parsing an external listfile
-void * ListFile_OpenExternal(const TCHAR * szListFile);
+void * ListFile_OpenExternal(LPCTSTR szListFile);
void * ListFile_FromBuffer(LPBYTE pbBuffer, DWORD cbBuffer);
bool ListFile_VerifyMD5(void * pvListFile, LPBYTE pbHashMD5);
size_t ListFile_GetNextLine(void * pvListFile, const char ** pszLineBegin, const char ** pszLineEnd);
diff --git a/dep/CascLib/src/md5/md5.cpp b/dep/CascLib/src/md5/md5.cpp
index b6cc49db42b..688269953a0 100644
--- a/dep/CascLib/src/md5/md5.cpp
+++ b/dep/CascLib/src/md5/md5.cpp
@@ -36,11 +36,11 @@
*/
#ifndef HAVE_OPENSSL
-
+
#include <string.h>
-
+
#include "md5.h"
-
+
/*
* The basic MD5 functions.
*
@@ -53,7 +53,7 @@
#define H(x, y, z) (((x) ^ (y)) ^ (z))
#define H2(x, y, z) ((x) ^ ((y) ^ (z)))
#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-
+
/*
* The MD5 transformation for all four rounds.
*/
@@ -61,7 +61,7 @@
(a) += f((b), (c), (d)) + (x) + (t); \
(a) = (((a) << (s)) | (((a) & 0xffffffff) >> (32 - (s)))); \
(a) += (b);
-
+
/*
* SET reads 4 input bytes in little-endian byte order and stores them in a
* properly aligned word in host byte order.
@@ -102,20 +102,20 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
const unsigned char *ptr;
MD5_u32plus a, b, c, d;
MD5_u32plus saved_a, saved_b, saved_c, saved_d;
-
+
ptr = (const unsigned char *)data;
-
+
a = ctx->a;
b = ctx->b;
c = ctx->c;
d = ctx->d;
-
+
do {
saved_a = a;
saved_b = b;
saved_c = c;
saved_d = d;
-
+
/* Round 1 */
STEP(F, a, b, c, d, SET(0), 0xd76aa478, 7)
STEP(F, d, a, b, c, SET(1), 0xe8c7b756, 12)
@@ -133,7 +133,7 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
STEP(F, d, a, b, c, SET(13), 0xfd987193, 12)
STEP(F, c, d, a, b, SET(14), 0xa679438e, 17)
STEP(F, b, c, d, a, SET(15), 0x49b40821, 22)
-
+
/* Round 2 */
STEP(G, a, b, c, d, GET(1), 0xf61e2562, 5)
STEP(G, d, a, b, c, GET(6), 0xc040b340, 9)
@@ -151,7 +151,7 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
STEP(G, d, a, b, c, GET(2), 0xfcefa3f8, 9)
STEP(G, c, d, a, b, GET(7), 0x676f02d9, 14)
STEP(G, b, c, d, a, GET(12), 0x8d2a4c8a, 20)
-
+
/* Round 3 */
STEP(H, a, b, c, d, GET(5), 0xfffa3942, 4)
STEP(H2, d, a, b, c, GET(8), 0x8771f681, 11)
@@ -169,7 +169,7 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
STEP(H2, d, a, b, c, GET(12), 0xe6db99e5, 11)
STEP(H, c, d, a, b, GET(15), 0x1fa27cf8, 16)
STEP(H2, b, c, d, a, GET(2), 0xc4ac5665, 23)
-
+
/* Round 4 */
STEP(I, a, b, c, d, GET(0), 0xf4292244, 6)
STEP(I, d, a, b, c, GET(7), 0x432aff97, 10)
@@ -187,20 +187,20 @@ static const void *body(MD5_CTX *ctx, const void *data, unsigned long size)
STEP(I, d, a, b, c, GET(11), 0xbd3af235, 10)
STEP(I, c, d, a, b, GET(2), 0x2ad7d2bb, 15)
STEP(I, b, c, d, a, GET(9), 0xeb86d391, 21)
-
+
a += saved_a;
b += saved_b;
c += saved_c;
d += saved_d;
-
+
ptr += 64;
} while (size -= 64);
-
+
ctx->a = a;
ctx->b = b;
ctx->c = c;
ctx->d = d;
-
+
return ptr;
}
@@ -210,81 +210,81 @@ void MD5_Init(MD5_CTX *ctx)
ctx->b = 0xefcdab89;
ctx->c = 0x98badcfe;
ctx->d = 0x10325476;
-
+
ctx->lo = 0;
ctx->hi = 0;
}
-
+
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
{
MD5_u32plus saved_lo;
unsigned long used, available;
-
+
saved_lo = ctx->lo;
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
ctx->hi++;
ctx->hi += size >> 29;
-
+
used = saved_lo & 0x3f;
-
+
if (used) {
available = 64 - used;
-
+
if (size < available) {
memcpy(&ctx->buffer[used], data, size);
return;
}
-
+
memcpy(&ctx->buffer[used], data, available);
data = (const unsigned char *)data + available;
size -= available;
body(ctx, ctx->buffer, 64);
}
-
+
if (size >= 64) {
data = body(ctx, data, size & ~(unsigned long)0x3f);
size &= 0x3f;
}
-
+
memcpy(ctx->buffer, data, size);
}
-
-#define OUT(dst, src) \
+
+#define PUT_VALUE32(dst, src) \
(dst)[0] = (unsigned char)(src); \
(dst)[1] = (unsigned char)((src) >> 8); \
(dst)[2] = (unsigned char)((src) >> 16); \
(dst)[3] = (unsigned char)((src) >> 24);
-
+
void MD5_Final(unsigned char *result, MD5_CTX *ctx)
{
unsigned long used, available;
-
+
used = ctx->lo & 0x3f;
-
+
ctx->buffer[used++] = 0x80;
-
+
available = 64 - used;
-
+
if (available < 8) {
memset(&ctx->buffer[used], 0, available);
body(ctx, ctx->buffer, 64);
used = 0;
available = 64;
}
-
+
memset(&ctx->buffer[used], 0, available - 8);
-
+
ctx->lo <<= 3;
- OUT(&ctx->buffer[56], ctx->lo)
- OUT(&ctx->buffer[60], ctx->hi)
-
+ PUT_VALUE32(&ctx->buffer[56], ctx->lo)
+ PUT_VALUE32(&ctx->buffer[60], ctx->hi)
+
body(ctx, ctx->buffer, 64);
-
- OUT(&result[0], ctx->a)
- OUT(&result[4], ctx->b)
- OUT(&result[8], ctx->c)
- OUT(&result[12], ctx->d)
-
+
+ PUT_VALUE32(&result[0], ctx->a)
+ PUT_VALUE32(&result[4], ctx->b)
+ PUT_VALUE32(&result[8], ctx->c)
+ PUT_VALUE32(&result[12], ctx->d)
+
memset(ctx, 0, sizeof(*ctx));
}