| 1 | /*****************************************************************************/
|
|---|
| 2 | /* StormLib.h Copyright (c) Ladislav Zezula 1999-2005 */
|
|---|
| 3 | /*---------------------------------------------------------------------------*/
|
|---|
| 4 | /* StormLib library v 5.00 */
|
|---|
| 5 | /* */
|
|---|
| 6 | /* Author : Ladislav Zezula */
|
|---|
| 7 | /* E-mail : ladik@zezula.net */
|
|---|
| 8 | /* WWW : http://www.zezula.net */
|
|---|
| 9 | /*---------------------------------------------------------------------------*/
|
|---|
| 10 | /* Date Ver Who Comment */
|
|---|
| 11 | /* -------- ---- --- ------- */
|
|---|
| 12 | /* xx.xx.99 1.00 Lad Created */
|
|---|
| 13 | /* 24.03.03 2.50 Lad Version 2.50 */
|
|---|
| 14 | /* 02.04.03 3.00 Lad Version 3.00 with compression */
|
|---|
| 15 | /* 11.04.03 3.01 Lad Renamed to StormLib.h for compatibility with */
|
|---|
| 16 | /* original headers for Storm.dll */
|
|---|
| 17 | /* 10.05.03 3.02 Lad Added Pkware DCL compression */
|
|---|
| 18 | /* 26.05.03 4.00 Lad Completed all compressions */
|
|---|
| 19 | /* 18.06.03 4.01 Lad Added SFileSetFileLocale */
|
|---|
| 20 | /* Added SFileExtractFile */
|
|---|
| 21 | /* 26.07.03 4.02 Lad Implemented nameless rename and delete */
|
|---|
| 22 | /* 26.07.03 4.03 Lad Added support for protected MPQs */
|
|---|
| 23 | /* 28.08.03 4.10 Lad Fixed bugs that caused StormLib incorrectly work */
|
|---|
| 24 | /* with Diablo I savegames and with files having full */
|
|---|
| 25 | /* hash table */
|
|---|
| 26 | /* 08.12.03 4.11 DCH Fixed bug in reading file block larger than 0x1000 */
|
|---|
| 27 | /* on certain files. */
|
|---|
| 28 | /* Fixed bug in AddFile with MPQ_FILE_REPLACE_EXISTING */
|
|---|
| 29 | /* (Thanx Daniel Chiamarello, dchiamarello@madvawes.com)*/
|
|---|
| 30 | /* 21.12.03 4.50 Lad Completed port for Mac */
|
|---|
| 31 | /* Fixed bug in compacting (if fsize is mul of 0x1000) */
|
|---|
| 32 | /* Fixed bug in SCompCompress */
|
|---|
| 33 | /* 27.05.04 4.51 Lad Changed memory management from new/delete to our */
|
|---|
| 34 | /* own macros */
|
|---|
| 35 | /* 22.06.04 4.60 Lad Optimized search. Support for multiple listfiles. */
|
|---|
| 36 | /* 30.09.04 4.61 Lad Fixed some bugs (Aaargh !!!) */
|
|---|
| 37 | /* Correctly works if HashTableSize > BlockTableSize */
|
|---|
| 38 | /* 29.12.04 4.70 Lad Fixed compatibility problem with MPQs from WoW */
|
|---|
| 39 | /* 14.07.05 5.00 Lad Added the BZLIB compression support */
|
|---|
| 40 | /* Added suport of files stored as single unit */
|
|---|
| 41 | /* 17.04.06 5.01 Lad Converted to MS Visual Studio 8.0 */
|
|---|
| 42 | /* Fixed issue with protected Warcraft 3 protected maps */
|
|---|
| 43 | /* 15.05.06 5.02 Lad Fixed issue with WoW 1.10+ */
|
|---|
| 44 | /* 07.09.06 5.10 Lad Fixed processing files longer than 2GB */
|
|---|
| 45 | /* 22.11.06 6.00 Lad Support for MPQ archives V2 */
|
|---|
| 46 | /* 12.06.07 6.10 Lad Support for extended file attributes */
|
|---|
| 47 | /* 10.09.07 6.12 Lad Support for MPQs protected by corrupting hash table */
|
|---|
| 48 | /* 03.12.07 6.13 Lad Support for MPQs with hash tbl size > block tbl size */
|
|---|
| 49 | /* 07.04.08 6.20 Lad Added SFileFlushArchive */
|
|---|
| 50 | /* 09.04.08 Lad Removed FilePointer variable from TMPQArchive, as */
|
|---|
| 51 | /* it caused more problems than benefits */
|
|---|
| 52 | /* 12.05.08 6.22 Lad Support for w3xMaster map protector */
|
|---|
| 53 | /* 05.10.08 6.23 Lad Support for protectors who set negative values in */
|
|---|
| 54 | /* the table of file blocks */
|
|---|
| 55 | /* 26.05.09 6.24 Lad Fixed search for multiple lang files with deleted */
|
|---|
| 56 | /* entries */
|
|---|
| 57 | /* 03.09.09 6.25 Lad Fixed decompression bug in huffmann decompression */
|
|---|
| 58 | /*****************************************************************************/
|
|---|
| 59 |
|
|---|
| 60 | #ifndef __STORMLIB_H_
|
|---|
| 61 | #define __STORMLIB_H_
|
|---|
| 62 |
|
|---|
| 63 | #include "StormPort.h"
|
|---|
| 64 |
|
|---|
| 65 | //-----------------------------------------------------------------------------
|
|---|
| 66 | // Use the apropriate library
|
|---|
| 67 | //
|
|---|
| 68 | // The library type is encoded in the library name as the following
|
|---|
| 69 | // StormLibXYZ.lib
|
|---|
| 70 | //
|
|---|
| 71 | // X - D for Debug version, R for Release version
|
|---|
| 72 | // Y - A for ANSI version, U for Unicode version (Unicode version does not exist yet)
|
|---|
| 73 | // Z - S for static C library, D for multithreaded DLL C-library
|
|---|
| 74 | //
|
|---|
| 75 |
|
|---|
| 76 | #if defined(_MSC_VER) && !defined (__STORMLIB_SELF__)
|
|---|
| 77 | #ifdef _DEBUG // DEBUG VERSIONS
|
|---|
| 78 | #ifdef _DLL
|
|---|
| 79 | #pragma comment(lib, "StormLibDAD.lib") // Debug Ansi Dynamic version
|
|---|
| 80 | #else
|
|---|
| 81 | #pragma comment(lib, "StormLibDAS.lib") // Debug Ansi Static version
|
|---|
| 82 | #endif
|
|---|
| 83 | #else // RELEASE VERSIONS
|
|---|
| 84 | #ifdef _DLL
|
|---|
| 85 | #pragma comment(lib, "StormLibRAD.lib") // Release Ansi Dynamic version
|
|---|
| 86 | #else
|
|---|
| 87 | #pragma comment(lib, "StormLibRAS.lib") // Release Ansi Static version
|
|---|
| 88 | #endif
|
|---|
| 89 | #endif
|
|---|
| 90 | #endif
|
|---|
| 91 |
|
|---|
| 92 | //-----------------------------------------------------------------------------
|
|---|
| 93 | // Defines
|
|---|
| 94 |
|
|---|
| 95 | #define ID_MPQ 0x1A51504D // MPQ archive header ID ('MPQ\x1A')
|
|---|
| 96 | #define ID_MPQ_SHUNT 0x1B51504D // MPQ shunt entry ('MPQ\x1B')
|
|---|
| 97 |
|
|---|
| 98 | #define ERROR_AVI_FILE 10000 // No MPQ file, but AVI file.
|
|---|
| 99 |
|
|---|
| 100 | // Values for SFileCreateArchiveEx
|
|---|
| 101 | #define HASH_TABLE_SIZE_MIN 0x00004
|
|---|
| 102 | #define HASH_TABLE_SIZE_MAX 0x40000
|
|---|
| 103 |
|
|---|
| 104 | #define HASH_ENTRY_DELETED 0xFFFFFFFE // Block index for deleted hash entry
|
|---|
| 105 | #define HASH_ENTRY_FREE 0xFFFFFFFF // Block index for free hash entry
|
|---|
| 106 |
|
|---|
| 107 | // Values for SFileOpenArchive
|
|---|
| 108 | #define SFILE_OPEN_HARD_DISK_FILE 2 // Open the archive on HDD
|
|---|
| 109 | #define SFILE_OPEN_CDROM_FILE 3 // Open the archive only if it is on CDROM
|
|---|
| 110 |
|
|---|
| 111 | // Values for SFileOpenFile
|
|---|
| 112 | #define SFILE_OPEN_FROM_MPQ 0 // Open the file from the MPQ archive
|
|---|
| 113 | #define SFILE_OPEN_BY_INDEX 1 // The 'szFileName' parameter is actually the file index
|
|---|
| 114 | #define SFILE_OPEN_LOCAL_FILE (DWORD)-1 // Open the file from the MPQ archive
|
|---|
| 115 |
|
|---|
| 116 | // Flags for TMPQArchive::dwFlags
|
|---|
| 117 | #define MPQ_FLAG_CHANGED 0x00000001 // If set, the MPQ has been changed
|
|---|
| 118 | #define MPQ_FLAG_PROTECTED 0x00000002 // Set on protected MPQs (like W3M maps)
|
|---|
| 119 |
|
|---|
| 120 | // Flags for SFileAddFile
|
|---|
| 121 | // Note: MPQ_FILE_COMPRESS_PKWARE has been replaced by MPQ_FILE_IMPLODE
|
|---|
| 122 | // Note: MPQ_FILE_COMPRESS_MULTI has been replaced by MPQ_FILE_COMPRESS
|
|---|
| 123 | #define MPQ_FILE_IMPLODE 0x00000100 // Implode method (By PKWARE Data Compression Library)
|
|---|
| 124 | #define MPQ_FILE_COMPRESS 0x00000200 // Compress methods (My various methods)
|
|---|
| 125 | #define MPQ_FILE_COMPRESSED 0x0000FF00 // File is compressed
|
|---|
| 126 | #define MPQ_FILE_ENCRYPTED 0x00010000 // Indicates whether file is encrypted
|
|---|
| 127 | #define MPQ_FILE_FIXSEED 0x00020000 // File decrypt seed has to be fixed
|
|---|
| 128 | #define MPQ_FILE_SINGLE_UNIT 0x01000000 // File is stored as a single unit, rather than split into sectors (Thx, Quantam)
|
|---|
| 129 | #define MPQ_FILE_DUMMY_FILE 0x02000000 // The file is only 1 byte long and its name is a hash
|
|---|
| 130 | #define MPQ_FILE_HAS_EXTRA 0x04000000 // The file has extra data appended after regular data.
|
|---|
| 131 | // Must be with compressed files only
|
|---|
| 132 | #define MPQ_FILE_EXISTS 0x80000000 // Set if file exists, reset when the file was deleted
|
|---|
| 133 | #define MPQ_FILE_REPLACEEXISTING 0x80000000 // Replace when the file exist (SFileAddFile)
|
|---|
| 134 |
|
|---|
| 135 | #define MPQ_FILE_VALID_FLAGS (MPQ_FILE_IMPLODE | \
|
|---|
| 136 | MPQ_FILE_COMPRESS | \
|
|---|
| 137 | MPQ_FILE_ENCRYPTED | \
|
|---|
| 138 | MPQ_FILE_FIXSEED | \
|
|---|
| 139 | MPQ_FILE_SINGLE_UNIT | \
|
|---|
| 140 | MPQ_FILE_DUMMY_FILE | \
|
|---|
| 141 | MPQ_FILE_HAS_EXTRA | \
|
|---|
| 142 | MPQ_FILE_EXISTS)
|
|---|
| 143 |
|
|---|
| 144 | // Compression types for multilpe compressions
|
|---|
| 145 | #define MPQ_COMPRESSION_HUFFMANN 0x01 // Huffmann compression (used on WAVE files only)
|
|---|
| 146 | #define MPQ_COMPRESSION_ZLIB 0x02 // ZLIB compression
|
|---|
| 147 | #define MPQ_COMPRESSION_PKWARE 0x08 // PKWARE DCL compression
|
|---|
| 148 | #define MPQ_COMPRESSION_BZIP2 0x10 // BZIP2 compression
|
|---|
| 149 | #define MPQ_COMPRESSION_WAVE_MONO 0x40 //
|
|---|
| 150 | #define MPQ_COMPRESSION_WAVE_STEREO 0x80 //
|
|---|
| 151 |
|
|---|
| 152 |
|
|---|
| 153 | // Constants for SFileAddWave
|
|---|
| 154 | #define MPQ_WAVE_QUALITY_HIGH 0 // Best quality, the worst compression
|
|---|
| 155 | #define MPQ_WAVE_QUALITY_MEDIUM 1 // Medium quality, medium compression
|
|---|
| 156 | #define MPQ_WAVE_QUALITY_LOW 2 // Low quality, the best compression
|
|---|
| 157 |
|
|---|
| 158 | // Constants for SFileGetFileInfo
|
|---|
| 159 | #define SFILE_INFO_ARCHIVE_SIZE 1 // MPQ size (value from header)
|
|---|
| 160 | #define SFILE_INFO_HASH_TABLE_SIZE 2 // Size of hash table, in entries
|
|---|
| 161 | #define SFILE_INFO_BLOCK_TABLE_SIZE 3 // Number of entries in the block table
|
|---|
| 162 | #define SFILE_INFO_BLOCK_SIZE 4 // Size of file block (in bytes)
|
|---|
| 163 | #define SFILE_INFO_HASH_TABLE 5 // Pointer to Hash table (TMPQHash *)
|
|---|
| 164 | #define SFILE_INFO_BLOCK_TABLE 6 // Pointer to Block Table (TMPQBlock *)
|
|---|
| 165 | #define SFILE_INFO_NUM_FILES 7 // Real number of files within archive
|
|---|
| 166 | //------
|
|---|
| 167 | #define SFILE_INFO_HASH_INDEX 8 // Hash index of file in MPQ
|
|---|
| 168 | #define SFILE_INFO_CODENAME1 9 // The first codename of the file
|
|---|
| 169 | #define SFILE_INFO_CODENAME2 10 // The second codename of the file
|
|---|
| 170 | #define SFILE_INFO_LOCALEID 11 // Locale ID of file in MPQ
|
|---|
| 171 | #define SFILE_INFO_BLOCKINDEX 12 // Index to Block Table
|
|---|
| 172 | #define SFILE_INFO_FILE_SIZE 13 // Original file size
|
|---|
| 173 | #define SFILE_INFO_COMPRESSED_SIZE 14 // Compressed file size
|
|---|
| 174 | #define SFILE_INFO_FLAGS 15 // File flags
|
|---|
| 175 | #define SFILE_INFO_POSITION 16 // File position within archive
|
|---|
| 176 | #define SFILE_INFO_SEED 17 // File decryption seed
|
|---|
| 177 | #define SFILE_INFO_SEED_UNFIXED 18 // Decryption seed not fixed to file pos and size
|
|---|
| 178 |
|
|---|
| 179 | // Values for compact callback
|
|---|
| 180 | #define CCB_CHECKING_FILES 1 // Checking archive (dwParam1 = current, dwParam2 = total)
|
|---|
| 181 | #define CCB_CHECKING_HASH_TABLE 2 // Checking hash table (dwParam1 = current, dwParam2 = total)
|
|---|
| 182 | #define CCB_COPYING_NON_MPQ_DATA 3 // Copying non-MPQ data: No params used
|
|---|
| 183 | #define CCB_COMPACTING_FILES 4 // Compacting archive (dwParam1 = current, dwParam2 = total)
|
|---|
| 184 | #define CCB_CLOSING_ARCHIVE 5 // Closing archive: No params used
|
|---|
| 185 |
|
|---|
| 186 | #define LISTFILE_NAME "(listfile)" // Name of internal listfile
|
|---|
| 187 | #define SIGNATURE_NAME "(signature)" // Name of internal signature
|
|---|
| 188 | #define ATTRIBUTES_NAME "(attributes)" // Name of internal attributes file
|
|---|
| 189 |
|
|---|
| 190 | #define STORMLIB_VERSION (0x0619) // Current version of StormLib
|
|---|
| 191 |
|
|---|
| 192 | #define MPQ_FORMAT_VERSION_1 0 // Up to The Burning Crusade
|
|---|
| 193 | #define MPQ_FORMAT_VERSION_2 1 // The Burning Crusade and newer
|
|---|
| 194 |
|
|---|
| 195 | // Flags for SFileOpenArchiveEx
|
|---|
| 196 | #define MPQ_OPEN_NO_LISTFILE 0x00000001 // Don't add the internal listfile
|
|---|
| 197 | #define MPQ_OPEN_NO_ATTRIBUTES 0x00000002 // Don't open the attributes
|
|---|
| 198 | #define MPQ_OPEN_FORCE_MPQ_V1 0x00000004 // Always open the archive as MPQ v 1.00, ignore the "wFormatVersion" variable in the header
|
|---|
| 199 |
|
|---|
| 200 | // Flags for MPQ attributes
|
|---|
| 201 | #define MPQ_ATTRIBUTE_CRC32 0x00000001 // The "(attributes)" contain array of CRC32s
|
|---|
| 202 | #define MPQ_ATTRIBUTE_FILETIME 0x00000002 // The "(attributes)" contain array of FILETIMEs
|
|---|
| 203 | #define MPQ_ATTRIBUTE_MD5 0x00000004 // The "(attributes)" contain array of MD5s
|
|---|
| 204 |
|
|---|
| 205 | // Supports archives with size > 4 GB
|
|---|
| 206 | // Additional flags for SFileCreateArchiveEx
|
|---|
| 207 | #define MPQ_CREATE_ARCHIVE_V1 0x00000000 // Creates archive with size up to 4GB
|
|---|
| 208 | #define MPQ_CREATE_ARCHIVE_V2 0x00010000 // Creates archive larger than 4 GB
|
|---|
| 209 | #define MPQ_CREATE_ATTRIBUTES 0x00100000 // Also add the (attributes) file
|
|---|
| 210 |
|
|---|
| 211 | // Formats of (attributes) file
|
|---|
| 212 | #define MPQ_ATTRIBUTES_V1 100 // FOrmat version 1.00
|
|---|
| 213 |
|
|---|
| 214 | //-----------------------------------------------------------------------------
|
|---|
| 215 | // Structures
|
|---|
| 216 |
|
|---|
| 217 | #if (defined(WIN32) || defined(WIN64))
|
|---|
| 218 | #include <pshpack1.h>
|
|---|
| 219 | #else
|
|---|
| 220 | #pragma pack(push,1)
|
|---|
| 221 | #endif
|
|---|
| 222 |
|
|---|
| 223 | struct TMPQFile;
|
|---|
| 224 |
|
|---|
| 225 | struct TMPQShunt
|
|---|
| 226 | {
|
|---|
| 227 | // The ID_MPQ_SHUNT ('MPQ\x1B') signature
|
|---|
| 228 | DWORD dwID;
|
|---|
| 229 |
|
|---|
| 230 | DWORD dwUnknown;
|
|---|
| 231 |
|
|---|
| 232 | // Position of the MPQ header, relative to the begin of the shunt
|
|---|
| 233 | DWORD dwHeaderPos;
|
|---|
| 234 | };
|
|---|
| 235 |
|
|---|
| 236 |
|
|---|
| 237 | // MPQ file header
|
|---|
| 238 | struct TMPQHeader
|
|---|
| 239 | {
|
|---|
| 240 | // The ID_MPQ ('MPQ\x1A') signature
|
|---|
| 241 | DWORD dwID;
|
|---|
| 242 |
|
|---|
| 243 | // Size of the archive header
|
|---|
| 244 | DWORD dwHeaderSize;
|
|---|
| 245 |
|
|---|
| 246 | // Size of MPQ archive
|
|---|
| 247 | // This field is deprecated in the Burning Crusade MoPaQ format, and the size of the archive
|
|---|
| 248 | // is calculated as the size from the beginning of the archive to the end of the hash table,
|
|---|
| 249 | // block table, or extended block table (whichever is largest).
|
|---|
| 250 | DWORD dwArchiveSize;
|
|---|
| 251 |
|
|---|
| 252 | // 0 = Original format
|
|---|
| 253 | // 1 = Extended format (The Burning Crusade and newer)
|
|---|
| 254 | USHORT wFormatVersion;
|
|---|
| 255 |
|
|---|
| 256 | // Power of two exponent specifying the number of 512-byte disk sectors in each logical sector
|
|---|
| 257 | // in the archive. The size of each logical sector in the archive is 512 * 2^SectorSizeShift.
|
|---|
| 258 | // Bugs in the Storm library dictate that this should always be 3 (4096 byte sectors).
|
|---|
| 259 | USHORT wBlockSize;
|
|---|
| 260 |
|
|---|
| 261 | // Offset to the beginning of the hash table, relative to the beginning of the archive.
|
|---|
| 262 | DWORD dwHashTablePos;
|
|---|
| 263 |
|
|---|
| 264 | // Offset to the beginning of the block table, relative to the beginning of the archive.
|
|---|
| 265 | DWORD dwBlockTablePos;
|
|---|
| 266 |
|
|---|
| 267 | // Number of entries in the hash table. Must be a power of two, and must be less than 2^16 for
|
|---|
| 268 | // the original MoPaQ format, or less than 2^20 for the Burning Crusade format.
|
|---|
| 269 | DWORD dwHashTableSize;
|
|---|
| 270 |
|
|---|
| 271 | // Number of entries in the block table
|
|---|
| 272 | DWORD dwBlockTableSize;
|
|---|
| 273 | };
|
|---|
| 274 |
|
|---|
| 275 |
|
|---|
| 276 | // Extended MPQ file header. Valid only if wFormatVersion is 1 or higher
|
|---|
| 277 | struct TMPQHeader2 : public TMPQHeader
|
|---|
| 278 | {
|
|---|
| 279 | // Offset to the beginning of the extended block table, relative to the beginning of the archive.
|
|---|
| 280 | LARGE_INTEGER ExtBlockTablePos;
|
|---|
| 281 |
|
|---|
| 282 | // High 16 bits of the hash table offset for large archives.
|
|---|
| 283 | USHORT wHashTablePosHigh;
|
|---|
| 284 |
|
|---|
| 285 | // High 16 bits of the block table offset for large archives.
|
|---|
| 286 | USHORT wBlockTablePosHigh;
|
|---|
| 287 | };
|
|---|
| 288 |
|
|---|
| 289 |
|
|---|
| 290 | // Hash entry. All files in the archive are searched by their hashes.
|
|---|
| 291 | struct TMPQHash
|
|---|
| 292 | {
|
|---|
| 293 | // The hash of the file path, using method A.
|
|---|
| 294 | DWORD dwName1;
|
|---|
| 295 |
|
|---|
| 296 | // The hash of the file path, using method B.
|
|---|
| 297 | DWORD dwName2;
|
|---|
| 298 |
|
|---|
| 299 | #if PLATFORM_LITTLE_ENDIAN
|
|---|
| 300 |
|
|---|
| 301 | // The language of the file. This is a Windows LANGID data type, and uses the same values.
|
|---|
| 302 | // 0 indicates the default language (American English), or that the file is language-neutral.
|
|---|
| 303 | USHORT lcLocale;
|
|---|
| 304 |
|
|---|
| 305 | // The platform the file is used for. 0 indicates the default platform.
|
|---|
| 306 | // No other values have been observed.
|
|---|
| 307 | USHORT wPlatform;
|
|---|
| 308 |
|
|---|
| 309 | #else
|
|---|
| 310 |
|
|---|
| 311 | USHORT wPlatform;
|
|---|
| 312 | USHORT lcLocale;
|
|---|
| 313 |
|
|---|
| 314 | #endif
|
|---|
| 315 |
|
|---|
| 316 | // If the hash table entry is valid, this is the index into the block table of the file.
|
|---|
| 317 | // Otherwise, one of the following two values:
|
|---|
| 318 | // - FFFFFFFFh: Hash table entry is empty, and has always been empty.
|
|---|
| 319 | // Terminates searches for a given file.
|
|---|
| 320 | // - FFFFFFFEh: Hash table entry is empty, but was valid at some point (a deleted file).
|
|---|
| 321 | // Does not terminate searches for a given file.
|
|---|
| 322 | DWORD dwBlockIndex;
|
|---|
| 323 | };
|
|---|
| 324 |
|
|---|
| 325 |
|
|---|
| 326 | // File description block contains informations about the file
|
|---|
| 327 | struct TMPQBlock
|
|---|
| 328 | {
|
|---|
| 329 | // Offset of the beginning of the block, relative to the beginning of the archive.
|
|---|
| 330 | DWORD dwFilePos;
|
|---|
| 331 |
|
|---|
| 332 | // Compressed file size
|
|---|
| 333 | DWORD dwCSize;
|
|---|
| 334 |
|
|---|
| 335 | // Only valid if the block is a file; otherwise meaningless, and should be 0.
|
|---|
| 336 | // If the file is compressed, this is the size of the uncompressed file data.
|
|---|
| 337 | DWORD dwFSize;
|
|---|
| 338 |
|
|---|
| 339 | // Flags for the file. See MPQ_FILE_XXXX constants
|
|---|
| 340 | DWORD dwFlags;
|
|---|
| 341 | };
|
|---|
| 342 |
|
|---|
| 343 |
|
|---|
| 344 | // The extended block table was added to support archives larger than 4 gigabytes (2^32 bytes).
|
|---|
| 345 | // The table contains the upper bits of the archive offsets for each block in the block table.
|
|---|
| 346 | // It is simply an array of int16s, which become bits 32-47 of the archive offsets for each block,
|
|---|
| 347 | // with bits 48-63 being zero. Individual blocks in the archive are still limited to 4 gigabytes
|
|---|
| 348 | // in size. This table is only present in Burning Crusade format archives that exceed 4 gigabytes size.
|
|---|
| 349 | struct TMPQBlockEx
|
|---|
| 350 | {
|
|---|
| 351 | USHORT wFilePosHigh;
|
|---|
| 352 | };
|
|---|
| 353 |
|
|---|
| 354 |
|
|---|
| 355 | struct TFileNode
|
|---|
| 356 | {
|
|---|
| 357 | DWORD dwRefCount; // Number of references
|
|---|
| 358 | // There can be more files that have the same name.
|
|---|
| 359 | // (e.g. multiple language files). We don't want to
|
|---|
| 360 | // have an entry for each of them, so the entries will be referenced.
|
|---|
| 361 | // When a number of node references reaches zero,
|
|---|
| 362 | // the node will be deleted
|
|---|
| 363 |
|
|---|
| 364 | size_t nLength; // File name length
|
|---|
| 365 | char szFileName[1]; // File name, variable length
|
|---|
| 366 | };
|
|---|
| 367 |
|
|---|
| 368 |
|
|---|
| 369 | // CRC32 present in the (attributes) file
|
|---|
| 370 | struct TMPQCRC32
|
|---|
| 371 | {
|
|---|
| 372 | DWORD dwValue; // Value of CRC32 for each block
|
|---|
| 373 | };
|
|---|
| 374 |
|
|---|
| 375 |
|
|---|
| 376 | // FILETIME present in the (attributes) file
|
|---|
| 377 | struct TMPQFileTime
|
|---|
| 378 | {
|
|---|
| 379 | DWORD dwFileTimeLow; // Low DWORD of the FILETIME
|
|---|
| 380 | DWORD dwFileTimeHigh; // High DWORD of the FILETIME
|
|---|
| 381 | };
|
|---|
| 382 |
|
|---|
| 383 |
|
|---|
| 384 | // MD5 presetn in the (attributes) file
|
|---|
| 385 | struct TMPQMD5
|
|---|
| 386 | {
|
|---|
| 387 | BYTE Value[0x10]; // 16 bytes of MD5
|
|---|
| 388 | };
|
|---|
| 389 |
|
|---|
| 390 |
|
|---|
| 391 | // Data from (attributes) file
|
|---|
| 392 | struct TMPQAttr
|
|---|
| 393 | {
|
|---|
| 394 | DWORD dwVersion; // Version of the (attributes) file. Must be 100 (0x64)
|
|---|
| 395 | DWORD dwFlags; // See MPQ_ATTRIBUTE_XXXX
|
|---|
| 396 | TMPQCRC32 * pCrc32; // Array of CRC32 (NULL if none)
|
|---|
| 397 | TMPQFileTime * pFileTime; // Array of FILETIME (NULL if not present)
|
|---|
| 398 | TMPQMD5 * pMd5; // Array of MD5 (NULL if none)
|
|---|
| 399 | };
|
|---|
| 400 |
|
|---|
| 401 |
|
|---|
| 402 | #if (defined(WIN32) || defined(WIN64))
|
|---|
| 403 | #include <poppack.h>
|
|---|
| 404 | #else
|
|---|
| 405 | #pragma pack(pop)
|
|---|
| 406 | #endif
|
|---|
| 407 |
|
|---|
| 408 | // Archive handle structure
|
|---|
| 409 | struct TMPQArchive
|
|---|
| 410 | {
|
|---|
| 411 | // TMPQArchive * pNext; // Next archive (used by Storm.dll only)
|
|---|
| 412 | // TMPQArchive * pPrev; // Previous archive (used by Storm.dll only)
|
|---|
| 413 | char szFileName[MAX_PATH]; // Opened archive file name
|
|---|
| 414 | HANDLE hFile; // File handle
|
|---|
| 415 | DWORD dwPriority; // Priority of the archive
|
|---|
| 416 | LARGE_INTEGER ShuntPos; // MPQShunt offset (only valid if a shunt is present)
|
|---|
| 417 | LARGE_INTEGER MpqPos; // File header offset (relative to the begin of the file)
|
|---|
| 418 | LARGE_INTEGER HashTablePos; // Hash table offset (relative to the begin of the file)
|
|---|
| 419 | LARGE_INTEGER BlockTablePos; // Block table offset (relative to the begin of the file)
|
|---|
| 420 | LARGE_INTEGER ExtBlockTablePos; // Ext. block table offset (relative to the begin of the file)
|
|---|
| 421 | LARGE_INTEGER MpqSize; // Size of MPQ archive
|
|---|
| 422 |
|
|---|
| 423 | TMPQFile * pLastFile; // Recently read file
|
|---|
| 424 | DWORD dwBlockPos; // Position of loaded block in the file
|
|---|
| 425 | DWORD dwBlockSize; // Size of file block
|
|---|
| 426 | BYTE * pbBlockBuffer; // Buffer (cache) for file block
|
|---|
| 427 | DWORD dwBuffPos; // Position in block buffer
|
|---|
| 428 | TMPQShunt * pShunt; // MPQ shunt (NULL if not present in the file)
|
|---|
| 429 | TMPQHeader2 * pHeader; // MPQ file header
|
|---|
| 430 | TMPQHash * pHashTable; // Hash table
|
|---|
| 431 | TMPQBlock * pBlockTable; // Block table
|
|---|
| 432 | TMPQBlockEx * pExtBlockTable; // Extended block table
|
|---|
| 433 |
|
|---|
| 434 | TMPQShunt Shunt; // MPQ shunt. Valid only when ID_MPQ_SHUNT has been found
|
|---|
| 435 | TMPQHeader2 Header; // MPQ header
|
|---|
| 436 |
|
|---|
| 437 | TMPQAttr * pAttributes; // MPQ attributes from "(attributes)" file (NULL if none)
|
|---|
| 438 | TFileNode ** pListFile; // File name array
|
|---|
| 439 | DWORD dwFlags; // See MPQ_FLAG_XXXXX
|
|---|
| 440 | };
|
|---|
| 441 |
|
|---|
| 442 |
|
|---|
| 443 | // File handle structure
|
|---|
| 444 | struct TMPQFile
|
|---|
| 445 | {
|
|---|
| 446 | HANDLE hFile; // File handle
|
|---|
| 447 | TMPQArchive * ha; // Archive handle
|
|---|
| 448 | TMPQHash * pHash; // Hash table entry
|
|---|
| 449 | TMPQBlockEx * pBlockEx; // Pointer to extended file block entry
|
|---|
| 450 | TMPQBlock * pBlock; // File block pointer
|
|---|
| 451 | DWORD dwSeed1; // Seed used for file decrypt
|
|---|
| 452 | DWORD dwFilePos; // Current file position
|
|---|
| 453 | LARGE_INTEGER RawFilePos; // Offset in MPQ archive (relative to file begin)
|
|---|
| 454 | LARGE_INTEGER MpqFilePos; // Offset in MPQ archive (relative to MPQ header)
|
|---|
| 455 |
|
|---|
| 456 | DWORD * pdwBlockPos; // Position of each file block (only for compressed files)
|
|---|
| 457 | DWORD nBlocks; // Number of blocks in the file (incl. the last incomplete one)
|
|---|
| 458 | BOOL bBlockPosLoaded; // TRUE if block positions loaded
|
|---|
| 459 | BYTE * pbFileBuffer; // Decompressed file (for single unit files, size is the uncompressed file size)
|
|---|
| 460 |
|
|---|
| 461 | TMPQCRC32 * pCrc32; // Pointer to CRC32 (NULL if none)
|
|---|
| 462 | TMPQFileTime * pFileTime; // Pointer to file's FILETIME (NULL if none)
|
|---|
| 463 | TMPQMD5 * pMd5; // Pointer to file's MD5 (NULL if none)
|
|---|
| 464 |
|
|---|
| 465 | DWORD dwHashIndex; // Index to Hash table
|
|---|
| 466 | DWORD dwBlockIndex; // Index to Block table
|
|---|
| 467 | char szFileName[1]; // File name (variable length)
|
|---|
| 468 | };
|
|---|
| 469 |
|
|---|
| 470 | // Used by searching in MPQ archives
|
|---|
| 471 | struct TMPQSearch
|
|---|
| 472 | {
|
|---|
| 473 | TMPQArchive * ha; // Handle to MPQ, where the search runs
|
|---|
| 474 | DWORD dwNextIndex; // Next hash index to be checked
|
|---|
| 475 | DWORD dwName1; // Lastly found Name1
|
|---|
| 476 | DWORD dwName2; // Lastly found Name2
|
|---|
| 477 | char szSearchMask[1]; // Search mask (variable length)
|
|---|
| 478 | };
|
|---|
| 479 |
|
|---|
| 480 |
|
|---|
| 481 | struct SFILE_FIND_DATA
|
|---|
| 482 | {
|
|---|
| 483 | char cFileName[MAX_PATH]; // Full name of the found file
|
|---|
| 484 | char * szPlainName; // Pointer to file part
|
|---|
| 485 | LCID lcLocale; // Locale version
|
|---|
| 486 | DWORD dwFileSize; // File size in bytes
|
|---|
| 487 | DWORD dwFileFlags; // File flags (compressed or encrypted)
|
|---|
| 488 | DWORD dwBlockIndex; // Block index for the file
|
|---|
| 489 | DWORD dwCompSize; // Compressed file size
|
|---|
| 490 | };
|
|---|
| 491 |
|
|---|
| 492 | //-----------------------------------------------------------------------------
|
|---|
| 493 | // Memory management
|
|---|
| 494 | //
|
|---|
| 495 | // We use our own macros for allocating/freeing memory. If you want
|
|---|
| 496 | // to redefine them, please keep the following rules
|
|---|
| 497 | //
|
|---|
| 498 | // - The memory allocation must return NULL if not enough memory
|
|---|
| 499 | // (i.e not to throw exception)
|
|---|
| 500 | // - It is not necessary to fill the allocated block with zeros
|
|---|
| 501 | // - Memory freeing function must not test the pointer to NULL.
|
|---|
| 502 | //
|
|---|
| 503 |
|
|---|
| 504 |
|
|---|
| 505 | __inline void * DebugMalloc(char * szFile, int nLine, int nSize)
|
|---|
| 506 | {
|
|---|
| 507 | void * ptr = malloc(nSize + 100);
|
|---|
| 508 | char * plain;
|
|---|
| 509 |
|
|---|
| 510 | plain = strrchr(szFile, '\\');
|
|---|
| 511 | if(plain == NULL)
|
|---|
| 512 | plain = strrchr(szFile, '/');
|
|---|
| 513 | if(plain == NULL)
|
|---|
| 514 | plain = szFile;
|
|---|
| 515 |
|
|---|
| 516 | #if _MSC_VER > 1300
|
|---|
| 517 | sprintf_s((char *)ptr, nSize+100, "%s(%u)", plain, nLine);
|
|---|
| 518 | #else
|
|---|
| 519 | sprintf((char *)ptr, "%s(%u)", plain, nLine);
|
|---|
| 520 | #endif
|
|---|
| 521 |
|
|---|
| 522 | return (char *)ptr + 100;
|
|---|
| 523 | }
|
|---|
| 524 |
|
|---|
| 525 |
|
|---|
| 526 | __inline void DebugFree(void * ptr)
|
|---|
| 527 | {
|
|---|
| 528 | free((char *)ptr - 100);
|
|---|
| 529 | }
|
|---|
| 530 |
|
|---|
| 531 |
|
|---|
| 532 | #ifndef ALLOCMEM
|
|---|
| 533 | #define ALLOCMEM(type, nitems) (type *)malloc((nitems) * sizeof(type))
|
|---|
| 534 | #define FREEMEM(ptr) free(ptr)
|
|---|
| 535 | #endif
|
|---|
| 536 |
|
|---|
| 537 | //#define ALLOCMEM(type, nitems) (type *)DebugMalloc(__FILE__, __LINE__, (nitems) * sizeof(type))
|
|---|
| 538 | //#define FREEMEM(ptr) DebugFree(ptr)
|
|---|
| 539 |
|
|---|
| 540 | //-----------------------------------------------------------------------------
|
|---|
| 541 | // Functions in StormLib - compatible with Storm.dll
|
|---|
| 542 |
|
|---|
| 543 | // Typedefs for functions exported by Storm.dll
|
|---|
| 544 | typedef LCID (WINAPI * SFILESETLOCALE)(LCID);
|
|---|
| 545 | typedef BOOL (WINAPI * SFILEOPENARCHIVE)(const char *, DWORD, DWORD, HANDLE *);
|
|---|
| 546 | typedef BOOL (WINAPI * SFILECLOSEARCHIVE)(HANDLE);
|
|---|
| 547 | typedef BOOL (WINAPI * SFILEOPENFILEEX)(HANDLE, const char *, DWORD, HANDLE *);
|
|---|
| 548 | typedef BOOL (WINAPI * SFILECLOSEFILE)(HANDLE);
|
|---|
| 549 | typedef DWORD (WINAPI * SFILEGETFILESIZE)(HANDLE, DWORD *);
|
|---|
| 550 | typedef DWORD (WINAPI * SFILESETFILEPOINTER)(HANDLE, LONG, LONG *, DWORD);
|
|---|
| 551 | typedef BOOL (WINAPI * SFILEREADFILE)(HANDLE, VOID *, DWORD, DWORD *, LPOVERLAPPED);
|
|---|
| 552 |
|
|---|
| 553 | // Archive opening/closing
|
|---|
| 554 | LCID WINAPI SFileSetLocale(LCID lcNewLocale);
|
|---|
| 555 | LCID WINAPI SFileGetLocale();
|
|---|
| 556 | BOOL WINAPI SFileOpenArchive(const char * szMpqName, DWORD dwPriority, DWORD dwFlags, HANDLE * phMpq);
|
|---|
| 557 | BOOL WINAPI SFileFlushArchive(HANDLE hMpq);
|
|---|
| 558 | BOOL WINAPI SFileCloseArchive(HANDLE hMpq);
|
|---|
| 559 |
|
|---|
| 560 | // File opening/closing
|
|---|
| 561 | BOOL WINAPI SFileOpenFileEx(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope, HANDLE * phFile);
|
|---|
| 562 | BOOL WINAPI SFileCloseFile(HANDLE hFile);
|
|---|
| 563 |
|
|---|
| 564 | // File I/O
|
|---|
| 565 | DWORD WINAPI SFileGetFilePos(HANDLE hFile, DWORD * pdwFilePosHigh = NULL);
|
|---|
| 566 | DWORD WINAPI SFileGetFileSize(HANDLE hFile, DWORD * pdwFileSizeHigh = NULL);
|
|---|
| 567 | DWORD WINAPI SFileSetFilePointer(HANDLE hFile, LONG lFilePos, LONG * pdwFilePosHigh, DWORD dwMethod);
|
|---|
| 568 | BOOL WINAPI SFileReadFile(HANDLE hFile, VOID * lpBuffer, DWORD dwToRead, DWORD * pdwRead = NULL, LPOVERLAPPED lpOverlapped = NULL);
|
|---|
| 569 |
|
|---|
| 570 | // Adds another listfile into MPQ. The currently added listfile(s) remain,
|
|---|
| 571 | // so you can use this API to combining more listfiles.
|
|---|
| 572 | // Note that this function is internally called by SFileFindFirstFile
|
|---|
| 573 | int WINAPI SFileAddListFile(HANDLE hMpq, const char * szListFile);
|
|---|
| 574 |
|
|---|
| 575 | //-----------------------------------------------------------------------------
|
|---|
| 576 | // Functions in StormLib - not implemented in Storm.dll
|
|---|
| 577 |
|
|---|
| 578 | // Archive creating and editing
|
|---|
| 579 | BOOL WINAPI SFileCreateArchiveEx(const char * szMpqName, DWORD dwCreationDisposition, DWORD dwHashTableSize, HANDLE * phMpq);
|
|---|
| 580 | BOOL WINAPI SFileAddFile(HANDLE hMpq, const char * szFileName, const char * szArchivedName, DWORD dwFlags);
|
|---|
| 581 | BOOL WINAPI SFileAddWave(HANDLE hMpq, const char * szFileName, const char * szArchivedName, DWORD dwFlags, DWORD dwQuality);
|
|---|
| 582 | BOOL WINAPI SFileRemoveFile(HANDLE hMpq, const char * szFileName, DWORD dwSearchScope = SFILE_OPEN_BY_INDEX);
|
|---|
| 583 | BOOL WINAPI SFileRenameFile(HANDLE hMpq, const char * szOldFileName, const char * szNewFileName);
|
|---|
| 584 | BOOL WINAPI SFileSetFileLocale(HANDLE hFile, LCID lcNewLocale);
|
|---|
| 585 |
|
|---|
| 586 | // Retrieving info about the file
|
|---|
| 587 | BOOL WINAPI SFileHasFile(HANDLE hMpq, char * szFileName);
|
|---|
| 588 | BOOL WINAPI SFileGetFileName(HANDLE hFile, char * szFileName);
|
|---|
| 589 | DWORD_PTR WINAPI SFileGetFileInfo(HANDLE hMpqOrFile, DWORD dwInfoType);
|
|---|
| 590 |
|
|---|
| 591 | // File search
|
|---|
| 592 | // Note that the SFileFindFirstFileEx has been removed. Use SListFileFindFirst/Next
|
|---|
| 593 | HANDLE WINAPI SFileFindFirstFile(HANDLE hMpq, const char * szMask, SFILE_FIND_DATA * lpFindFileData, const char * szListFile);
|
|---|
| 594 | BOOL WINAPI SFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData);
|
|---|
| 595 | BOOL WINAPI SFileFindClose(HANDLE hFind);
|
|---|
| 596 |
|
|---|
| 597 | // Listfile search
|
|---|
| 598 | HANDLE SListFileFindFirstFile(HANDLE hMpq, const char * szListFile, const char * szMask, SFILE_FIND_DATA * lpFindFileData);
|
|---|
| 599 | BOOL SListFileFindNextFile(HANDLE hFind, SFILE_FIND_DATA * lpFindFileData);
|
|---|
| 600 | BOOL SListFileFindClose(HANDLE hFind);
|
|---|
| 601 |
|
|---|
| 602 | // Archive compacting
|
|---|
| 603 | typedef void (WINAPI * COMPACTCB)(void * lpUserData, DWORD dwWorkType, DWORD dwParam1, DWORD dwParam2);
|
|---|
| 604 | BOOL WINAPI SFileSetCompactCallback(HANDLE hMpq, COMPACTCB CompactCB, void * lpData);
|
|---|
| 605 | BOOL WINAPI SFileCompactArchive(HANDLE hMpq, const char * szListFile = NULL, BOOL bReserved = 0);
|
|---|
| 606 |
|
|---|
| 607 | // Locale support
|
|---|
| 608 | int WINAPI SFileEnumLocales(HANDLE hMpq, const char * szFileName, LCID * plcLocales, DWORD * pdwMaxLocales, DWORD dwSearchScope);
|
|---|
| 609 |
|
|---|
| 610 | // (De)compression
|
|---|
| 611 | int WINAPI SCompCompress (char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength, int uCompressions, int nCmpType, int nCmpLevel);
|
|---|
| 612 | int WINAPI SCompDecompress (char * pbOutBuffer, int * pdwOutLength, char * pbInBuffer, int dwInLength);
|
|---|
| 613 |
|
|---|
| 614 | // Sets the default data compression for files added to MPQ,
|
|---|
| 615 | // if MPQ_FILE_COMPRESS_MULTI has been specified in call to SFileAddFile
|
|---|
| 616 | // Use one of the MPQ_COMPRESSION_XXX values
|
|---|
| 617 | int WINAPI SCompSetDataCompression(int nDataCompression);
|
|---|
| 618 |
|
|---|
| 619 | // Verifies file against its extended attributes (depending on dwFlags).
|
|---|
| 620 | // For dwFlags, use one or more of MPQ_ATTRIBUTE_MD5
|
|---|
| 621 | BOOL WINAPI SFileVerifyFile(HANDLE hMpq, const char * szFileName, DWORD dwFlags);
|
|---|
| 622 |
|
|---|
| 623 | // High-level extract function
|
|---|
| 624 | BOOL WINAPI SFileExtractFile(HANDLE hMpq, const char * szToExtract, const char * szExtracted);
|
|---|
| 625 |
|
|---|
| 626 | //-----------------------------------------------------------------------------
|
|---|
| 627 | // Functions from Storm.dll. They use slightly different names for keeping
|
|---|
| 628 | // possibility to use them together with StormLib (StormXXX instead of SFileXXX)
|
|---|
| 629 |
|
|---|
| 630 | #ifdef __LINK_STORM_DLL__
|
|---|
| 631 | #define STORM_ALTERNATE_NAMES // Force Storm.h to use alternate fnc names
|
|---|
| 632 | #include "StormDll.h"
|
|---|
| 633 | #endif // __LINK_STORM_DLL__
|
|---|
| 634 |
|
|---|
| 635 | //-----------------------------------------------------------------------------
|
|---|
| 636 | // GFX decode functions. See GfxDecode.cpp for details and description
|
|---|
| 637 |
|
|---|
| 638 | USHORT WINAPI celGetFrameCount(BYTE * fileBuf);
|
|---|
| 639 | BYTE * WINAPI celGetFrameData(BYTE *fileBuf, BYTE *palette, USHORT xsize, USHORT frame, USHORT *ysize, USHORT *maxX=NULL);
|
|---|
| 640 | USHORT WINAPI cl2GetFrameCount(BYTE *fileBuf);
|
|---|
| 641 | BYTE ** WINAPI cl2GetDirData(BYTE *fileBuf, BYTE *palette, USHORT xsize, USHORT dir, USHORT *ysize);
|
|---|
| 642 | BYTE * WINAPI pcxGetData(BYTE *filebuf, DWORD filesize, BYTE transcol, USHORT *xsize, USHORT *ysize);
|
|---|
| 643 |
|
|---|
| 644 | #endif // __STORMLIB_H_
|
|---|