stormlib 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (624) hide show
  1. checksums.yaml +4 -4
  2. data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CMakeCCompiler.cmake +72 -0
  3. data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CMakeCXXCompiler.cmake +83 -0
  4. data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CMakeDetermineCompilerABI_C.bin +0 -0
  5. data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CMakeDetermineCompilerABI_CXX.bin +0 -0
  6. data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CMakeSystem.cmake +15 -0
  7. data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CompilerIdC/CMakeCCompilerId.c +803 -0
  8. data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CompilerIdC/a.out +0 -0
  9. data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CompilerIdCXX/CMakeCXXCompilerId.cpp +791 -0
  10. data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CompilerIdCXX/a.out +0 -0
  11. data/ext/stormlib/StormLib/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
  12. data/ext/stormlib/StormLib/CMakeFiles/CMakeOutput.log +478 -0
  13. data/ext/stormlib/StormLib/CMakeFiles/Export/share/StormLib/StormLibConfig-noconfig.cmake +19 -0
  14. data/ext/stormlib/StormLib/CMakeFiles/Export/share/StormLib/StormLibConfig.cmake +99 -0
  15. data/ext/stormlib/StormLib/CMakeFiles/Makefile.cmake +61 -0
  16. data/ext/stormlib/StormLib/CMakeFiles/Makefile2 +112 -0
  17. data/ext/stormlib/StormLib/CMakeFiles/TargetDirectories.txt +9 -0
  18. data/ext/stormlib/StormLib/CMakeFiles/cmake.check_cache +1 -0
  19. data/ext/stormlib/StormLib/CMakeFiles/progress.marks +1 -0
  20. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/DependInfo.cmake +243 -0
  21. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/build.make +3695 -0
  22. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/cmake_clean.cmake +459 -0
  23. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/cmake_clean_target.cmake +3 -0
  24. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/compiler_depend.make +2 -0
  25. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/compiler_depend.ts +2 -0
  26. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/depend.make +2 -0
  27. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/flags.make +17 -0
  28. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/link.txt +2 -0
  29. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/progress.make +227 -0
  30. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/FileStream.cpp.o.d +160 -0
  31. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SBaseCommon.cpp.o.d +159 -0
  32. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SBaseDumpData.cpp.o.d +159 -0
  33. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SBaseFileTable.cpp.o.d +159 -0
  34. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SBaseSubTypes.cpp.o.d +159 -0
  35. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SCompression.cpp.o.d +159 -0
  36. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileAddFile.cpp.o.d +159 -0
  37. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileAttributes.cpp.o.d +159 -0
  38. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileCompactArchive.cpp.o.d +159 -0
  39. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileCreateArchive.cpp.o.d +159 -0
  40. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileExtractFile.cpp.o.d +159 -0
  41. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileFindFile.cpp.o.d +159 -0
  42. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileGetFileInfo.cpp.o.d +159 -0
  43. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileListFile.cpp.o.d +159 -0
  44. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileOpenArchive.cpp.o.d +159 -0
  45. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileOpenFileEx.cpp.o.d +159 -0
  46. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFilePatchArchives.cpp.o.d +159 -0
  47. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileReadFile.cpp.o.d +159 -0
  48. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileVerify.cpp.o.d +159 -0
  49. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/adpcm/adpcm.cpp.o.d +12 -0
  50. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/huffman/huff.cpp.o.d +16 -0
  51. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/jenkins/lookup3.c.o.d +88 -0
  52. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/hashes/hash_memory.c.o.d +102 -0
  53. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/hashes/md5.c.o.d +102 -0
  54. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/hashes/sha1.c.o.d +102 -0
  55. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/hashes/sha256.c.o.d +102 -0
  56. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/math/ltm_desc.c.o.d +105 -0
  57. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/math/multi.c.o.d +102 -0
  58. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/math/rand_prime.c.o.d +102 -0
  59. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/base64_decode.c.o.d +102 -0
  60. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_argchk.c.o.d +102 -0
  61. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_find_hash.c.o.d +102 -0
  62. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_find_prng.c.o.d +102 -0
  63. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_hash_descriptor.c.o.d +102 -0
  64. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_hash_is_valid.c.o.d +102 -0
  65. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_libc.c.o.d +102 -0
  66. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.c.o.d +102 -0
  67. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_prng_descriptor.c.o.d +102 -0
  68. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_prng_is_valid.c.o.d +102 -0
  69. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_register_hash.c.o.d +102 -0
  70. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_register_prng.c.o.d +102 -0
  71. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/zeromem.c.o.d +102 -0
  72. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_bit_string.c.o.d +102 -0
  73. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_boolean.c.o.d +102 -0
  74. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_choice.c.o.d +102 -0
  75. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.c.o.d +102 -0
  76. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_integer.c.o.d +102 -0
  77. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.c.o.d +102 -0
  78. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_octet_string.c.o.d +102 -0
  79. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_printable_string.c.o.d +102 -0
  80. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_sequence_ex.c.o.d +102 -0
  81. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.c.o.d +102 -0
  82. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_sequence_multi.c.o.d +102 -0
  83. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_short_integer.c.o.d +102 -0
  84. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_utctime.c.o.d +102 -0
  85. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_utf8_string.c.o.d +102 -0
  86. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_bit_string.c.o.d +102 -0
  87. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_boolean.c.o.d +102 -0
  88. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_ia5_string.c.o.d +102 -0
  89. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_integer.c.o.d +102 -0
  90. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_object_identifier.c.o.d +102 -0
  91. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_octet_string.c.o.d +102 -0
  92. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_printable_string.c.o.d +102 -0
  93. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_sequence_ex.c.o.d +102 -0
  94. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_sequence_multi.c.o.d +102 -0
  95. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_set.c.o.d +102 -0
  96. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_setof.c.o.d +102 -0
  97. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_short_integer.c.o.d +102 -0
  98. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_utctime.c.o.d +102 -0
  99. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_utf8_string.c.o.d +102 -0
  100. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_bit_string.c.o.d +102 -0
  101. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_boolean.c.o.d +102 -0
  102. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_ia5_string.c.o.d +102 -0
  103. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_integer.c.o.d +102 -0
  104. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_object_identifier.c.o.d +102 -0
  105. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_octet_string.c.o.d +102 -0
  106. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_printable_string.c.o.d +102 -0
  107. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_sequence.c.o.d +102 -0
  108. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_short_integer.c.o.d +102 -0
  109. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_utctime.c.o.d +102 -0
  110. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_utf8_string.c.o.d +102 -0
  111. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_sequence_free.c.o.d +102 -0
  112. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/ecc/ltc_ecc_map.c.o.d +102 -0
  113. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c.o.d +102 -0
  114. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c.o.d +102 -0
  115. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/ecc/ltc_ecc_points.c.o.d +102 -0
  116. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c.o.d +102 -0
  117. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c.o.d +102 -0
  118. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c.o.d +102 -0
  119. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c.o.d +102 -0
  120. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c.o.d +102 -0
  121. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c.o.d +102 -0
  122. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c.o.d +102 -0
  123. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c.o.d +102 -0
  124. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/rsa/rsa_exptmod.c.o.d +102 -0
  125. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/rsa/rsa_free.c.o.d +102 -0
  126. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/rsa/rsa_import.c.o.d +102 -0
  127. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/rsa/rsa_make_key.c.o.d +102 -0
  128. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/rsa/rsa_sign_hash.c.o.d +102 -0
  129. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/rsa/rsa_verify_hash.c.o.d +102 -0
  130. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/rsa/rsa_verify_simple.c.o.d +102 -0
  131. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_fast_mp_invmod.c.o.d +65 -0
  132. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_fast_mp_montgomery_reduce.c.o.d +65 -0
  133. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_fast_s_mp_mul_digs.c.o.d +65 -0
  134. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_fast_s_mp_mul_high_digs.c.o.d +65 -0
  135. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_fast_s_mp_sqr.c.o.d +65 -0
  136. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_2expt.c.o.d +65 -0
  137. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_abs.c.o.d +65 -0
  138. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_add.c.o.d +65 -0
  139. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_add_d.c.o.d +65 -0
  140. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_addmod.c.o.d +65 -0
  141. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_and.c.o.d +65 -0
  142. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_clamp.c.o.d +65 -0
  143. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_clear.c.o.d +65 -0
  144. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_clear_multi.c.o.d +65 -0
  145. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_cmp.c.o.d +65 -0
  146. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_cmp_d.c.o.d +65 -0
  147. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_cmp_mag.c.o.d +65 -0
  148. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_cnt_lsb.c.o.d +65 -0
  149. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_copy.c.o.d +65 -0
  150. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_count_bits.c.o.d +65 -0
  151. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_div.c.o.d +65 -0
  152. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_div_2.c.o.d +65 -0
  153. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_div_2d.c.o.d +65 -0
  154. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_div_3.c.o.d +65 -0
  155. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_div_d.c.o.d +65 -0
  156. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_dr_is_modulus.c.o.d +65 -0
  157. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_dr_reduce.c.o.d +65 -0
  158. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_dr_setup.c.o.d +65 -0
  159. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_exch.c.o.d +65 -0
  160. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_expt_d.c.o.d +65 -0
  161. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_exptmod.c.o.d +65 -0
  162. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_exptmod_fast.c.o.d +65 -0
  163. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_exteuclid.c.o.d +65 -0
  164. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_fread.c.o.d +65 -0
  165. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_fwrite.c.o.d +65 -0
  166. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_gcd.c.o.d +65 -0
  167. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_get_int.c.o.d +65 -0
  168. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_grow.c.o.d +65 -0
  169. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_init.c.o.d +65 -0
  170. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_init_copy.c.o.d +65 -0
  171. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_init_multi.c.o.d +65 -0
  172. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_init_set.c.o.d +65 -0
  173. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_init_set_int.c.o.d +65 -0
  174. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_init_size.c.o.d +65 -0
  175. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_invmod.c.o.d +65 -0
  176. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_invmod_slow.c.o.d +65 -0
  177. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_is_square.c.o.d +65 -0
  178. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_jacobi.c.o.d +65 -0
  179. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_karatsuba_mul.c.o.d +65 -0
  180. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_karatsuba_sqr.c.o.d +65 -0
  181. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_lcm.c.o.d +65 -0
  182. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_lshd.c.o.d +65 -0
  183. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mod.c.o.d +65 -0
  184. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mod_2d.c.o.d +65 -0
  185. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mod_d.c.o.d +65 -0
  186. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_montgomery_calc_normalization.c.o.d +65 -0
  187. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_montgomery_reduce.c.o.d +65 -0
  188. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_montgomery_setup.c.o.d +65 -0
  189. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mul.c.o.d +65 -0
  190. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mul_2.c.o.d +65 -0
  191. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mul_2d.c.o.d +65 -0
  192. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mul_d.c.o.d +65 -0
  193. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mulmod.c.o.d +65 -0
  194. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_n_root.c.o.d +65 -0
  195. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_neg.c.o.d +65 -0
  196. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_or.c.o.d +65 -0
  197. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_prime_fermat.c.o.d +65 -0
  198. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_prime_is_divisible.c.o.d +65 -0
  199. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_prime_is_prime.c.o.d +65 -0
  200. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_prime_miller_rabin.c.o.d +65 -0
  201. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_prime_next_prime.c.o.d +65 -0
  202. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_prime_rabin_miller_trials.c.o.d +65 -0
  203. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_prime_random_ex.c.o.d +65 -0
  204. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_radix_size.c.o.d +65 -0
  205. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_radix_smap.c.o.d +65 -0
  206. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_rand.c.o.d +65 -0
  207. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_read_radix.c.o.d +65 -0
  208. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_read_signed_bin.c.o.d +65 -0
  209. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_read_unsigned_bin.c.o.d +65 -0
  210. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce.c.o.d +65 -0
  211. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce_2k.c.o.d +65 -0
  212. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce_2k_l.c.o.d +65 -0
  213. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce_2k_setup.c.o.d +65 -0
  214. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce_2k_setup_l.c.o.d +65 -0
  215. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce_is_2k.c.o.d +65 -0
  216. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce_is_2k_l.c.o.d +65 -0
  217. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce_setup.c.o.d +65 -0
  218. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_rshd.c.o.d +65 -0
  219. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_set.c.o.d +65 -0
  220. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_set_int.c.o.d +65 -0
  221. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_shrink.c.o.d +65 -0
  222. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_signed_bin_size.c.o.d +65 -0
  223. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_sqr.c.o.d +65 -0
  224. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_sqrmod.c.o.d +65 -0
  225. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_sqrt.c.o.d +65 -0
  226. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_sub.c.o.d +65 -0
  227. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_sub_d.c.o.d +65 -0
  228. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_submod.c.o.d +65 -0
  229. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_to_signed_bin.c.o.d +65 -0
  230. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_to_signed_bin_n.c.o.d +65 -0
  231. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_to_unsigned_bin.c.o.d +65 -0
  232. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_to_unsigned_bin_n.c.o.d +65 -0
  233. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_toom_mul.c.o.d +65 -0
  234. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_toom_sqr.c.o.d +65 -0
  235. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_toradix.c.o.d +65 -0
  236. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_toradix_n.c.o.d +65 -0
  237. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_unsigned_bin_size.c.o.d +65 -0
  238. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_xor.c.o.d +65 -0
  239. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_zero.c.o.d +65 -0
  240. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_prime_tab.c.o.d +65 -0
  241. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_reverse.c.o.d +65 -0
  242. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_s_mp_add.c.o.d +65 -0
  243. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_s_mp_exptmod.c.o.d +65 -0
  244. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_s_mp_mul_digs.c.o.d +65 -0
  245. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_s_mp_mul_high_digs.c.o.d +65 -0
  246. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_s_mp_sqr.c.o.d +65 -0
  247. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_s_mp_sub.c.o.d +65 -0
  248. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bncore.c.o.d +65 -0
  249. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/lzma/C/LzFind.c.o.d +18 -0
  250. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/lzma/C/LzmaDec.c.o.d +17 -0
  251. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/lzma/C/LzmaEnc.c.o.d +18 -0
  252. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/pklib/explode.c.o.d +16 -0
  253. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/pklib/implode.c.o.d +23 -0
  254. data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/sparse/sparse.cpp.o.d +16 -0
  255. data/ext/stormlib/StormLib/CMakeLists.txt +418 -0
  256. data/ext/stormlib/StormLib/Info.plist +22 -0
  257. data/ext/stormlib/StormLib/LICENSE +21 -0
  258. data/ext/stormlib/StormLib/Premake5.lua +132 -0
  259. data/ext/stormlib/StormLib/README.md +39 -0
  260. data/ext/stormlib/StormLib/StormLib.sln +162 -0
  261. data/ext/stormlib/StormLib/StormLib.vcxproj +1024 -0
  262. data/ext/stormlib/StormLib/StormLib.vcxproj.filters +221 -0
  263. data/ext/stormlib/StormLib/StormLib.xcodeproj/project.pbxproj +2104 -0
  264. data/ext/stormlib/StormLib/StormLib_dll.vcxproj +348 -0
  265. data/ext/stormlib/StormLib/StormLib_dll.vcxproj.filters +229 -0
  266. data/ext/stormlib/StormLib/StormLib_test.vcxproj +360 -0
  267. data/ext/stormlib/StormLib/StormLib_test.vcxproj.filters +230 -0
  268. data/ext/stormlib/StormLib/StormLib_vs08.sln +139 -0
  269. data/ext/stormlib/StormLib/StormLib_vs08.vcproj +4205 -0
  270. data/ext/stormlib/StormLib/StormLib_vs08_dll.vcproj +1851 -0
  271. data/ext/stormlib/StormLib/StormLib_vs08_test.vcproj +1289 -0
  272. data/ext/stormlib/StormLib/doc/History.txt +78 -0
  273. data/ext/stormlib/StormLib/doc/The MoPaQ File Format 0.9.txt +318 -0
  274. data/ext/stormlib/StormLib/doc/The MoPaQ File Format 1.0.txt +433 -0
  275. data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-deDE.txt +1 -0
  276. data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-enGB.txt +1 -0
  277. data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-enSG.txt +1 -0
  278. data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-enUS.txt +1 -0
  279. data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-esES.txt +1 -0
  280. data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-esMX.txt +1 -0
  281. data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-frFR.txt +1 -0
  282. data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-itIT.txt +1 -0
  283. data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-koKR.txt +1 -0
  284. data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-plPL.txt +1 -0
  285. data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-ptBR.txt +1 -0
  286. data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-zhTW.txt +1 -0
  287. data/ext/stormlib/StormLib/doc/hots-authenticationcode/hots-authenticationcode-bgdl.txt +1 -0
  288. data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-deDE.txt +1 -0
  289. data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-enGB.txt +1 -0
  290. data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-enUS.txt +1 -0
  291. data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-esES.txt +1 -0
  292. data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-esMX.txt +1 -0
  293. data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-frFR.txt +1 -0
  294. data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-itIT.txt +1 -0
  295. data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-koKR.txt +1 -0
  296. data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-plPL.txt +1 -0
  297. data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-ptBR.txt +1 -0
  298. data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-ruRU.txt +1 -0
  299. data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-zhTW.txt +1 -0
  300. data/ext/stormlib/StormLib/make-msvc.bat +95 -0
  301. data/ext/stormlib/StormLib/make.bat +46 -0
  302. data/ext/stormlib/StormLib/sources +14 -0
  303. data/ext/stormlib/StormLib/src/DllMain.c +24 -0
  304. data/ext/stormlib/StormLib/src/DllMain.def +79 -0
  305. data/ext/stormlib/StormLib/src/DllMain.rc +110 -0
  306. data/ext/stormlib/StormLib/src/FileStream.cpp +2928 -0
  307. data/ext/stormlib/StormLib/src/FileStream.h +217 -0
  308. data/ext/stormlib/StormLib/src/LibTomCrypt.c +85 -0
  309. data/ext/stormlib/StormLib/src/LibTomMath.c +125 -0
  310. data/ext/stormlib/StormLib/src/LibTomMathDesc.c +4 -0
  311. data/ext/stormlib/StormLib/src/SBaseCommon.cpp +1970 -0
  312. data/ext/stormlib/StormLib/src/SBaseDumpData.cpp +183 -0
  313. data/ext/stormlib/StormLib/src/SBaseFileTable.cpp +3194 -0
  314. data/ext/stormlib/StormLib/src/SBaseSubTypes.cpp +688 -0
  315. data/ext/stormlib/StormLib/src/SCompression.cpp +1183 -0
  316. data/ext/stormlib/StormLib/src/SFileAddFile.cpp +1337 -0
  317. data/ext/stormlib/StormLib/src/SFileAttributes.cpp +573 -0
  318. data/ext/stormlib/StormLib/src/SFileCompactArchive.cpp +654 -0
  319. data/ext/stormlib/StormLib/src/SFileCreateArchive.cpp +285 -0
  320. data/ext/stormlib/StormLib/src/SFileExtractFile.cpp +64 -0
  321. data/ext/stormlib/StormLib/src/SFileFindFile.cpp +484 -0
  322. data/ext/stormlib/StormLib/src/SFileGetFileInfo.cpp +627 -0
  323. data/ext/stormlib/StormLib/src/SFileListFile.cpp +750 -0
  324. data/ext/stormlib/StormLib/src/SFileOpenArchive.cpp +723 -0
  325. data/ext/stormlib/StormLib/src/SFileOpenFileEx.cpp +423 -0
  326. data/ext/stormlib/StormLib/src/SFilePatchArchives.cpp +1175 -0
  327. data/ext/stormlib/StormLib/src/SFileReadFile.cpp +922 -0
  328. data/ext/stormlib/StormLib/src/SFileVerify.cpp +1059 -0
  329. data/ext/stormlib/StormLib/src/StormCommon.h +450 -0
  330. data/ext/stormlib/StormLib/src/StormLib.exp +74 -0
  331. data/ext/stormlib/StormLib/src/StormLib.h +1157 -0
  332. data/ext/stormlib/StormLib/src/StormPort.h +474 -0
  333. data/ext/stormlib/StormLib/src/adpcm/adpcm.cpp +539 -0
  334. data/ext/stormlib/StormLib/src/adpcm/adpcm.h +27 -0
  335. data/ext/stormlib/StormLib/src/bzip2/blocksort.c +1094 -0
  336. data/ext/stormlib/StormLib/src/bzip2/bzlib.c +1573 -0
  337. data/ext/stormlib/StormLib/src/bzip2/bzlib.h +282 -0
  338. data/ext/stormlib/StormLib/src/bzip2/bzlib_private.h +509 -0
  339. data/ext/stormlib/StormLib/src/bzip2/compress.c +672 -0
  340. data/ext/stormlib/StormLib/src/bzip2/crctable.c +104 -0
  341. data/ext/stormlib/StormLib/src/bzip2/decompress.c +626 -0
  342. data/ext/stormlib/StormLib/src/bzip2/huffman.c +205 -0
  343. data/ext/stormlib/StormLib/src/bzip2/randtable.c +84 -0
  344. data/ext/stormlib/StormLib/src/huffman/huff.cpp +915 -0
  345. data/ext/stormlib/StormLib/src/huffman/huff.h +143 -0
  346. data/ext/stormlib/StormLib/src/jenkins/lookup.h +24 -0
  347. data/ext/stormlib/StormLib/src/jenkins/lookup3.c +1003 -0
  348. data/ext/stormlib/StormLib/src/libtomcrypt/src/hashes/hash_memory.c +69 -0
  349. data/ext/stormlib/StormLib/src/libtomcrypt/src/hashes/md5.c +368 -0
  350. data/ext/stormlib/StormLib/src/libtomcrypt/src/hashes/sha1.c +288 -0
  351. data/ext/stormlib/StormLib/src/libtomcrypt/src/hashes/sha256.c +340 -0
  352. data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt.h +91 -0
  353. data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_argchk.h +38 -0
  354. data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_cfg.h +144 -0
  355. data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_cipher.h +891 -0
  356. data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_custom.h +424 -0
  357. data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_hash.h +378 -0
  358. data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_mac.h +384 -0
  359. data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_macros.h +424 -0
  360. data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_math.h +500 -0
  361. data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_misc.h +23 -0
  362. data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_pk.h +558 -0
  363. data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_pkcs.h +89 -0
  364. data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_prng.h +199 -0
  365. data/ext/stormlib/StormLib/src/libtomcrypt/src/math/ltm_desc.c +483 -0
  366. data/ext/stormlib/StormLib/src/libtomcrypt/src/math/multi.c +61 -0
  367. data/ext/stormlib/StormLib/src/libtomcrypt/src/math/rand_prime.c +87 -0
  368. data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/base64_decode.c +104 -0
  369. data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_argchk.c +30 -0
  370. data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_find_hash.c +40 -0
  371. data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_find_prng.c +41 -0
  372. data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_hash_descriptor.c +27 -0
  373. data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_hash_is_valid.c +36 -0
  374. data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_libc.c +43 -0
  375. data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.c +13 -0
  376. data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_prng_descriptor.c +26 -0
  377. data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_prng_is_valid.c +36 -0
  378. data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_register_hash.c +54 -0
  379. data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_register_prng.c +54 -0
  380. data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/zeromem.c +34 -0
  381. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_bit_string.c +102 -0
  382. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_boolean.c +47 -0
  383. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_choice.c +182 -0
  384. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.c +96 -0
  385. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_integer.c +110 -0
  386. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.c +99 -0
  387. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_octet_string.c +91 -0
  388. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_printable_string.c +96 -0
  389. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_ex.c +287 -0
  390. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.c +386 -0
  391. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_multi.c +139 -0
  392. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_short_integer.c +68 -0
  393. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_utctime.c +127 -0
  394. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_utf8_string.c +111 -0
  395. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_bit_string.c +89 -0
  396. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_boolean.c +51 -0
  397. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_ia5_string.c +85 -0
  398. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_integer.c +130 -0
  399. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_object_identifier.c +111 -0
  400. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_octet_string.c +86 -0
  401. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_printable_string.c +85 -0
  402. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_sequence_ex.c +335 -0
  403. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_sequence_multi.c +138 -0
  404. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_set.c +103 -0
  405. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_setof.c +162 -0
  406. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_short_integer.c +97 -0
  407. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_utctime.c +83 -0
  408. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_utf8_string.c +105 -0
  409. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_bit_string.c +54 -0
  410. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_boolean.c +35 -0
  411. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_ia5_string.c +194 -0
  412. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_integer.c +82 -0
  413. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_object_identifier.c +89 -0
  414. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_octet_string.c +53 -0
  415. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_printable_string.c +166 -0
  416. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_sequence.c +169 -0
  417. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_short_integer.c +70 -0
  418. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_utctime.c +46 -0
  419. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_utf8_string.c +83 -0
  420. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_sequence_free.c +65 -0
  421. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_map.c +76 -0
  422. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c +207 -0
  423. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c +222 -0
  424. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_points.c +60 -0
  425. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c +196 -0
  426. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c +147 -0
  427. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c +108 -0
  428. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c +189 -0
  429. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c +177 -0
  430. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c +175 -0
  431. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c +110 -0
  432. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c +111 -0
  433. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/rsa/rsa_exptmod.c +113 -0
  434. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/rsa/rsa_free.c +34 -0
  435. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/rsa/rsa_import.c +143 -0
  436. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/rsa/rsa_make_key.c +112 -0
  437. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/rsa/rsa_sign_hash.c +134 -0
  438. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/rsa/rsa_verify_hash.c +167 -0
  439. data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/rsa/rsa_verify_simple.c +87 -0
  440. data/ext/stormlib/StormLib/src/libtommath/bn_fast_mp_invmod.c +148 -0
  441. data/ext/stormlib/StormLib/src/libtommath/bn_fast_mp_montgomery_reduce.c +172 -0
  442. data/ext/stormlib/StormLib/src/libtommath/bn_fast_s_mp_mul_digs.c +107 -0
  443. data/ext/stormlib/StormLib/src/libtommath/bn_fast_s_mp_mul_high_digs.c +98 -0
  444. data/ext/stormlib/StormLib/src/libtommath/bn_fast_s_mp_sqr.c +114 -0
  445. data/ext/stormlib/StormLib/src/libtommath/bn_mp_2expt.c +48 -0
  446. data/ext/stormlib/StormLib/src/libtommath/bn_mp_abs.c +43 -0
  447. data/ext/stormlib/StormLib/src/libtommath/bn_mp_add.c +53 -0
  448. data/ext/stormlib/StormLib/src/libtommath/bn_mp_add_d.c +112 -0
  449. data/ext/stormlib/StormLib/src/libtommath/bn_mp_addmod.c +41 -0
  450. data/ext/stormlib/StormLib/src/libtommath/bn_mp_and.c +57 -0
  451. data/ext/stormlib/StormLib/src/libtommath/bn_mp_clamp.c +44 -0
  452. data/ext/stormlib/StormLib/src/libtommath/bn_mp_clear.c +44 -0
  453. data/ext/stormlib/StormLib/src/libtommath/bn_mp_clear_multi.c +34 -0
  454. data/ext/stormlib/StormLib/src/libtommath/bn_mp_cmp.c +43 -0
  455. data/ext/stormlib/StormLib/src/libtommath/bn_mp_cmp_d.c +44 -0
  456. data/ext/stormlib/StormLib/src/libtommath/bn_mp_cmp_mag.c +55 -0
  457. data/ext/stormlib/StormLib/src/libtommath/bn_mp_cnt_lsb.c +53 -0
  458. data/ext/stormlib/StormLib/src/libtommath/bn_mp_copy.c +68 -0
  459. data/ext/stormlib/StormLib/src/libtommath/bn_mp_count_bits.c +45 -0
  460. data/ext/stormlib/StormLib/src/libtommath/bn_mp_div.c +292 -0
  461. data/ext/stormlib/StormLib/src/libtommath/bn_mp_div_2.c +68 -0
  462. data/ext/stormlib/StormLib/src/libtommath/bn_mp_div_2d.c +97 -0
  463. data/ext/stormlib/StormLib/src/libtommath/bn_mp_div_3.c +79 -0
  464. data/ext/stormlib/StormLib/src/libtommath/bn_mp_div_d.c +115 -0
  465. data/ext/stormlib/StormLib/src/libtommath/bn_mp_dr_is_modulus.c +43 -0
  466. data/ext/stormlib/StormLib/src/libtommath/bn_mp_dr_reduce.c +94 -0
  467. data/ext/stormlib/StormLib/src/libtommath/bn_mp_dr_setup.c +32 -0
  468. data/ext/stormlib/StormLib/src/libtommath/bn_mp_exch.c +34 -0
  469. data/ext/stormlib/StormLib/src/libtommath/bn_mp_expt_d.c +57 -0
  470. data/ext/stormlib/StormLib/src/libtommath/bn_mp_exptmod.c +112 -0
  471. data/ext/stormlib/StormLib/src/libtommath/bn_mp_exptmod_fast.c +321 -0
  472. data/ext/stormlib/StormLib/src/libtommath/bn_mp_exteuclid.c +82 -0
  473. data/ext/stormlib/StormLib/src/libtommath/bn_mp_fread.c +67 -0
  474. data/ext/stormlib/StormLib/src/libtommath/bn_mp_fwrite.c +52 -0
  475. data/ext/stormlib/StormLib/src/libtommath/bn_mp_gcd.c +105 -0
  476. data/ext/stormlib/StormLib/src/libtommath/bn_mp_get_int.c +45 -0
  477. data/ext/stormlib/StormLib/src/libtommath/bn_mp_grow.c +57 -0
  478. data/ext/stormlib/StormLib/src/libtommath/bn_mp_init.c +46 -0
  479. data/ext/stormlib/StormLib/src/libtommath/bn_mp_init_copy.c +32 -0
  480. data/ext/stormlib/StormLib/src/libtommath/bn_mp_init_multi.c +59 -0
  481. data/ext/stormlib/StormLib/src/libtommath/bn_mp_init_set.c +32 -0
  482. data/ext/stormlib/StormLib/src/libtommath/bn_mp_init_set_int.c +31 -0
  483. data/ext/stormlib/StormLib/src/libtommath/bn_mp_init_size.c +48 -0
  484. data/ext/stormlib/StormLib/src/libtommath/bn_mp_invmod.c +43 -0
  485. data/ext/stormlib/StormLib/src/libtommath/bn_mp_invmod_slow.c +175 -0
  486. data/ext/stormlib/StormLib/src/libtommath/bn_mp_is_square.c +109 -0
  487. data/ext/stormlib/StormLib/src/libtommath/bn_mp_jacobi.c +105 -0
  488. data/ext/stormlib/StormLib/src/libtommath/bn_mp_karatsuba_mul.c +167 -0
  489. data/ext/stormlib/StormLib/src/libtommath/bn_mp_karatsuba_sqr.c +121 -0
  490. data/ext/stormlib/StormLib/src/libtommath/bn_mp_lcm.c +60 -0
  491. data/ext/stormlib/StormLib/src/libtommath/bn_mp_lshd.c +67 -0
  492. data/ext/stormlib/StormLib/src/libtommath/bn_mp_mod.c +48 -0
  493. data/ext/stormlib/StormLib/src/libtommath/bn_mp_mod_2d.c +55 -0
  494. data/ext/stormlib/StormLib/src/libtommath/bn_mp_mod_d.c +27 -0
  495. data/ext/stormlib/StormLib/src/libtommath/bn_mp_montgomery_calc_normalization.c +59 -0
  496. data/ext/stormlib/StormLib/src/libtommath/bn_mp_montgomery_reduce.c +118 -0
  497. data/ext/stormlib/StormLib/src/libtommath/bn_mp_montgomery_setup.c +59 -0
  498. data/ext/stormlib/StormLib/src/libtommath/bn_mp_mul.c +66 -0
  499. data/ext/stormlib/StormLib/src/libtommath/bn_mp_mul_2.c +82 -0
  500. data/ext/stormlib/StormLib/src/libtommath/bn_mp_mul_2d.c +85 -0
  501. data/ext/stormlib/StormLib/src/libtommath/bn_mp_mul_d.c +79 -0
  502. data/ext/stormlib/StormLib/src/libtommath/bn_mp_mulmod.c +40 -0
  503. data/ext/stormlib/StormLib/src/libtommath/bn_mp_n_root.c +132 -0
  504. data/ext/stormlib/StormLib/src/libtommath/bn_mp_neg.c +40 -0
  505. data/ext/stormlib/StormLib/src/libtommath/bn_mp_or.c +50 -0
  506. data/ext/stormlib/StormLib/src/libtommath/bn_mp_prime_fermat.c +62 -0
  507. data/ext/stormlib/StormLib/src/libtommath/bn_mp_prime_is_divisible.c +50 -0
  508. data/ext/stormlib/StormLib/src/libtommath/bn_mp_prime_is_prime.c +83 -0
  509. data/ext/stormlib/StormLib/src/libtommath/bn_mp_prime_miller_rabin.c +103 -0
  510. data/ext/stormlib/StormLib/src/libtommath/bn_mp_prime_next_prime.c +170 -0
  511. data/ext/stormlib/StormLib/src/libtommath/bn_mp_prime_rabin_miller_trials.c +52 -0
  512. data/ext/stormlib/StormLib/src/libtommath/bn_mp_prime_random_ex.c +125 -0
  513. data/ext/stormlib/StormLib/src/libtommath/bn_mp_radix_size.c +78 -0
  514. data/ext/stormlib/StormLib/src/libtommath/bn_mp_radix_smap.c +24 -0
  515. data/ext/stormlib/StormLib/src/libtommath/bn_mp_rand.c +55 -0
  516. data/ext/stormlib/StormLib/src/libtommath/bn_mp_read_radix.c +85 -0
  517. data/ext/stormlib/StormLib/src/libtommath/bn_mp_read_signed_bin.c +41 -0
  518. data/ext/stormlib/StormLib/src/libtommath/bn_mp_read_unsigned_bin.c +55 -0
  519. data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce.c +100 -0
  520. data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce_2k.c +61 -0
  521. data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce_2k_l.c +62 -0
  522. data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce_2k_setup.c +47 -0
  523. data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce_2k_setup_l.c +44 -0
  524. data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce_is_2k.c +52 -0
  525. data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce_is_2k_l.c +44 -0
  526. data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce_setup.c +34 -0
  527. data/ext/stormlib/StormLib/src/libtommath/bn_mp_rshd.c +72 -0
  528. data/ext/stormlib/StormLib/src/libtommath/bn_mp_set.c +29 -0
  529. data/ext/stormlib/StormLib/src/libtommath/bn_mp_set_int.c +48 -0
  530. data/ext/stormlib/StormLib/src/libtommath/bn_mp_shrink.c +35 -0
  531. data/ext/stormlib/StormLib/src/libtommath/bn_mp_signed_bin_size.c +27 -0
  532. data/ext/stormlib/StormLib/src/libtommath/bn_mp_sqr.c +58 -0
  533. data/ext/stormlib/StormLib/src/libtommath/bn_mp_sqrmod.c +41 -0
  534. data/ext/stormlib/StormLib/src/libtommath/bn_mp_sqrt.c +81 -0
  535. data/ext/stormlib/StormLib/src/libtommath/bn_mp_sub.c +59 -0
  536. data/ext/stormlib/StormLib/src/libtommath/bn_mp_sub_d.c +93 -0
  537. data/ext/stormlib/StormLib/src/libtommath/bn_mp_submod.c +42 -0
  538. data/ext/stormlib/StormLib/src/libtommath/bn_mp_to_signed_bin.c +33 -0
  539. data/ext/stormlib/StormLib/src/libtommath/bn_mp_to_signed_bin_n.c +31 -0
  540. data/ext/stormlib/StormLib/src/libtommath/bn_mp_to_unsigned_bin.c +48 -0
  541. data/ext/stormlib/StormLib/src/libtommath/bn_mp_to_unsigned_bin_n.c +31 -0
  542. data/ext/stormlib/StormLib/src/libtommath/bn_mp_toom_mul.c +284 -0
  543. data/ext/stormlib/StormLib/src/libtommath/bn_mp_toom_sqr.c +226 -0
  544. data/ext/stormlib/StormLib/src/libtommath/bn_mp_toradix.c +75 -0
  545. data/ext/stormlib/StormLib/src/libtommath/bn_mp_toradix_n.c +88 -0
  546. data/ext/stormlib/StormLib/src/libtommath/bn_mp_unsigned_bin_size.c +28 -0
  547. data/ext/stormlib/StormLib/src/libtommath/bn_mp_xor.c +51 -0
  548. data/ext/stormlib/StormLib/src/libtommath/bn_mp_zero.c +36 -0
  549. data/ext/stormlib/StormLib/src/libtommath/bn_prime_tab.c +61 -0
  550. data/ext/stormlib/StormLib/src/libtommath/bn_reverse.c +39 -0
  551. data/ext/stormlib/StormLib/src/libtommath/bn_s_mp_add.c +109 -0
  552. data/ext/stormlib/StormLib/src/libtommath/bn_s_mp_exptmod.c +252 -0
  553. data/ext/stormlib/StormLib/src/libtommath/bn_s_mp_mul_digs.c +90 -0
  554. data/ext/stormlib/StormLib/src/libtommath/bn_s_mp_mul_high_digs.c +81 -0
  555. data/ext/stormlib/StormLib/src/libtommath/bn_s_mp_sqr.c +84 -0
  556. data/ext/stormlib/StormLib/src/libtommath/bn_s_mp_sub.c +89 -0
  557. data/ext/stormlib/StormLib/src/libtommath/bncore.c +36 -0
  558. data/ext/stormlib/StormLib/src/libtommath/tommath.h +584 -0
  559. data/ext/stormlib/StormLib/src/libtommath/tommath_class.h +999 -0
  560. data/ext/stormlib/StormLib/src/libtommath/tommath_superclass.h +76 -0
  561. data/ext/stormlib/StormLib/src/lzma/C/LzFind.c +761 -0
  562. data/ext/stormlib/StormLib/src/lzma/C/LzFind.h +115 -0
  563. data/ext/stormlib/StormLib/src/lzma/C/LzFindMt.c +793 -0
  564. data/ext/stormlib/StormLib/src/lzma/C/LzFindMt.h +105 -0
  565. data/ext/stormlib/StormLib/src/lzma/C/LzHash.h +54 -0
  566. data/ext/stormlib/StormLib/src/lzma/C/LzmaDec.c +999 -0
  567. data/ext/stormlib/StormLib/src/lzma/C/LzmaDec.h +231 -0
  568. data/ext/stormlib/StormLib/src/lzma/C/LzmaEnc.c +2268 -0
  569. data/ext/stormlib/StormLib/src/lzma/C/LzmaEnc.h +80 -0
  570. data/ext/stormlib/StormLib/src/lzma/C/Threads.c +84 -0
  571. data/ext/stormlib/StormLib/src/lzma/C/Threads.h +59 -0
  572. data/ext/stormlib/StormLib/src/lzma/C/Types.h +236 -0
  573. data/ext/stormlib/StormLib/src/lzma/info.txt +1 -0
  574. data/ext/stormlib/StormLib/src/pklib/crc32.c +66 -0
  575. data/ext/stormlib/StormLib/src/pklib/explode.c +521 -0
  576. data/ext/stormlib/StormLib/src/pklib/implode.c +674 -0
  577. data/ext/stormlib/StormLib/src/pklib/pklib.h +160 -0
  578. data/ext/stormlib/StormLib/src/resource.h +15 -0
  579. data/ext/stormlib/StormLib/src/sparse/sparse.cpp +287 -0
  580. data/ext/stormlib/StormLib/src/sparse/sparse.h +17 -0
  581. data/ext/stormlib/StormLib/src/wdk/sources-cpp.cpp +26 -0
  582. data/ext/stormlib/StormLib/src/wdk/sources-wdk-bzip2.c +13 -0
  583. data/ext/stormlib/StormLib/src/wdk/sources-wdk-ltc.c +4 -0
  584. data/ext/stormlib/StormLib/src/wdk/sources-wdk-lzma.c +8 -0
  585. data/ext/stormlib/StormLib/src/wdk/sources-wdk-misc.c +6 -0
  586. data/ext/stormlib/StormLib/src/wdk/sources-wdk-tomcrypt.c +82 -0
  587. data/ext/stormlib/StormLib/src/wdk/sources-wdk-tommath.c +123 -0
  588. data/ext/stormlib/StormLib/src/wdk/sources-wdk-zlib.c +21 -0
  589. data/ext/stormlib/StormLib/src/zlib/adler32.c +169 -0
  590. data/ext/stormlib/StormLib/src/zlib/compress.c +80 -0
  591. data/ext/stormlib/StormLib/src/zlib/compress_zlib.c +5 -0
  592. data/ext/stormlib/StormLib/src/zlib/crc32.c +442 -0
  593. data/ext/stormlib/StormLib/src/zlib/crc32.h +441 -0
  594. data/ext/stormlib/StormLib/src/zlib/deflate.c +1834 -0
  595. data/ext/stormlib/StormLib/src/zlib/deflate.h +342 -0
  596. data/ext/stormlib/StormLib/src/zlib/gzguts.h +218 -0
  597. data/ext/stormlib/StormLib/src/zlib/inffast.c +340 -0
  598. data/ext/stormlib/StormLib/src/zlib/inffast.h +11 -0
  599. data/ext/stormlib/StormLib/src/zlib/inffixed.h +94 -0
  600. data/ext/stormlib/StormLib/src/zlib/inflate.c +1480 -0
  601. data/ext/stormlib/StormLib/src/zlib/inflate.h +130 -0
  602. data/ext/stormlib/StormLib/src/zlib/inftrees.c +330 -0
  603. data/ext/stormlib/StormLib/src/zlib/inftrees.h +67 -0
  604. data/ext/stormlib/StormLib/src/zlib/trees.c +1244 -0
  605. data/ext/stormlib/StormLib/src/zlib/trees.h +128 -0
  606. data/ext/stormlib/StormLib/src/zlib/zconf.h +428 -0
  607. data/ext/stormlib/StormLib/src/zlib/zlib.h +1613 -0
  608. data/ext/stormlib/StormLib/src/zlib/zutil.c +318 -0
  609. data/ext/stormlib/StormLib/src/zlib/zutil.h +274 -0
  610. data/ext/stormlib/StormLib/storm_dll/storm.cpp +117 -0
  611. data/ext/stormlib/StormLib/storm_dll/storm.def +25 -0
  612. data/ext/stormlib/StormLib/storm_dll/storm.h +65 -0
  613. data/ext/stormlib/StormLib/storm_dll/storm.vcxproj +209 -0
  614. data/ext/stormlib/StormLib/storm_dll/storm.vcxproj.filters +28 -0
  615. data/ext/stormlib/StormLib/storm_dll/storm_test.cpp +182 -0
  616. data/ext/stormlib/StormLib/storm_dll/storm_test.vcxproj +202 -0
  617. data/ext/stormlib/StormLib/storm_dll/storm_test.vcxproj.filters +22 -0
  618. data/ext/stormlib/StormLib/test/StormTest.cpp +4393 -0
  619. data/ext/stormlib/StormLib/test/TLogHelper.cpp +567 -0
  620. data/ext/stormlib/StormLib/test/stormlib-test-001.txt +164 -0
  621. data/ext/stormlib/extconf.rb +0 -2
  622. data/lib/stormlib/version.rb +1 -1
  623. data/stormlib.gemspec +1 -1
  624. metadata +621 -2
@@ -0,0 +1,3194 @@
1
+ /*****************************************************************************/
2
+ /* SBaseFileTable.cpp Copyright (c) Ladislav Zezula 2010 */
3
+ /*---------------------------------------------------------------------------*/
4
+ /* Description: Common handler for classic and new hash&block tables */
5
+ /*---------------------------------------------------------------------------*/
6
+ /* Date Ver Who Comment */
7
+ /* -------- ---- --- ------- */
8
+ /* 06.09.10 1.00 Lad The first version of SBaseFileTable.cpp */
9
+ /*****************************************************************************/
10
+
11
+ #define __STORMLIB_SELF__
12
+ #include "StormLib.h"
13
+ #include "StormCommon.h"
14
+
15
+ //-----------------------------------------------------------------------------
16
+ // Local defines
17
+
18
+ #define INVALID_FLAG_VALUE 0xCCCCCCCC
19
+ #define MAX_FLAG_INDEX 512
20
+
21
+ //-----------------------------------------------------------------------------
22
+ // Support for calculating bit sizes
23
+
24
+ static void InitFileFlagArray(LPDWORD FlagArray)
25
+ {
26
+ memset(FlagArray, 0xCC, MAX_FLAG_INDEX * sizeof(DWORD));
27
+ }
28
+
29
+ static DWORD GetFileFlagIndex(LPDWORD FlagArray, DWORD dwFlags)
30
+ {
31
+ // Find free or equal entry in the flag array
32
+ for(DWORD dwFlagIndex = 0; dwFlagIndex < MAX_FLAG_INDEX; dwFlagIndex++)
33
+ {
34
+ if(FlagArray[dwFlagIndex] == INVALID_FLAG_VALUE || FlagArray[dwFlagIndex] == dwFlags)
35
+ {
36
+ FlagArray[dwFlagIndex] = dwFlags;
37
+ return dwFlagIndex;
38
+ }
39
+ }
40
+
41
+ // This should never happen
42
+ assert(false);
43
+ return 0xFFFFFFFF;
44
+ }
45
+
46
+ static DWORD GetNecessaryBitCount(ULONGLONG MaxValue)
47
+ {
48
+ DWORD dwBitCount = 0;
49
+
50
+ while(MaxValue > 0)
51
+ {
52
+ MaxValue >>= 1;
53
+ dwBitCount++;
54
+ }
55
+
56
+ return dwBitCount;
57
+ }
58
+
59
+ //-----------------------------------------------------------------------------
60
+ // Implementation of the TMPQBits struct
61
+
62
+ struct TMPQBits
63
+ {
64
+ static TMPQBits * Create(DWORD NumberOfBits, BYTE FillValue);
65
+
66
+ DWORD GetBits(unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, unsigned int nResultSize);
67
+ DWORD SetBits(unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, unsigned int nResultSize);
68
+
69
+ static const USHORT SetBitsMask[]; // Bit mask for each number of bits (0-8)
70
+
71
+ DWORD NumberOfBytes; // Total number of bytes in "Elements"
72
+ DWORD NumberOfBits; // Total number of bits that are available
73
+ BYTE Elements[1]; // Array of elements (variable length)
74
+ };
75
+
76
+ const USHORT TMPQBits::SetBitsMask[] = {0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
77
+
78
+ TMPQBits * TMPQBits::Create(
79
+ DWORD NumberOfBits,
80
+ BYTE FillValue)
81
+ {
82
+ TMPQBits * pBitArray;
83
+ size_t nSize = sizeof(TMPQBits) + (NumberOfBits + 7) / 8;
84
+
85
+ // Allocate the bit array
86
+ pBitArray = (TMPQBits *)STORM_ALLOC(BYTE, nSize);
87
+ if(pBitArray != NULL)
88
+ {
89
+ memset(pBitArray, FillValue, nSize);
90
+ pBitArray->NumberOfBytes = (NumberOfBits + 7) / 8;
91
+ pBitArray->NumberOfBits = NumberOfBits;
92
+ }
93
+
94
+ return pBitArray;
95
+ }
96
+
97
+ DWORD TMPQBits::GetBits(
98
+ unsigned int nBitPosition,
99
+ unsigned int nBitLength,
100
+ void * pvBuffer,
101
+ unsigned int nResultByteSize)
102
+ {
103
+ unsigned char * pbBuffer = (unsigned char *)pvBuffer;
104
+ unsigned int nBytePosition0 = (nBitPosition / 8);
105
+ unsigned int nBytePosition1 = nBytePosition0 + 1;
106
+ unsigned int nByteLength = (nBitLength / 8);
107
+ unsigned int nBitOffset = (nBitPosition & 0x07);
108
+ unsigned char BitBuffer;
109
+
110
+ // Check for bit overflow
111
+ if(nBitPosition + nBitLength < nBitPosition)
112
+ return ERROR_BUFFER_OVERFLOW;
113
+ if(nBitPosition + nBitLength > NumberOfBits)
114
+ return ERROR_BUFFER_OVERFLOW;
115
+ if(nByteLength > nResultByteSize)
116
+ return ERROR_BUFFER_OVERFLOW;
117
+
118
+ #ifdef _DEBUG
119
+ // Check if the target is properly zeroed
120
+ for(unsigned int i = 0; i < nResultByteSize; i++)
121
+ assert(pbBuffer[i] == 0);
122
+ #endif
123
+
124
+ #ifndef STORMLIB_LITTLE_ENDIAN
125
+ // Adjust the buffer pointer for big endian platforms
126
+ pbBuffer += (nResultByteSize - 1);
127
+ #endif
128
+
129
+ // Copy whole bytes, if any
130
+ while(nByteLength > 0)
131
+ {
132
+ // Is the current position in the Elements byte-aligned?
133
+ if(nBitOffset != 0)
134
+ {
135
+ BitBuffer = (unsigned char)((Elements[nBytePosition0] >> nBitOffset) | (Elements[nBytePosition1] << (0x08 - nBitOffset)));
136
+ }
137
+ else
138
+ {
139
+ BitBuffer = Elements[nBytePosition0];
140
+ }
141
+
142
+ #ifdef STORMLIB_LITTLE_ENDIAN
143
+ *pbBuffer++ = BitBuffer;
144
+ #else
145
+ *pbBuffer-- = BitBuffer;
146
+ #endif
147
+
148
+ // Move byte positions and lengths
149
+ nBytePosition1++;
150
+ nBytePosition0++;
151
+ nByteLength--;
152
+ }
153
+
154
+ // Get the rest of the bits
155
+ nBitLength = (nBitLength & 0x07);
156
+ if(nBitLength != 0)
157
+ {
158
+ *pbBuffer = (unsigned char)(Elements[nBytePosition0] >> nBitOffset);
159
+
160
+ if(nBitLength > (8 - nBitOffset))
161
+ *pbBuffer = (unsigned char)((Elements[nBytePosition1] << (8 - nBitOffset)) | (Elements[nBytePosition0] >> nBitOffset));
162
+
163
+ *pbBuffer &= (0x01 << nBitLength) - 1;
164
+ }
165
+ return ERROR_SUCCESS;
166
+ }
167
+
168
+ DWORD TMPQBits::SetBits(
169
+ unsigned int nBitPosition,
170
+ unsigned int nBitLength,
171
+ void * pvBuffer,
172
+ unsigned int nResultByteSize)
173
+ {
174
+ unsigned char * pbBuffer = (unsigned char *)pvBuffer;
175
+ unsigned int nBytePosition = (nBitPosition / 8);
176
+ unsigned int nBitOffset = (nBitPosition & 0x07);
177
+ unsigned short BitBuffer = 0;
178
+ unsigned short AndMask = 0;
179
+ unsigned short OneByte = 0;
180
+
181
+ // Keep compilers happy for platforms where nResultByteSize is not used
182
+ STORMLIB_UNUSED(nResultByteSize);
183
+
184
+ // Check for bit overflow
185
+ if(nBitPosition + nBitLength < nBitPosition)
186
+ return ERROR_BUFFER_OVERFLOW;
187
+ if(nBitPosition + nBitLength > NumberOfBits)
188
+ return ERROR_BUFFER_OVERFLOW;
189
+ if(nBitLength / 8 > nResultByteSize)
190
+ return ERROR_BUFFER_OVERFLOW;
191
+
192
+ #ifndef STORMLIB_LITTLE_ENDIAN
193
+ // Adjust the buffer pointer for big endian platforms
194
+ pbBuffer += (nResultByteSize - 1);
195
+ #endif
196
+
197
+ // Copy whole bytes, if any
198
+ while(nBitLength > 8)
199
+ {
200
+ // Reload the bit buffer
201
+ #ifdef STORMLIB_LITTLE_ENDIAN
202
+ OneByte = *pbBuffer++;
203
+ #else
204
+ OneByte = *pbBuffer--;
205
+ #endif
206
+ // Update the BitBuffer and AndMask for the bit array
207
+ BitBuffer = (BitBuffer >> 0x08) | (OneByte << nBitOffset);
208
+ AndMask = (AndMask >> 0x08) | (0x00FF << nBitOffset);
209
+
210
+ // Update the byte in the array
211
+ Elements[nBytePosition] = (BYTE)((Elements[nBytePosition] & ~AndMask) | BitBuffer);
212
+
213
+ // Move byte positions and lengths
214
+ nBytePosition++;
215
+ nBitLength -= 0x08;
216
+ }
217
+
218
+ if(nBitLength != 0)
219
+ {
220
+ // Reload the bit buffer
221
+ OneByte = *pbBuffer;
222
+
223
+ // Update the AND mask for the last bit
224
+ BitBuffer = (BitBuffer >> 0x08) | (OneByte << nBitOffset);
225
+ AndMask = (AndMask >> 0x08) | (SetBitsMask[nBitLength] << nBitOffset);
226
+
227
+ // Update the byte in the array
228
+ Elements[nBytePosition] = (BYTE)((Elements[nBytePosition] & ~AndMask) | BitBuffer);
229
+
230
+ // Update the next byte, if needed
231
+ if(AndMask & 0xFF00)
232
+ {
233
+ nBytePosition++;
234
+ BitBuffer >>= 0x08;
235
+ AndMask >>= 0x08;
236
+
237
+ Elements[nBytePosition] = (BYTE)((Elements[nBytePosition] & ~AndMask) | BitBuffer);
238
+ }
239
+ }
240
+ return ERROR_SUCCESS;
241
+ }
242
+
243
+ void GetMPQBits(TMPQBits * pBits, unsigned int nBitPosition, unsigned int nBitLength, void * pvBuffer, int nResultByteSize)
244
+ {
245
+ pBits->GetBits(nBitPosition, nBitLength, pvBuffer, nResultByteSize);
246
+ }
247
+
248
+ //-----------------------------------------------------------------------------
249
+ // Support for MPQ header
250
+
251
+ static bool VerifyTablePosition64(
252
+ ULONGLONG MpqOffset, // Position of the MPQ header
253
+ ULONGLONG TableOffset, // Position of the MPQ table, relative to MPQ header
254
+ ULONGLONG TableSize, // Size of the MPQ table, in bytes
255
+ ULONGLONG FileSize) // Size of the entire file, in bytes
256
+ {
257
+ if(TableOffset != 0)
258
+ {
259
+ // Verify overflows
260
+ if((MpqOffset + TableOffset) < MpqOffset)
261
+ return false;
262
+ if((MpqOffset + TableOffset + TableSize) < MpqOffset)
263
+ return false;
264
+
265
+ // Verify sizes
266
+ if(TableOffset >= FileSize || TableSize >= FileSize)
267
+ return false;
268
+ if((MpqOffset + TableOffset) >= FileSize)
269
+ return false;
270
+ if((MpqOffset + TableOffset + TableSize) >= FileSize)
271
+ return false;
272
+ }
273
+ return true;
274
+ }
275
+
276
+ static bool VerifyTableTandemPositions(
277
+ ULONGLONG MpqOffset, // Position of the MPQ header
278
+ ULONGLONG TableOffset1, // 1st table: Position, relative to MPQ header
279
+ ULONGLONG TableSize1, // 1st table: Size in bytes
280
+ ULONGLONG TableOffset2, // 2nd table: Position, relative to MPQ header
281
+ ULONGLONG TableSize2, // 2nd table: Size in bytes
282
+ ULONGLONG FileSize) // Size of the entire file, in bytes
283
+ {
284
+ return VerifyTablePosition64(MpqOffset, TableOffset1, TableSize1, FileSize) &&
285
+ VerifyTablePosition64(MpqOffset, TableOffset2, TableSize2, FileSize);
286
+ }
287
+
288
+ static ULONGLONG DetermineArchiveSize_V1(
289
+ TMPQArchive * ha,
290
+ TMPQHeader * pHeader,
291
+ ULONGLONG MpqOffset,
292
+ ULONGLONG FileSize)
293
+ {
294
+ ULONGLONG ByteOffset;
295
+ ULONGLONG EndOfMpq = FileSize;
296
+ DWORD SignatureHeader = 0;
297
+ DWORD dwArchiveSize32;
298
+
299
+ // This could only be called for MPQs version 1.0
300
+ assert(pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1);
301
+
302
+ // Check if we can rely on the archive size in the header
303
+ if(pHeader->dwBlockTablePos < pHeader->dwArchiveSize)
304
+ {
305
+ // The block table cannot be compressed, so the sizes must match
306
+ if((pHeader->dwArchiveSize - pHeader->dwBlockTablePos) == (pHeader->dwBlockTableSize * sizeof(TMPQBlock)))
307
+ return pHeader->dwArchiveSize;
308
+
309
+ // If the archive size in the header is less than real file size
310
+ dwArchiveSize32 = (DWORD)(FileSize - MpqOffset);
311
+ if(pHeader->dwArchiveSize == dwArchiveSize32)
312
+ return pHeader->dwArchiveSize;
313
+ }
314
+
315
+ // Check if there is a signature header
316
+ if((EndOfMpq - MpqOffset) > (MPQ_STRONG_SIGNATURE_SIZE + 4))
317
+ {
318
+ ByteOffset = EndOfMpq - MPQ_STRONG_SIGNATURE_SIZE - 4;
319
+ if(FileStream_Read(ha->pStream, &ByteOffset, &SignatureHeader, sizeof(DWORD)))
320
+ {
321
+ if(BSWAP_INT32_UNSIGNED(SignatureHeader) == MPQ_STRONG_SIGNATURE_ID)
322
+ EndOfMpq = EndOfMpq - MPQ_STRONG_SIGNATURE_SIZE - 4;
323
+ }
324
+ }
325
+
326
+ // Return the returned archive size
327
+ return (EndOfMpq - MpqOffset);
328
+ }
329
+
330
+ static ULONGLONG DetermineBlockTableSize_V2(TMPQHeader * pHeader, ULONGLONG MpqHeaderPos, ULONGLONG FileSize)
331
+ {
332
+ ULONGLONG BlockTablePos = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
333
+ ULONGLONG ArchiveSize = FileSize - MpqHeaderPos;
334
+
335
+ // If there is a hi-block table and it is beyond the block table,
336
+ // we can determine the block table size from it
337
+ if(pHeader->HiBlockTablePos64 != 0)
338
+ {
339
+ if(pHeader->HiBlockTablePos64 > BlockTablePos)
340
+ {
341
+ return (pHeader->HiBlockTablePos64 - BlockTablePos);
342
+ }
343
+ }
344
+
345
+ // If we have valid archive size, we can determine the block table size from the archive size
346
+ else
347
+ {
348
+ if((BlockTablePos >> 0x20) == 0 && (ArchiveSize >> 0x20) == 0)
349
+ {
350
+ DWORD dwBlockTablePos32 = (DWORD)(BlockTablePos);
351
+ DWORD dwArchiveSize32 = (DWORD)(ArchiveSize);
352
+
353
+ if(pHeader->dwArchiveSize == dwArchiveSize32)
354
+ {
355
+ return (dwArchiveSize32 - dwBlockTablePos32);
356
+ }
357
+ }
358
+ }
359
+
360
+ // Default is the block table size from MPQ header
361
+ return (ULONGLONG)(pHeader->dwBlockTableSize) * sizeof(TMPQBlock);
362
+ }
363
+
364
+ static ULONGLONG DetermineArchiveSize_V4(
365
+ TMPQHeader * pHeader,
366
+ ULONGLONG /* MpqOffset */,
367
+ ULONGLONG /* FileSize */)
368
+ {
369
+ ULONGLONG ArchiveSize = 0;
370
+ ULONGLONG EndOfTable;
371
+
372
+ // This could only be called for MPQs version 4
373
+ assert(pHeader->wFormatVersion == MPQ_FORMAT_VERSION_4);
374
+
375
+ // Check position of BET table, if correct
376
+ if((pHeader->BetTablePos64 >> 0x20) == 0 && (pHeader->BetTableSize64 >> 0x20) == 0)
377
+ {
378
+ EndOfTable = pHeader->BetTablePos64 + pHeader->BetTableSize64;
379
+ if(EndOfTable > ArchiveSize)
380
+ ArchiveSize = EndOfTable;
381
+ }
382
+
383
+ // Check position of HET table, if correct
384
+ if((pHeader->HetTablePos64 >> 0x20) == 0 && (pHeader->HetTableSize64 >> 0x20) == 0)
385
+ {
386
+ EndOfTable = pHeader->HetTablePos64 + pHeader->HetTableSize64;
387
+ if(EndOfTable > ArchiveSize)
388
+ ArchiveSize = EndOfTable;
389
+ }
390
+
391
+ EndOfTable = pHeader->dwHashTablePos + pHeader->dwHashTableSize * sizeof(TMPQHash);
392
+ if(EndOfTable > ArchiveSize)
393
+ ArchiveSize = EndOfTable;
394
+
395
+ EndOfTable = pHeader->dwBlockTablePos + pHeader->dwBlockTableSize * sizeof(TMPQBlock);
396
+ if(EndOfTable > ArchiveSize)
397
+ ArchiveSize = EndOfTable;
398
+
399
+ // Return the calculated archive size
400
+ return ArchiveSize;
401
+ }
402
+
403
+ ULONGLONG GetFileOffsetMask(TMPQArchive * ha)
404
+ {
405
+ ULONGLONG FileOffsetMask = (ULONGLONG)(-1);
406
+
407
+ // Sanity checks
408
+ assert(ha != NULL);
409
+ assert(ha->pHeader != NULL);
410
+
411
+ // MPQs of format 1 are 32-bit only
412
+ if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1)
413
+ FileOffsetMask = (ULONGLONG)(DWORD)(-1);
414
+ return FileOffsetMask;
415
+ }
416
+
417
+ ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset)
418
+ {
419
+ return (ha->MpqPos + MpqOffset) & ha->FileOffsetMask;
420
+ }
421
+
422
+ //ULONGLONG FileOffsetFromMpqOffset(TMPQArchive * ha, ULONGLONG MpqOffset)
423
+ //{
424
+ // if(ha->pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1)
425
+ // {
426
+ // // For MPQ archive v1, any file offset is only 32-bit
427
+ // return (ULONGLONG)((DWORD)ha->MpqPos + (DWORD)MpqOffset);
428
+ // }
429
+ // else
430
+ // {
431
+ // // For MPQ archive v2+, file offsets are full 64-bit
432
+ // return ha->MpqPos + MpqOffset;
433
+ // }
434
+ //}
435
+
436
+ ULONGLONG CalculateRawSectorOffset(
437
+ TMPQFile * hf,
438
+ DWORD dwSectorOffset)
439
+ {
440
+ ULONGLONG RawFilePos;
441
+
442
+ // Must be used for files within a MPQ
443
+ assert(hf->ha != NULL);
444
+ assert(hf->ha->pHeader != NULL);
445
+
446
+ //
447
+ // Some MPQ protectors place the sector offset table after the actual file data.
448
+ // Sector offsets in the sector offset table are negative. When added
449
+ // to MPQ file offset from the block table entry, the result is a correct
450
+ // position of the file data in the MPQ.
451
+ //
452
+ // For MPQs version 1.0, the offset is purely 32-bit
453
+ //
454
+
455
+ RawFilePos = (hf->RawFilePos + dwSectorOffset) & hf->ha->FileOffsetMask;
456
+
457
+ // We also have to add patch header size, if patch header is present
458
+ if(hf->pPatchInfo != NULL)
459
+ RawFilePos += hf->pPatchInfo->dwLength;
460
+
461
+ // Return the result offset
462
+ return RawFilePos;
463
+ }
464
+
465
+ // This function converts the MPQ header so it always looks like version 4
466
+ DWORD ConvertMpqHeaderToFormat4(
467
+ TMPQArchive * ha,
468
+ ULONGLONG ByteOffset,
469
+ ULONGLONG FileSize,
470
+ DWORD dwFlags,
471
+ MTYPE MapType)
472
+ {
473
+ TMPQHeader * pHeader = (TMPQHeader *)ha->HeaderData;
474
+ ULONGLONG BlockTablePos64 = 0;
475
+ ULONGLONG HashTablePos64 = 0;
476
+ ULONGLONG BlockTableMask = (ULONGLONG)-1;
477
+ ULONGLONG MaxOffset;
478
+ USHORT wFormatVersion = BSWAP_INT16_UNSIGNED(pHeader->wFormatVersion);
479
+ bool bHashBlockOffsetOK = false;
480
+ bool bHetBetOffsetOK = false;
481
+ DWORD dwErrCode = ERROR_SUCCESS;
482
+
483
+ // If version 1.0 is forced, then the format version is forced to be 1.0
484
+ // Reason: Storm.dll in Warcraft III ignores format version value
485
+ if((MapType == MapTypeWarcraft3) || (dwFlags & MPQ_OPEN_FORCE_MPQ_V1))
486
+ wFormatVersion = MPQ_FORMAT_VERSION_1;
487
+
488
+ // Don't accept format 3 for Starcraft II maps
489
+ if((MapType == MapTypeStarcraft2) && (pHeader->wFormatVersion > MPQ_FORMAT_VERSION_2))
490
+ wFormatVersion = MPQ_FORMAT_VERSION_4;
491
+
492
+ // Format-specific fixes
493
+ switch(wFormatVersion)
494
+ {
495
+ case MPQ_FORMAT_VERSION_1:
496
+
497
+ // Make sure that the MPQ Header is properly swapped
498
+ BSWAP_TMPQHEADER(pHeader, MPQ_FORMAT_VERSION_1);
499
+
500
+ // Check for blatantly wrong MPQ header by the hash table position
501
+ if(((ByteOffset + pHeader->dwHashTablePos) & 0xFFFFFFFF) > FileSize)
502
+ return ERROR_FAKE_MPQ_HEADER;
503
+ if(((ByteOffset + pHeader->dwBlockTablePos) & 0xFFFFFFFF) > FileSize)
504
+ return ERROR_FAKE_MPQ_HEADER;
505
+
506
+ // Check for malformed MPQ header version 1.0
507
+ if(pHeader->wFormatVersion != MPQ_FORMAT_VERSION_1 || pHeader->dwHeaderSize != MPQ_HEADER_SIZE_V1)
508
+ {
509
+ pHeader->wFormatVersion = MPQ_FORMAT_VERSION_1;
510
+ pHeader->dwHeaderSize = MPQ_HEADER_SIZE_V1;
511
+ ha->dwFlags |= MPQ_FLAG_MALFORMED;
512
+ }
513
+
514
+ //
515
+ // Note: The value of "dwArchiveSize" member in the MPQ header
516
+ // is ignored by Storm.dll and can contain garbage value
517
+ // ("w3xmaster" protector).
518
+ //
519
+
520
+ Label_ArchiveVersion1:
521
+ if(pHeader->dwBlockTableSize > 1) // Prevent empty MPQs being marked as malformed
522
+ {
523
+ if(pHeader->dwHashTablePos <= pHeader->dwHeaderSize || (pHeader->dwHashTablePos & 0x80000000))
524
+ ha->dwFlags |= MPQ_FLAG_MALFORMED;
525
+ if(pHeader->dwBlockTablePos <= pHeader->dwHeaderSize || (pHeader->dwBlockTablePos & 0x80000000))
526
+ ha->dwFlags |= MPQ_FLAG_MALFORMED;
527
+ }
528
+
529
+ // Only low byte of sector size is really used
530
+ if(pHeader->wSectorSize & 0xFF00)
531
+ ha->dwFlags |= MPQ_FLAG_MALFORMED;
532
+ pHeader->wSectorSize = pHeader->wSectorSize & 0xFF;
533
+
534
+ // Fill the rest of the header
535
+ memset((LPBYTE)pHeader + MPQ_HEADER_SIZE_V1, 0, sizeof(TMPQHeader) - MPQ_HEADER_SIZE_V1);
536
+ pHeader->BlockTableSize64 = pHeader->dwBlockTableSize * sizeof(TMPQBlock);
537
+ pHeader->HashTableSize64 = pHeader->dwHashTableSize * sizeof(TMPQHash);
538
+ pHeader->ArchiveSize64 = pHeader->dwArchiveSize;
539
+
540
+ // Block table position must be calculated as 32-bit value
541
+ // Note: BOBA protector puts block table before the MPQ header, so it is negative
542
+ BlockTablePos64 = (ULONGLONG)((DWORD)ByteOffset + pHeader->dwBlockTablePos);
543
+ BlockTableMask = 0xFFFFFFF0;
544
+
545
+ // Determine the archive size on malformed MPQs
546
+ if(ha->dwFlags & MPQ_FLAG_MALFORMED)
547
+ {
548
+ // Calculate the archive size
549
+ pHeader->ArchiveSize64 = DetermineArchiveSize_V1(ha, pHeader, ByteOffset, FileSize);
550
+ pHeader->dwArchiveSize = (DWORD)pHeader->ArchiveSize64;
551
+ }
552
+
553
+ // EWIX_v8_7.w3x: TMPQHeader::dwBlockTableSize = 0x00319601
554
+ // Size of TFileTable goes to ~200MB, so we artificially cut it
555
+ if(BlockTablePos64 + (pHeader->dwBlockTableSize * sizeof(TMPQBlock)) > FileSize)
556
+ {
557
+ pHeader->dwBlockTableSize = (DWORD)((FileSize - BlockTablePos64) / sizeof(TMPQBlock));
558
+ pHeader->BlockTableSize64 = pHeader->dwBlockTableSize * sizeof(TMPQBlock);
559
+ }
560
+ break;
561
+
562
+ case MPQ_FORMAT_VERSION_2:
563
+
564
+ // Check for malformed MPQ header version 1.0
565
+ BSWAP_TMPQHEADER(pHeader, MPQ_FORMAT_VERSION_2);
566
+ if(pHeader->wFormatVersion != MPQ_FORMAT_VERSION_2 || pHeader->dwHeaderSize != MPQ_HEADER_SIZE_V2)
567
+ {
568
+ pHeader->wFormatVersion = MPQ_FORMAT_VERSION_1;
569
+ pHeader->dwHeaderSize = MPQ_HEADER_SIZE_V1;
570
+ ha->dwFlags |= MPQ_FLAG_MALFORMED;
571
+ goto Label_ArchiveVersion1;
572
+ }
573
+
574
+ // Fill the rest of the header with zeros
575
+ memset((LPBYTE)pHeader + MPQ_HEADER_SIZE_V2, 0, sizeof(TMPQHeader) - MPQ_HEADER_SIZE_V2);
576
+
577
+ // Check position of the hi-block table
578
+ if(pHeader->HiBlockTablePos64 > FileSize)
579
+ return ERROR_FILE_CORRUPT;
580
+
581
+ // Calculate the expected hash table size
582
+ pHeader->HashTableSize64 = (pHeader->dwHashTableSize * sizeof(TMPQHash));
583
+ HashTablePos64 = MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos);
584
+
585
+ // Calculate the expected block table size
586
+ pHeader->BlockTableSize64 = (pHeader->dwBlockTableSize * sizeof(TMPQBlock));
587
+ BlockTablePos64 = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
588
+
589
+ // We require the block table to follow hash table
590
+ if(BlockTablePos64 >= HashTablePos64)
591
+ {
592
+ // Determine whether the hash table is compressed. This can be detected
593
+ // by subtracting hash table position from the block table position.
594
+ pHeader->HashTableSize64 = BlockTablePos64 - HashTablePos64;
595
+
596
+ // Also, block table may be compressed. We check whether the HiBlockTable is there.
597
+ // If not, we try to use the archive size. Note that ArchiveSize may have
598
+ // an arbitrary value, because it is not tested by Blizzard games anymore
599
+ pHeader->BlockTableSize64 = DetermineBlockTableSize_V2(pHeader, ByteOffset, FileSize);
600
+ }
601
+ else
602
+ {
603
+ pHeader->ArchiveSize64 = pHeader->dwArchiveSize;
604
+ ha->dwFlags |= MPQ_FLAG_MALFORMED;
605
+ }
606
+
607
+ // Add the MPQ Offset
608
+ BlockTablePos64 += ByteOffset;
609
+ break;
610
+
611
+ case MPQ_FORMAT_VERSION_3:
612
+
613
+ // In MPQ format 3.0, the entire header is optional
614
+ // and the size of the header can actually be identical
615
+ // to size of header 2.0
616
+ BSWAP_TMPQHEADER(pHeader, MPQ_FORMAT_VERSION_3);
617
+ if(pHeader->dwHeaderSize < MPQ_HEADER_SIZE_V3)
618
+ {
619
+ pHeader->ArchiveSize64 = pHeader->dwArchiveSize;
620
+ pHeader->HetTablePos64 = 0;
621
+ pHeader->BetTablePos64 = 0;
622
+ }
623
+
624
+ // Fixup malformed MPQ header sizes
625
+ pHeader->dwHeaderSize = STORMLIB_MIN(pHeader->dwHeaderSize, MPQ_HEADER_SIZE_V3);
626
+
627
+ //
628
+ // We need to calculate the compressed size of each table. We assume the following order:
629
+ // 1) HET table
630
+ // 2) BET table
631
+ // 3) Classic hash table
632
+ // 4) Classic block table
633
+ // 5) Hi-block table
634
+ //
635
+
636
+ // Fill the rest of the header with zeros
637
+ memset((LPBYTE)pHeader + MPQ_HEADER_SIZE_V3, 0, sizeof(TMPQHeader) - MPQ_HEADER_SIZE_V3);
638
+ BlockTablePos64 = MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
639
+ HashTablePos64 = MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos);
640
+ MaxOffset = pHeader->ArchiveSize64;
641
+
642
+ // Size of the hi-block table
643
+ if(pHeader->HiBlockTablePos64)
644
+ {
645
+ if(pHeader->HiBlockTablePos64 > FileSize)
646
+ return ERROR_FILE_CORRUPT;
647
+ pHeader->HiBlockTableSize64 = MaxOffset - pHeader->HiBlockTablePos64;
648
+ MaxOffset = pHeader->HiBlockTablePos64;
649
+ }
650
+
651
+ // Size of the block table
652
+ if(BlockTablePos64)
653
+ {
654
+ if(BlockTablePos64 > FileSize)
655
+ return ERROR_FILE_CORRUPT;
656
+ pHeader->BlockTableSize64 = MaxOffset - BlockTablePos64;
657
+ MaxOffset = BlockTablePos64;
658
+ }
659
+
660
+ // Size of the hash table
661
+ if(HashTablePos64)
662
+ {
663
+ if(HashTablePos64 > FileSize)
664
+ return ERROR_FILE_CORRUPT;
665
+ pHeader->HashTableSize64 = MaxOffset - HashTablePos64;
666
+ MaxOffset = HashTablePos64;
667
+ }
668
+
669
+ // Size of the BET table
670
+ if(pHeader->BetTablePos64)
671
+ {
672
+ if(pHeader->BetTablePos64 > FileSize)
673
+ return ERROR_FILE_CORRUPT;
674
+ pHeader->BetTableSize64 = MaxOffset - pHeader->BetTablePos64;
675
+ MaxOffset = pHeader->BetTablePos64;
676
+ }
677
+
678
+ // Size of the HET table
679
+ if(pHeader->HetTablePos64)
680
+ {
681
+ if(pHeader->HetTablePos64 > FileSize)
682
+ return ERROR_FILE_CORRUPT;
683
+ pHeader->HetTableSize64 = MaxOffset - pHeader->HetTablePos64;
684
+ // MaxOffset = pHeader->HetTablePos64;
685
+ }
686
+
687
+ // Add the MPQ Offset
688
+ BlockTablePos64 += ByteOffset;
689
+ break;
690
+
691
+ case MPQ_FORMAT_VERSION_4:
692
+
693
+ // Verify header MD5. Header MD5 is calculated from the MPQ header since the 'MPQ\x1A'
694
+ // signature until the position of header MD5 at offset 0xC0
695
+ // Apparently, Starcraft II only accepts MPQ headers where the MPQ header hash matches
696
+ // If MD5 doesn't match, we ignore this offset. We also ignore it if there's no MD5 at all
697
+ if(!IsValidMD5(pHeader->MD5_MpqHeader))
698
+ return ERROR_FAKE_MPQ_HEADER;
699
+ if(!VerifyDataBlockHash(pHeader, MPQ_HEADER_SIZE_V4 - MD5_DIGEST_SIZE, pHeader->MD5_MpqHeader))
700
+ return ERROR_FAKE_MPQ_HEADER;
701
+
702
+ // Byteswap after header MD5 is verified
703
+ BSWAP_TMPQHEADER(pHeader, MPQ_FORMAT_VERSION_4);
704
+
705
+ // Fixup malformed MPQ header sizes
706
+ pHeader->dwHeaderSize = MPQ_HEADER_SIZE_V4;
707
+
708
+ // HiBlockTable must be 0 for archives under 4GB
709
+ if((pHeader->ArchiveSize64 >> 0x20) == 0 && pHeader->HiBlockTablePos64 != 0)
710
+ return ERROR_FAKE_MPQ_HEADER;
711
+
712
+ // Is the "HET&BET" table tandem OK?
713
+ bHetBetOffsetOK = VerifyTableTandemPositions(ByteOffset,
714
+ pHeader->HetTablePos64, pHeader->HetTableSize64,
715
+ pHeader->BetTablePos64, pHeader->BetTableSize64,
716
+ FileSize);
717
+
718
+ // Is the "Hash&Block" table tandem OK?
719
+ bHashBlockOffsetOK = VerifyTableTandemPositions(ByteOffset,
720
+ pHeader->dwHashTablePos, pHeader->HashTableSize64,
721
+ pHeader->dwBlockTablePos, pHeader->BlockTableSize64,
722
+ FileSize);
723
+
724
+ // At least one pair must be OK
725
+ if(bHetBetOffsetOK == false && bHashBlockOffsetOK == false)
726
+ return ERROR_FAKE_MPQ_HEADER;
727
+
728
+ // Check for malformed MPQs
729
+ if(pHeader->wFormatVersion != MPQ_FORMAT_VERSION_4 || (ByteOffset + pHeader->ArchiveSize64) > FileSize || (ByteOffset + pHeader->HiBlockTablePos64) >= FileSize)
730
+ {
731
+ pHeader->wFormatVersion = MPQ_FORMAT_VERSION_4;
732
+ pHeader->dwHeaderSize = MPQ_HEADER_SIZE_V4;
733
+ ha->dwFlags |= MPQ_FLAG_MALFORMED;
734
+ }
735
+
736
+ // Recalculate archive size
737
+ if(ha->dwFlags & MPQ_FLAG_MALFORMED)
738
+ {
739
+ // Calculate the archive size
740
+ pHeader->ArchiveSize64 = DetermineArchiveSize_V4(pHeader, ByteOffset, FileSize);
741
+ pHeader->dwArchiveSize = (DWORD)pHeader->ArchiveSize64;
742
+ }
743
+
744
+ // Calculate the block table position
745
+ BlockTablePos64 = ByteOffset + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
746
+ break;
747
+
748
+ default:
749
+
750
+ // Check if it's a War of the Immortal data file (SQP)
751
+ // If not, we treat it as malformed MPQ version 1.0
752
+ if(ConvertSqpHeaderToFormat4(ha, FileSize, dwFlags) != ERROR_SUCCESS)
753
+ {
754
+ pHeader->wFormatVersion = MPQ_FORMAT_VERSION_1;
755
+ pHeader->dwHeaderSize = MPQ_HEADER_SIZE_V1;
756
+ ha->dwFlags |= MPQ_FLAG_MALFORMED;
757
+ goto Label_ArchiveVersion1;
758
+ }
759
+
760
+ // Calculate the block table position
761
+ BlockTablePos64 = ByteOffset + MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos);
762
+ break;
763
+ }
764
+
765
+ // Handle case when block table is placed before the MPQ header
766
+ // Used by BOBA protector
767
+ if(BlockTablePos64 < ByteOffset)
768
+ ha->dwFlags |= MPQ_FLAG_MALFORMED;
769
+ return dwErrCode;
770
+ }
771
+
772
+ //-----------------------------------------------------------------------------
773
+ // Support for hash table
774
+
775
+ // Hash entry verification when the file table does not exist yet
776
+ bool IsValidHashEntry(TMPQArchive * ha, TMPQHash * pHash)
777
+ {
778
+ TFileEntry * pFileEntry = ha->pFileTable + MPQ_BLOCK_INDEX(pHash);
779
+
780
+ return ((MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize) && (pFileEntry->dwFlags & MPQ_FILE_EXISTS)) ? true : false;
781
+ }
782
+
783
+ // Hash entry verification when the file table does not exist yet
784
+ static bool IsValidHashEntry1(TMPQArchive * ha, TMPQHash * pHash, TMPQBlock * pBlockTable)
785
+ {
786
+ ULONGLONG ByteOffset;
787
+ TMPQBlock * pBlock;
788
+
789
+ // The block index is considered valid if it's less than block table size
790
+ if(MPQ_BLOCK_INDEX(pHash) < ha->pHeader->dwBlockTableSize)
791
+ {
792
+ // Calculate the block table position
793
+ pBlock = pBlockTable + MPQ_BLOCK_INDEX(pHash);
794
+
795
+ // Check whether this is an existing file
796
+ if(pBlock->dwFlags & MPQ_FILE_EXISTS)
797
+ {
798
+ // We don't allow to be file size greater than 2GB in malformed archives
799
+ if((ha->dwFlags & MPQ_FLAG_MALFORMED) && (pBlock->dwFSize >= 0x80000000))
800
+ return false;
801
+
802
+ // The begin of the file must be within the archive
803
+ ByteOffset = FileOffsetFromMpqOffset(ha, pBlock->dwFilePos);
804
+ return (ByteOffset < ha->FileSize);
805
+ }
806
+ }
807
+
808
+ return false;
809
+ }
810
+
811
+ // Returns a hash table entry in the following order:
812
+ // 1) A hash table entry with the preferred locale and platform
813
+ // 2) A hash table entry with the neutral|matching locale and neutral|matching platform
814
+ // 3) NULL
815
+ // Storm_2016.dll: 15020940
816
+ static TMPQHash * GetHashEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale)
817
+ {
818
+ TMPQHash * pFirstHash = GetFirstHashEntry(ha, szFileName);
819
+ TMPQHash * pBestEntry = NULL;
820
+ TMPQHash * pHash = pFirstHash;
821
+ USHORT Locale = SFILE_LOCALE(lcFileLocale);
822
+ BYTE Platform = SFILE_PLATFORM(lcFileLocale);
823
+
824
+ // Parse the found hashes
825
+ while(pHash != NULL)
826
+ {
827
+ // Storm_2016.dll: 150209CB
828
+ // If the hash entry matches both locale and platform, return it immediately
829
+ // Only do that for non-0 locale&platform, because for loc&plat=0, there's different
830
+ // processing in Warcraft III vs. Starcraft, which is abused by some protectors.
831
+ if((Locale || Platform) && pHash->Locale == Locale && pHash->Platform == Platform)
832
+ return pHash;
833
+
834
+ // Storm_2016.dll: 150209D9
835
+ // If (locale matches or is neutral) AND (platform matches or is neutral), remember this as the best entry
836
+ // Also remember the first matching entry for Starcraft maps
837
+ if(pHash->Locale == 0 || pHash->Locale == Locale)
838
+ {
839
+ if(pHash->Platform == 0 || pHash->Platform == Platform)
840
+ {
841
+ pBestEntry = pHash;
842
+ }
843
+ }
844
+
845
+ // Get the next hash entry for that file
846
+ pHash = GetNextHashEntry(ha, pFirstHash, pHash);
847
+ }
848
+
849
+ // Return the best entry that we found
850
+ return pBestEntry;
851
+ }
852
+
853
+ // Returns a hash table entry in the following order:
854
+ // 1) A hash table entry with the preferred locale&platform
855
+ // 2) NULL
856
+ // In case there are multiple items with the same locale&platform,
857
+ // we need to return the last one. This is because it must correspond to SFileOpenFileEx
858
+ static TMPQHash * GetHashEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale)
859
+ {
860
+ TMPQHash * pFirstHash = GetFirstHashEntry(ha, szFileName);
861
+ TMPQHash * pBestHash = NULL;
862
+ TMPQHash * pHash = pFirstHash;
863
+ USHORT Locale = SFILE_LOCALE(lcFileLocale);
864
+ BYTE Platform = SFILE_PLATFORM(lcFileLocale);
865
+
866
+ // Parse the found hashes
867
+ while(pHash != NULL)
868
+ {
869
+ // If the locales match, we remember this one as the best one
870
+ if(pHash->Locale == Locale && pHash->Platform == Platform)
871
+ pBestHash = pHash;
872
+
873
+ // Get the next hash entry for that file
874
+ pHash = GetNextHashEntry(ha, pFirstHash, pHash);
875
+ }
876
+
877
+ // Return the best hash or NULL
878
+ return pBestHash;
879
+ }
880
+
881
+ // Defragment the file table so it does not contain any gaps
882
+ // Note: As long as all values of all TMPQHash::dwBlockIndex
883
+ // are not HASH_ENTRY_FREE, the startup search index does not matter.
884
+ // Hash table is circular, so as long as there is no terminator,
885
+ // all entries will be found.
886
+ /*
887
+ static TMPQHash * DefragmentHashTable(
888
+ TMPQArchive * ha,
889
+ TMPQHash * pHashTable,
890
+ TMPQBlock * pBlockTable)
891
+ {
892
+ TMPQHeader * pHeader = ha->pHeader;
893
+ TMPQHash * pHashTableEnd = pHashTable + pHeader->dwHashTableSize;
894
+ TMPQHash * pSource = pHashTable;
895
+ TMPQHash * pTarget = pHashTable;
896
+ DWORD dwFirstFreeEntry;
897
+ DWORD dwNewTableSize;
898
+
899
+ // Sanity checks
900
+ assert(pHeader->wFormatVersion == MPQ_FORMAT_VERSION_1);
901
+ assert(pHeader->HiBlockTablePos64 == 0);
902
+
903
+ // Parse the hash table and move the entries to the begin of it
904
+ for(pSource = pHashTable; pSource < pHashTableEnd; pSource++)
905
+ {
906
+ // Check whether this is a valid hash table entry
907
+ if(IsValidHashEntry1(ha, pSource, pBlockTable))
908
+ {
909
+ // Copy the hash table entry back
910
+ if(pSource > pTarget)
911
+ pTarget[0] = pSource[0];
912
+
913
+ // Move the target
914
+ pTarget++;
915
+ }
916
+ }
917
+
918
+ // Calculate how many entries in the hash table we really need
919
+ dwFirstFreeEntry = (DWORD)(pTarget - pHashTable);
920
+ dwNewTableSize = GetNearestPowerOfTwo(dwFirstFreeEntry);
921
+
922
+ // Fill the rest with entries that look like deleted
923
+ pHashTableEnd = pHashTable + dwNewTableSize;
924
+ pSource = pHashTable + dwFirstFreeEntry;
925
+ memset(pSource, 0xFF, (dwNewTableSize - dwFirstFreeEntry) * sizeof(TMPQHash));
926
+
927
+ // Mark the block indexes as deleted
928
+ for(; pSource < pHashTableEnd; pSource++)
929
+ pSource->dwBlockIndex = HASH_ENTRY_DELETED;
930
+
931
+ // Free some of the space occupied by the hash table
932
+ if(dwNewTableSize < pHeader->dwHashTableSize)
933
+ {
934
+ pHashTable = STORM_REALLOC(TMPQHash, pHashTable, dwNewTableSize);
935
+ ha->pHeader->BlockTableSize64 = dwNewTableSize * sizeof(TMPQHash);
936
+ ha->pHeader->dwHashTableSize = dwNewTableSize;
937
+ }
938
+
939
+ return pHashTable;
940
+ }
941
+ */
942
+
943
+ static DWORD BuildFileTableFromBlockTable(
944
+ TMPQArchive * ha,
945
+ TMPQBlock * pBlockTable)
946
+ {
947
+ TFileEntry * pFileEntry;
948
+ TMPQHeader * pHeader = ha->pHeader;
949
+ TMPQBlock * pBlock;
950
+ TMPQHash * pHashTableEnd;
951
+ TMPQHash * pHash;
952
+ LPDWORD DefragmentTable = NULL;
953
+ DWORD dwItemCount = 0;
954
+
955
+ // Sanity checks
956
+ assert(ha->pFileTable != NULL);
957
+ assert(ha->dwFileTableSize >= ha->dwMaxFileCount);
958
+
959
+ //
960
+ // Defragmentation of the hash table was removed. The reason is a MPQ protector,
961
+ // two hash entries with the same name, where only the second one is valid.
962
+ // The index of the first entry (HashString(szFileName, 0)) points to the second one:
963
+ //
964
+ // NameA NameB BlkIdx Name
965
+ // B701656E FCFB1EED 0000001C staredit\scenario.chk (correct one)
966
+ // --> B701656E FCFB1EED 0000001D staredit\scenario.chk (corrupt one)
967
+ //
968
+ // Defragmenting the hash table corrupts the order and "staredit\scenario.chk" can't be read
969
+ // Example MPQ: MPQ_2022_v1_Sniper.scx
970
+ //
971
+
972
+ //if(ha->dwFlags & MPQ_FLAG_HASH_TABLE_CUT)
973
+ //{
974
+ // ha->pHashTable = DefragmentHashTable(ha, ha->pHashTable, pBlockTable);
975
+ // ha->dwMaxFileCount = pHeader->dwHashTableSize;
976
+ //}
977
+
978
+ // If the hash table or block table is cut,
979
+ // we will defragment the block table
980
+ if(ha->dwFlags & (MPQ_FLAG_HASH_TABLE_CUT | MPQ_FLAG_BLOCK_TABLE_CUT))
981
+ {
982
+ // Sanity checks
983
+ assert(pHeader->HiBlockTablePos64 == 0);
984
+
985
+ // Allocate the translation table
986
+ DefragmentTable = STORM_ALLOC(DWORD, pHeader->dwBlockTableSize);
987
+ if(DefragmentTable == NULL)
988
+ return ERROR_NOT_ENOUGH_MEMORY;
989
+
990
+ // Fill the translation table
991
+ memset(DefragmentTable, 0xFF, pHeader->dwBlockTableSize * sizeof(DWORD));
992
+ }
993
+
994
+ // Parse the entire hash table
995
+ pHashTableEnd = ha->pHashTable + pHeader->dwHashTableSize;
996
+ for(pHash = ha->pHashTable; pHash < pHashTableEnd; pHash++)
997
+ {
998
+ //
999
+ // We need to properly handle these cases:
1000
+ // - Multiple hash entries (same file name) point to the same block entry
1001
+ // - Multiple hash entries (different file name) point to the same block entry
1002
+ //
1003
+ // Ignore all hash table entries where:
1004
+ // - Block Index >= BlockTableSize
1005
+ // - Flags of the appropriate block table entry
1006
+ //
1007
+
1008
+ if(IsValidHashEntry1(ha, pHash, pBlockTable))
1009
+ {
1010
+ DWORD dwOldIndex = MPQ_BLOCK_INDEX(pHash);
1011
+ DWORD dwNewIndex = MPQ_BLOCK_INDEX(pHash);
1012
+
1013
+ // Determine the new block index
1014
+ if(DefragmentTable != NULL)
1015
+ {
1016
+ // Need to handle case when multiple hash
1017
+ // entries point to the same block entry
1018
+ if(DefragmentTable[dwOldIndex] == HASH_ENTRY_FREE)
1019
+ {
1020
+ DefragmentTable[dwOldIndex] = dwItemCount;
1021
+ dwNewIndex = dwItemCount++;
1022
+ }
1023
+ else
1024
+ {
1025
+ dwNewIndex = DefragmentTable[dwOldIndex];
1026
+ }
1027
+
1028
+ // Fix the pointer in the hash entry
1029
+ pHash->dwBlockIndex = dwNewIndex;
1030
+
1031
+ // Dump the relocation entry
1032
+ // printf("Relocating hash entry %08X-%08X: %08X -> %08X\n", pHash->dwName1, pHash->dwName2, dwBlockIndex, dwNewIndex);
1033
+ }
1034
+
1035
+ // Get the pointer to the file entry and the block entry
1036
+ pFileEntry = ha->pFileTable + dwNewIndex;
1037
+ pBlock = pBlockTable + dwOldIndex;
1038
+
1039
+ // ByteOffset is only valid if file size is not zero
1040
+ pFileEntry->ByteOffset = pBlock->dwFilePos;
1041
+ if(pFileEntry->ByteOffset == 0 && pBlock->dwFSize == 0)
1042
+ pFileEntry->ByteOffset = ha->pHeader->dwHeaderSize;
1043
+
1044
+ // Clear file flags that are unknown to this type of map.
1045
+ pFileEntry->dwFlags = pBlock->dwFlags & ha->dwValidFileFlags;
1046
+
1047
+ // Fill the rest of the file entry
1048
+ pFileEntry->dwFileSize = pBlock->dwFSize;
1049
+ pFileEntry->dwCmpSize = pBlock->dwCSize;
1050
+ }
1051
+ }
1052
+
1053
+ // Free the translation table
1054
+ if(DefragmentTable != NULL)
1055
+ {
1056
+ // If we defragmented the block table in the process,
1057
+ // free some memory by shrinking the file table
1058
+ if(ha->dwFileTableSize > ha->dwMaxFileCount)
1059
+ {
1060
+ ha->pFileTable = STORM_REALLOC(TFileEntry, ha->pFileTable, ha->dwMaxFileCount);
1061
+ ha->pHeader->BlockTableSize64 = ha->dwMaxFileCount * sizeof(TMPQBlock);
1062
+ ha->pHeader->dwBlockTableSize = ha->dwMaxFileCount;
1063
+ ha->dwFileTableSize = ha->dwMaxFileCount;
1064
+ }
1065
+
1066
+ // DumpFileTable(ha->pFileTable, ha->dwFileTableSize);
1067
+
1068
+ // Free the translation table
1069
+ STORM_FREE(DefragmentTable);
1070
+ }
1071
+
1072
+ return ERROR_SUCCESS;
1073
+ }
1074
+
1075
+ static TMPQHash * TranslateHashTable(
1076
+ TMPQArchive * ha,
1077
+ ULONGLONG * pcbTableSize)
1078
+ {
1079
+ TMPQHash * pHashTable;
1080
+ size_t HashTableSize;
1081
+
1082
+ // Allocate copy of the hash table
1083
+ pHashTable = STORM_ALLOC(TMPQHash, ha->pHeader->dwHashTableSize);
1084
+ if(pHashTable != NULL)
1085
+ {
1086
+ // Copy the hash table
1087
+ HashTableSize = sizeof(TMPQHash) * ha->pHeader->dwHashTableSize;
1088
+ memcpy(pHashTable, ha->pHashTable, HashTableSize);
1089
+
1090
+ // Give the size to the caller
1091
+ if(pcbTableSize != NULL)
1092
+ {
1093
+ *pcbTableSize = (ULONGLONG)HashTableSize;
1094
+ }
1095
+ }
1096
+
1097
+ return pHashTable;
1098
+ }
1099
+
1100
+ // Also used in SFileGetFileInfo
1101
+ TMPQBlock * TranslateBlockTable(
1102
+ TMPQArchive * ha,
1103
+ ULONGLONG * pcbTableSize,
1104
+ bool * pbNeedHiBlockTable)
1105
+ {
1106
+ TFileEntry * pFileEntry = ha->pFileTable;
1107
+ TMPQBlock * pBlockTable;
1108
+ TMPQBlock * pBlock;
1109
+ DWORD NeedHiBlockTable = 0;
1110
+ DWORD dwBlockTableSize = ha->pHeader->dwBlockTableSize;
1111
+
1112
+ // Allocate copy of the hash table
1113
+ pBlockTable = pBlock = STORM_ALLOC(TMPQBlock, dwBlockTableSize);
1114
+ if(pBlockTable != NULL)
1115
+ {
1116
+ // Convert the block table
1117
+ for(DWORD i = 0; i < dwBlockTableSize; i++)
1118
+ {
1119
+ NeedHiBlockTable |= (DWORD)(pFileEntry->ByteOffset >> 32);
1120
+ pBlock->dwFilePos = (DWORD)pFileEntry->ByteOffset;
1121
+ pBlock->dwFSize = pFileEntry->dwFileSize;
1122
+ pBlock->dwCSize = pFileEntry->dwCmpSize;
1123
+ pBlock->dwFlags = pFileEntry->dwFlags;
1124
+
1125
+ pFileEntry++;
1126
+ pBlock++;
1127
+ }
1128
+
1129
+ // Give the size to the caller
1130
+ if(pcbTableSize != NULL)
1131
+ *pcbTableSize = (ULONGLONG)dwBlockTableSize * sizeof(TMPQBlock);
1132
+
1133
+ if(pbNeedHiBlockTable != NULL)
1134
+ *pbNeedHiBlockTable = NeedHiBlockTable ? true : false;
1135
+ }
1136
+
1137
+ return pBlockTable;
1138
+ }
1139
+
1140
+ static USHORT * TranslateHiBlockTable(
1141
+ TMPQArchive * ha,
1142
+ ULONGLONG * pcbTableSize)
1143
+ {
1144
+ TFileEntry * pFileEntry = ha->pFileTable;
1145
+ USHORT * pHiBlockTable;
1146
+ USHORT * pHiBlock;
1147
+ DWORD dwBlockTableSize = ha->pHeader->dwBlockTableSize;
1148
+
1149
+ // Allocate copy of the hash table
1150
+ pHiBlockTable = pHiBlock = STORM_ALLOC(USHORT, dwBlockTableSize);
1151
+ if(pHiBlockTable != NULL)
1152
+ {
1153
+ // Copy the block table
1154
+ for(DWORD i = 0; i < dwBlockTableSize; i++)
1155
+ pHiBlock[i] = (USHORT)(pFileEntry[i].ByteOffset >> 0x20);
1156
+
1157
+ // Give the size to the caller
1158
+ if(pcbTableSize != NULL)
1159
+ *pcbTableSize = (ULONGLONG)dwBlockTableSize * sizeof(USHORT);
1160
+ }
1161
+
1162
+ return pHiBlockTable;
1163
+ }
1164
+
1165
+ //-----------------------------------------------------------------------------
1166
+ // General EXT table functions
1167
+
1168
+ TMPQExtHeader * LoadExtTable(
1169
+ TMPQArchive * ha,
1170
+ ULONGLONG ByteOffset,
1171
+ size_t Size,
1172
+ DWORD dwSignature,
1173
+ DWORD dwKey)
1174
+ {
1175
+ TMPQExtHeader * pCompressed = NULL; // Compressed table
1176
+ TMPQExtHeader * pExtTable = NULL; // Uncompressed table
1177
+
1178
+ // Do nothing if the size is zero
1179
+ if(ByteOffset != 0 && Size != 0)
1180
+ {
1181
+ // Allocate size for the compressed table
1182
+ pExtTable = (TMPQExtHeader *)STORM_ALLOC(BYTE, Size);
1183
+ if(pExtTable != NULL)
1184
+ {
1185
+ // Load the table from the MPQ
1186
+ ByteOffset += ha->MpqPos;
1187
+ if(!FileStream_Read(ha->pStream, &ByteOffset, pExtTable, (DWORD)Size))
1188
+ {
1189
+ STORM_FREE(pExtTable);
1190
+ return NULL;
1191
+ }
1192
+
1193
+ // Swap the ext table header
1194
+ BSWAP_ARRAY32_UNSIGNED(pExtTable, sizeof(TMPQExtHeader));
1195
+ if(pExtTable->dwSignature != dwSignature)
1196
+ {
1197
+ STORM_FREE(pExtTable);
1198
+ return NULL;
1199
+ }
1200
+
1201
+ // Decrypt the block
1202
+ BSWAP_ARRAY32_UNSIGNED(pExtTable + 1, pExtTable->dwDataSize);
1203
+ DecryptMpqBlock(pExtTable + 1, (DWORD)(Size - sizeof(TMPQExtHeader)), dwKey);
1204
+ BSWAP_ARRAY32_UNSIGNED(pExtTable + 1, pExtTable->dwDataSize);
1205
+
1206
+ // If the table is compressed, decompress it
1207
+ if((pExtTable->dwDataSize + sizeof(TMPQExtHeader)) > Size)
1208
+ {
1209
+ pCompressed = pExtTable;
1210
+ pExtTable = (TMPQExtHeader *)STORM_ALLOC(BYTE, sizeof(TMPQExtHeader) + pCompressed->dwDataSize);
1211
+ if(pExtTable != NULL)
1212
+ {
1213
+ int cbOutBuffer = (int)pCompressed->dwDataSize;
1214
+ int cbInBuffer = (int)Size;
1215
+
1216
+ // Decompress the extended table
1217
+ pExtTable->dwSignature = pCompressed->dwSignature;
1218
+ pExtTable->dwVersion = pCompressed->dwVersion;
1219
+ pExtTable->dwDataSize = pCompressed->dwDataSize;
1220
+ if(!SCompDecompress2(pExtTable + 1, &cbOutBuffer, pCompressed + 1, cbInBuffer))
1221
+ {
1222
+ STORM_FREE(pExtTable);
1223
+ pExtTable = NULL;
1224
+ }
1225
+ }
1226
+
1227
+ // Free the compressed block
1228
+ STORM_FREE(pCompressed);
1229
+ }
1230
+ }
1231
+ }
1232
+
1233
+ // Return the decompressed table to the caller
1234
+ return pExtTable;
1235
+ }
1236
+
1237
+ static DWORD SaveMpqTable(
1238
+ TMPQArchive * ha,
1239
+ void * pMpqTable,
1240
+ ULONGLONG ByteOffset,
1241
+ size_t Size,
1242
+ unsigned char * md5,
1243
+ DWORD dwKey,
1244
+ bool bCompress)
1245
+ {
1246
+ ULONGLONG FileOffset;
1247
+ void * pCompressed = NULL;
1248
+ DWORD dwErrCode = ERROR_SUCCESS;
1249
+
1250
+ // Do we have to compress the table?
1251
+ if(bCompress)
1252
+ {
1253
+ int cbOutBuffer = (int)Size;
1254
+ int cbInBuffer = (int)Size;
1255
+
1256
+ // Allocate extra space for compressed table
1257
+ pCompressed = STORM_ALLOC(BYTE, Size);
1258
+ if(pCompressed == NULL)
1259
+ return ERROR_NOT_ENOUGH_MEMORY;
1260
+
1261
+ // Compress the table
1262
+ SCompCompress(pCompressed, &cbOutBuffer, pMpqTable, cbInBuffer, MPQ_COMPRESSION_ZLIB, 0, 0);
1263
+
1264
+ // If the compression failed, revert it. Otherwise, swap the tables
1265
+ if(cbOutBuffer >= cbInBuffer)
1266
+ {
1267
+ STORM_FREE(pCompressed);
1268
+ pCompressed = NULL;
1269
+ }
1270
+ else
1271
+ {
1272
+ pMpqTable = pCompressed;
1273
+ }
1274
+ }
1275
+
1276
+ // Encrypt the table
1277
+ if(dwKey != 0)
1278
+ {
1279
+ BSWAP_ARRAY32_UNSIGNED(pMpqTable, Size);
1280
+ EncryptMpqBlock(pMpqTable, (DWORD)Size, dwKey);
1281
+ BSWAP_ARRAY32_UNSIGNED(pMpqTable, Size);
1282
+ }
1283
+
1284
+ // Calculate the MD5
1285
+ if(md5 != NULL)
1286
+ {
1287
+ CalculateDataBlockHash(pMpqTable, (DWORD)Size, md5);
1288
+ }
1289
+
1290
+ // Save the table to the MPQ
1291
+ BSWAP_ARRAY32_UNSIGNED(pMpqTable, Size);
1292
+ FileOffset = ha->MpqPos + ByteOffset;
1293
+ if(!FileStream_Write(ha->pStream, &FileOffset, pMpqTable, (DWORD)Size))
1294
+ dwErrCode = GetLastError();
1295
+
1296
+ // Free the compressed table, if any
1297
+ if(pCompressed != NULL)
1298
+ STORM_FREE(pCompressed);
1299
+ return dwErrCode;
1300
+ }
1301
+
1302
+ static DWORD SaveExtTable(
1303
+ TMPQArchive * ha,
1304
+ TMPQExtHeader * pExtTable,
1305
+ ULONGLONG ByteOffset,
1306
+ DWORD dwTableSize,
1307
+ unsigned char * md5,
1308
+ DWORD dwKey,
1309
+ bool bCompress,
1310
+ LPDWORD pcbTotalSize)
1311
+ {
1312
+ ULONGLONG FileOffset;
1313
+ TMPQExtHeader * pCompressed = NULL;
1314
+ DWORD cbTotalSize = 0;
1315
+ DWORD dwErrCode = ERROR_SUCCESS;
1316
+
1317
+ // Do we have to compress the table?
1318
+ if(bCompress)
1319
+ {
1320
+ int cbOutBuffer = (int)dwTableSize;
1321
+ int cbInBuffer = (int)dwTableSize;
1322
+
1323
+ // Allocate extra space for compressed table
1324
+ pCompressed = (TMPQExtHeader *)STORM_ALLOC(BYTE, dwTableSize);
1325
+ if(pCompressed == NULL)
1326
+ return ERROR_NOT_ENOUGH_MEMORY;
1327
+
1328
+ // Compress the table
1329
+ pCompressed->dwSignature = pExtTable->dwSignature;
1330
+ pCompressed->dwVersion = pExtTable->dwVersion;
1331
+ pCompressed->dwDataSize = pExtTable->dwDataSize;
1332
+ SCompCompress((pCompressed + 1), &cbOutBuffer, (pExtTable + 1), cbInBuffer, MPQ_COMPRESSION_ZLIB, 0, 0);
1333
+
1334
+ // If the compression failed, revert it. Otherwise, swap the tables
1335
+ if(cbOutBuffer >= cbInBuffer)
1336
+ {
1337
+ STORM_FREE(pCompressed);
1338
+ pCompressed = NULL;
1339
+ }
1340
+ else
1341
+ {
1342
+ pExtTable = pCompressed;
1343
+ }
1344
+ }
1345
+
1346
+ // Encrypt the table
1347
+ if(dwKey != 0)
1348
+ {
1349
+ BSWAP_ARRAY32_UNSIGNED(pExtTable + 1, pExtTable->dwDataSize);
1350
+ EncryptMpqBlock(pExtTable + 1, (DWORD)(dwTableSize - sizeof(TMPQExtHeader)), dwKey);
1351
+ BSWAP_ARRAY32_UNSIGNED(pExtTable + 1, pExtTable->dwDataSize);
1352
+ }
1353
+
1354
+ // Calculate the MD5 of the table after
1355
+ if(md5 != NULL)
1356
+ {
1357
+ CalculateDataBlockHash(pExtTable, dwTableSize, md5);
1358
+ }
1359
+
1360
+ // Save the table to the MPQ
1361
+ FileOffset = ha->MpqPos + ByteOffset;
1362
+ if(FileStream_Write(ha->pStream, &FileOffset, pExtTable, dwTableSize))
1363
+ cbTotalSize += dwTableSize;
1364
+ else
1365
+ dwErrCode = GetLastError();
1366
+
1367
+ // We have to write raw data MD5
1368
+ if(dwErrCode == ERROR_SUCCESS && ha->pHeader->dwRawChunkSize != 0)
1369
+ {
1370
+ dwErrCode = WriteMemDataMD5(ha->pStream,
1371
+ FileOffset,
1372
+ pExtTable,
1373
+ dwTableSize,
1374
+ ha->pHeader->dwRawChunkSize,
1375
+ &cbTotalSize);
1376
+ }
1377
+
1378
+ // Give the total written size, if needed
1379
+ if(pcbTotalSize != NULL)
1380
+ *pcbTotalSize = cbTotalSize;
1381
+
1382
+ // Free the compressed table, if any
1383
+ if(pCompressed != NULL)
1384
+ STORM_FREE(pCompressed);
1385
+ return dwErrCode;
1386
+ }
1387
+
1388
+ //-----------------------------------------------------------------------------
1389
+ // Support for HET table
1390
+
1391
+ static void CreateHetHeader(
1392
+ TMPQHetTable * pHetTable,
1393
+ TMPQHetHeader * pHetHeader)
1394
+ {
1395
+ // Fill the common header
1396
+ pHetHeader->ExtHdr.dwSignature = HET_TABLE_SIGNATURE;
1397
+ pHetHeader->ExtHdr.dwVersion = 1;
1398
+ pHetHeader->ExtHdr.dwDataSize = 0;
1399
+
1400
+ // Fill the HET header
1401
+ pHetHeader->dwEntryCount = pHetTable->dwEntryCount;
1402
+ pHetHeader->dwTotalCount = pHetTable->dwTotalCount;
1403
+ pHetHeader->dwNameHashBitSize = pHetTable->dwNameHashBitSize;
1404
+ pHetHeader->dwIndexSizeTotal = pHetTable->dwIndexSizeTotal;
1405
+ pHetHeader->dwIndexSizeExtra = pHetTable->dwIndexSizeExtra;
1406
+ pHetHeader->dwIndexSize = pHetTable->dwIndexSize;
1407
+ pHetHeader->dwIndexTableSize = ((pHetHeader->dwIndexSizeTotal * pHetTable->dwTotalCount) + 7) / 8;
1408
+
1409
+ // Calculate the total size needed for holding HET table
1410
+ pHetHeader->ExtHdr.dwDataSize =
1411
+ pHetHeader->dwTableSize = sizeof(TMPQHetHeader) - sizeof(TMPQExtHeader) +
1412
+ pHetHeader->dwTotalCount +
1413
+ pHetHeader->dwIndexTableSize;
1414
+ }
1415
+
1416
+ TMPQHetTable * CreateHetTable(DWORD dwEntryCount, DWORD dwTotalCount, DWORD dwNameHashBitSize, LPBYTE pbSrcData)
1417
+ {
1418
+ TMPQHetTable * pHetTable;
1419
+
1420
+ pHetTable = STORM_ALLOC(TMPQHetTable, 1);
1421
+ if(pHetTable != NULL)
1422
+ {
1423
+ // Zero the HET table
1424
+ memset(pHetTable, 0, sizeof(TMPQHetTable));
1425
+
1426
+ // Hash sizes less than 0x40 bits are not tested
1427
+ assert(dwNameHashBitSize == 0x40);
1428
+
1429
+ // Calculate masks
1430
+ pHetTable->AndMask64 = ((dwNameHashBitSize != 0x40) ? ((ULONGLONG)1 << dwNameHashBitSize) : 0) - 1;
1431
+ pHetTable->OrMask64 = (ULONGLONG)1 << (dwNameHashBitSize - 1);
1432
+
1433
+ // If the total count is not entered, use default
1434
+ if(dwTotalCount == 0)
1435
+ dwTotalCount = (dwEntryCount * 4) / 3;
1436
+
1437
+ // Store the HET table parameters
1438
+ pHetTable->dwEntryCount = dwEntryCount;
1439
+ pHetTable->dwTotalCount = dwTotalCount;
1440
+ pHetTable->dwNameHashBitSize = dwNameHashBitSize;
1441
+ pHetTable->dwIndexSizeTotal = GetNecessaryBitCount(dwEntryCount);
1442
+ pHetTable->dwIndexSizeExtra = 0;
1443
+ pHetTable->dwIndexSize = pHetTable->dwIndexSizeTotal;
1444
+
1445
+ // Allocate array of hashes
1446
+ pHetTable->pNameHashes = STORM_ALLOC(BYTE, dwTotalCount);
1447
+ if(pHetTable->pNameHashes != NULL)
1448
+ {
1449
+ // Make sure the data are initialized
1450
+ memset(pHetTable->pNameHashes, 0, dwTotalCount);
1451
+
1452
+ // Allocate the bit array for file indexes
1453
+ pHetTable->pBetIndexes = TMPQBits::Create(dwTotalCount * pHetTable->dwIndexSizeTotal, 0xFF);
1454
+ if(pHetTable->pBetIndexes != NULL)
1455
+ {
1456
+ // Initialize the HET table from the source data (if given)
1457
+ if(pbSrcData != NULL)
1458
+ {
1459
+ // Copy the name hashes
1460
+ memcpy(pHetTable->pNameHashes, pbSrcData, dwTotalCount);
1461
+
1462
+ // Copy the file indexes
1463
+ memcpy(pHetTable->pBetIndexes->Elements, pbSrcData + dwTotalCount, pHetTable->pBetIndexes->NumberOfBytes);
1464
+ }
1465
+
1466
+ // Return the result HET table
1467
+ return pHetTable;
1468
+ }
1469
+
1470
+ // Free the name hashes
1471
+ STORM_FREE(pHetTable->pNameHashes);
1472
+ }
1473
+
1474
+ STORM_FREE(pHetTable);
1475
+ }
1476
+
1477
+ // Failed
1478
+ return NULL;
1479
+ }
1480
+
1481
+ static DWORD InsertHetEntry(TMPQHetTable * pHetTable, ULONGLONG FileNameHash, DWORD dwFileIndex)
1482
+ {
1483
+ DWORD StartIndex;
1484
+ DWORD Index;
1485
+ BYTE NameHash1;
1486
+
1487
+ // Get the start index and the high 8 bits of the name hash
1488
+ StartIndex = Index = (DWORD)(FileNameHash % pHetTable->dwTotalCount);
1489
+ NameHash1 = (BYTE)(FileNameHash >> (pHetTable->dwNameHashBitSize - 8));
1490
+
1491
+ // Find a place where to put it
1492
+ for(;;)
1493
+ {
1494
+ // Did we find a free HET entry?
1495
+ if(pHetTable->pNameHashes[Index] == HET_ENTRY_FREE)
1496
+ {
1497
+ // Set the entry in the name hash table
1498
+ pHetTable->pNameHashes[Index] = NameHash1;
1499
+
1500
+ // Set the entry in the file index table
1501
+ pHetTable->pBetIndexes->SetBits(pHetTable->dwIndexSizeTotal * Index,
1502
+ pHetTable->dwIndexSize,
1503
+ &dwFileIndex,
1504
+ 4);
1505
+ return ERROR_SUCCESS;
1506
+ }
1507
+
1508
+ // Move to the next entry in the HET table
1509
+ // If we came to the start index again, we are done
1510
+ Index = (Index + 1) % pHetTable->dwTotalCount;
1511
+ if(Index == StartIndex)
1512
+ break;
1513
+ }
1514
+
1515
+ // No space in the HET table. Should never happen,
1516
+ // because the HET table is created according to the number of files
1517
+ assert(false);
1518
+ return ERROR_DISK_FULL;
1519
+ }
1520
+
1521
+ static TMPQHetTable * TranslateHetTable(TMPQHetHeader * pHetHeader)
1522
+ {
1523
+ TMPQHetTable * pHetTable = NULL;
1524
+ LPBYTE pbSrcData = (LPBYTE)(pHetHeader + 1);
1525
+
1526
+ // Sanity check
1527
+ assert(pHetHeader->ExtHdr.dwSignature == HET_TABLE_SIGNATURE);
1528
+ assert(pHetHeader->ExtHdr.dwVersion == 1);
1529
+
1530
+ // Verify size of the HET table
1531
+ if(pHetHeader->ExtHdr.dwDataSize >= (sizeof(TMPQHetHeader) - sizeof(TMPQExtHeader)))
1532
+ {
1533
+ // Verify the size of the table in the header
1534
+ if(pHetHeader->ExtHdr.dwDataSize >= pHetHeader->dwTableSize)
1535
+ {
1536
+ // The size of the HET table must be sum of header, hash and index table size
1537
+ if((sizeof(TMPQHetHeader) - sizeof(TMPQExtHeader) + pHetHeader->dwTotalCount + pHetHeader->dwIndexTableSize) == pHetHeader->dwTableSize)
1538
+ {
1539
+ // So far, all MPQs with HET Table have had total number of entries equal to 4/3 of file count
1540
+ // Exception: "2010 - Starcraft II\!maps\Tya's Zerg Defense (unprotected).SC2Map"
1541
+ // assert(((pHetHeader->dwEntryCount * 4) / 3) == pHetHeader->dwTotalCount);
1542
+
1543
+ // The size of one index is predictable as well
1544
+ assert(GetNecessaryBitCount(pHetHeader->dwEntryCount) == pHetHeader->dwIndexSizeTotal);
1545
+
1546
+ // The size of index table (in entries) is expected
1547
+ // to be the same like the hash table size (in bytes)
1548
+ assert(((pHetHeader->dwTotalCount * pHetHeader->dwIndexSizeTotal) + 7) / 8 == pHetHeader->dwIndexTableSize);
1549
+
1550
+ // Create translated table
1551
+ pHetTable = CreateHetTable(pHetHeader->dwEntryCount, pHetHeader->dwTotalCount, pHetHeader->dwNameHashBitSize, pbSrcData);
1552
+ if(pHetTable != NULL)
1553
+ {
1554
+ // Now the sizes in the hash table should be already set
1555
+ assert(pHetTable->dwEntryCount == pHetHeader->dwEntryCount);
1556
+ assert(pHetTable->dwTotalCount == pHetHeader->dwTotalCount);
1557
+ assert(pHetTable->dwIndexSizeTotal == pHetHeader->dwIndexSizeTotal);
1558
+
1559
+ // Copy the missing variables
1560
+ pHetTable->dwIndexSizeExtra = pHetHeader->dwIndexSizeExtra;
1561
+ pHetTable->dwIndexSize = pHetHeader->dwIndexSize;
1562
+ }
1563
+ }
1564
+ }
1565
+ }
1566
+
1567
+ return pHetTable;
1568
+ }
1569
+
1570
+ static TMPQExtHeader * TranslateHetTable(TMPQHetTable * pHetTable, ULONGLONG * pcbHetTable)
1571
+ {
1572
+ TMPQHetHeader * pHetHeader = NULL;
1573
+ TMPQHetHeader HetHeader;
1574
+ LPBYTE pbLinearTable = NULL;
1575
+ LPBYTE pbTrgData;
1576
+
1577
+ // Prepare header of the HET table
1578
+ CreateHetHeader(pHetTable, &HetHeader);
1579
+
1580
+ // Allocate space for the linear table
1581
+ pbLinearTable = STORM_ALLOC(BYTE, sizeof(TMPQExtHeader) + HetHeader.dwTableSize);
1582
+ if(pbLinearTable != NULL)
1583
+ {
1584
+ // Copy the table header
1585
+ pHetHeader = (TMPQHetHeader *)pbLinearTable;
1586
+ memcpy(pHetHeader, &HetHeader, sizeof(TMPQHetHeader));
1587
+ pbTrgData = (LPBYTE)(pHetHeader + 1);
1588
+
1589
+ // Copy the array of name hashes
1590
+ memcpy(pbTrgData, pHetTable->pNameHashes, pHetTable->dwTotalCount);
1591
+ pbTrgData += pHetTable->dwTotalCount;
1592
+
1593
+ // Copy the bit array of BET indexes
1594
+ memcpy(pbTrgData, pHetTable->pBetIndexes->Elements, HetHeader.dwIndexTableSize);
1595
+
1596
+ // Calculate the total size of the table, including the TMPQExtHeader
1597
+ if(pcbHetTable != NULL)
1598
+ {
1599
+ *pcbHetTable = (ULONGLONG)(sizeof(TMPQExtHeader) + HetHeader.dwTableSize);
1600
+ }
1601
+ }
1602
+
1603
+ // Keep Coverity happy
1604
+ assert((TMPQExtHeader *)&pHetHeader->ExtHdr == (TMPQExtHeader *)pbLinearTable);
1605
+ return (TMPQExtHeader *)pbLinearTable;
1606
+ }
1607
+
1608
+ static DWORD GetFileIndex_Het(TMPQArchive * ha, const char * szFileName)
1609
+ {
1610
+ TMPQHetTable * pHetTable = ha->pHetTable;
1611
+ ULONGLONG FileNameHash;
1612
+ DWORD StartIndex;
1613
+ DWORD Index;
1614
+ BYTE NameHash1; // Upper 8 bits of the masked file name hash
1615
+
1616
+ // If there are no entries in the HET table, do nothing
1617
+ if(pHetTable->dwEntryCount == 0)
1618
+ return HASH_ENTRY_FREE;
1619
+
1620
+ // Do nothing if the MPQ has no HET table
1621
+ assert(ha->pHetTable != NULL);
1622
+
1623
+ // Calculate 64-bit hash of the file name
1624
+ FileNameHash = (HashStringJenkins(szFileName) & pHetTable->AndMask64) | pHetTable->OrMask64;
1625
+
1626
+ // Split the file name hash into two parts:
1627
+ // NameHash1: The highest 8 bits of the name hash
1628
+ // NameHash2: File name hash limited to hash size
1629
+ // Note: Our file table contains full name hash, no need to cut the high 8 bits before comparison
1630
+ NameHash1 = (BYTE)(FileNameHash >> (pHetTable->dwNameHashBitSize - 8));
1631
+
1632
+ // Calculate the starting index to the hash table
1633
+ StartIndex = Index = (DWORD)(FileNameHash % pHetTable->dwTotalCount);
1634
+
1635
+ // Go through HET table until we find a terminator
1636
+ while(pHetTable->pNameHashes[Index] != HET_ENTRY_FREE)
1637
+ {
1638
+ // Did we find a match ?
1639
+ if(pHetTable->pNameHashes[Index] == NameHash1)
1640
+ {
1641
+ DWORD dwFileIndex = 0;
1642
+
1643
+ // Get the file index
1644
+ if(pHetTable->pBetIndexes->GetBits(pHetTable->dwIndexSizeTotal * Index,
1645
+ pHetTable->dwIndexSize,
1646
+ &dwFileIndex,
1647
+ sizeof(DWORD)) == ERROR_SUCCESS)
1648
+ {
1649
+ // Verify the FileNameHash against the entry in the table of name hashes
1650
+ if(dwFileIndex <= ha->dwFileTableSize && ha->pFileTable[dwFileIndex].FileNameHash == FileNameHash)
1651
+ {
1652
+ return dwFileIndex;
1653
+ }
1654
+ }
1655
+ }
1656
+
1657
+ // Move to the next entry in the HET table
1658
+ // If we came to the start index again, we are done
1659
+ Index = (Index + 1) % pHetTable->dwTotalCount;
1660
+ if(Index == StartIndex)
1661
+ break;
1662
+ }
1663
+
1664
+ // File not found
1665
+ return HASH_ENTRY_FREE;
1666
+ }
1667
+
1668
+ void FreeHetTable(TMPQHetTable * pHetTable)
1669
+ {
1670
+ if(pHetTable != NULL)
1671
+ {
1672
+ if(pHetTable->pNameHashes != NULL)
1673
+ STORM_FREE(pHetTable->pNameHashes);
1674
+ if(pHetTable->pBetIndexes != NULL)
1675
+ STORM_FREE(pHetTable->pBetIndexes);
1676
+
1677
+ STORM_FREE(pHetTable);
1678
+ }
1679
+ }
1680
+
1681
+ //-----------------------------------------------------------------------------
1682
+ // Support for BET table
1683
+
1684
+ static bool VerifyBetHeaderSize(TMPQArchive * /* ha */, TMPQBetHeader * pBetHeader)
1685
+ {
1686
+ LPBYTE pbSrcData = (LPBYTE)(pBetHeader + 1);
1687
+ LPBYTE pbSrcEnd = (LPBYTE)(pBetHeader) + pBetHeader->dwTableSize;
1688
+
1689
+ // Move past the flags
1690
+ pbSrcData = pbSrcData + (pBetHeader->dwFlagCount * sizeof(DWORD)) + (pBetHeader->dwEntryCount * pBetHeader->dwTableEntrySize) / 8;
1691
+ return (pbSrcData <= pbSrcEnd);
1692
+ }
1693
+
1694
+ static void CreateBetHeader(
1695
+ TMPQArchive * ha,
1696
+ TMPQBetHeader * pBetHeader)
1697
+ {
1698
+ TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
1699
+ TFileEntry * pFileEntry;
1700
+ ULONGLONG MaxByteOffset = 0;
1701
+ DWORD FlagArray[MAX_FLAG_INDEX];
1702
+ DWORD dwMaxFlagIndex = 0;
1703
+ DWORD dwMaxFileSize = 0;
1704
+ DWORD dwMaxCmpSize = 0;
1705
+ DWORD dwFlagIndex;
1706
+
1707
+ // Initialize array of flag combinations
1708
+ InitFileFlagArray(FlagArray);
1709
+
1710
+ // Fill the common header
1711
+ pBetHeader->ExtHdr.dwSignature = BET_TABLE_SIGNATURE;
1712
+ pBetHeader->ExtHdr.dwVersion = 1;
1713
+ pBetHeader->ExtHdr.dwDataSize = 0;
1714
+
1715
+ // Get the maximum values for the BET table
1716
+ pFileTableEnd = ha->pFileTable + ha->pHeader->dwBlockTableSize;
1717
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
1718
+ {
1719
+ //
1720
+ // Note: Deleted files must be counted as well
1721
+ //
1722
+
1723
+ // Highest file position in the MPQ
1724
+ if(pFileEntry->ByteOffset > MaxByteOffset)
1725
+ MaxByteOffset = pFileEntry->ByteOffset;
1726
+
1727
+ // Biggest file size
1728
+ if(pFileEntry->dwFileSize > dwMaxFileSize)
1729
+ dwMaxFileSize = pFileEntry->dwFileSize;
1730
+
1731
+ // Biggest compressed size
1732
+ if(pFileEntry->dwCmpSize > dwMaxCmpSize)
1733
+ dwMaxCmpSize = pFileEntry->dwCmpSize;
1734
+
1735
+ // Check if this flag was there before
1736
+ dwFlagIndex = GetFileFlagIndex(FlagArray, pFileEntry->dwFlags);
1737
+ if(dwFlagIndex > dwMaxFlagIndex)
1738
+ dwMaxFlagIndex = dwFlagIndex;
1739
+ }
1740
+
1741
+ // Now save bit count for every piece of file information
1742
+ pBetHeader->dwBitIndex_FilePos = 0;
1743
+ pBetHeader->dwBitCount_FilePos = GetNecessaryBitCount(MaxByteOffset);
1744
+
1745
+ pBetHeader->dwBitIndex_FileSize = pBetHeader->dwBitIndex_FilePos + pBetHeader->dwBitCount_FilePos;
1746
+ pBetHeader->dwBitCount_FileSize = GetNecessaryBitCount(dwMaxFileSize);
1747
+
1748
+ pBetHeader->dwBitIndex_CmpSize = pBetHeader->dwBitIndex_FileSize + pBetHeader->dwBitCount_FileSize;
1749
+ pBetHeader->dwBitCount_CmpSize = GetNecessaryBitCount(dwMaxCmpSize);
1750
+
1751
+ pBetHeader->dwBitIndex_FlagIndex = pBetHeader->dwBitIndex_CmpSize + pBetHeader->dwBitCount_CmpSize;
1752
+ pBetHeader->dwBitCount_FlagIndex = GetNecessaryBitCount(dwMaxFlagIndex + 1);
1753
+
1754
+ pBetHeader->dwBitIndex_Unknown = pBetHeader->dwBitIndex_FlagIndex + pBetHeader->dwBitCount_FlagIndex;
1755
+ pBetHeader->dwBitCount_Unknown = 0;
1756
+
1757
+ // Calculate the total size of one entry
1758
+ pBetHeader->dwTableEntrySize = pBetHeader->dwBitCount_FilePos +
1759
+ pBetHeader->dwBitCount_FileSize +
1760
+ pBetHeader->dwBitCount_CmpSize +
1761
+ pBetHeader->dwBitCount_FlagIndex +
1762
+ pBetHeader->dwBitCount_Unknown;
1763
+
1764
+ // Save the file count and flag count
1765
+ pBetHeader->dwEntryCount = ha->pHeader->dwBlockTableSize;
1766
+ pBetHeader->dwFlagCount = dwMaxFlagIndex + 1;
1767
+ pBetHeader->dwUnknown08 = 0x10;
1768
+
1769
+ // Save the total size of the BET hash
1770
+ pBetHeader->dwBitTotal_NameHash2 = ha->pHetTable->dwNameHashBitSize - 0x08;
1771
+ pBetHeader->dwBitExtra_NameHash2 = 0;
1772
+ pBetHeader->dwBitCount_NameHash2 = pBetHeader->dwBitTotal_NameHash2;
1773
+ pBetHeader->dwNameHashArraySize = ((pBetHeader->dwBitTotal_NameHash2 * pBetHeader->dwEntryCount) + 7) / 8;
1774
+
1775
+ // Save the total table size
1776
+ pBetHeader->ExtHdr.dwDataSize =
1777
+ pBetHeader->dwTableSize = sizeof(TMPQBetHeader) - sizeof(TMPQExtHeader) +
1778
+ pBetHeader->dwFlagCount * sizeof(DWORD) +
1779
+ ((pBetHeader->dwTableEntrySize * pBetHeader->dwEntryCount) + 7) / 8 +
1780
+ pBetHeader->dwNameHashArraySize;
1781
+ }
1782
+
1783
+ TMPQBetTable * CreateBetTable(DWORD dwEntryCount)
1784
+ {
1785
+ TMPQBetTable * pBetTable;
1786
+
1787
+ // Allocate BET table
1788
+ pBetTable = STORM_ALLOC(TMPQBetTable, 1);
1789
+ if(pBetTable != NULL)
1790
+ {
1791
+ memset(pBetTable, 0, sizeof(TMPQBetTable));
1792
+ pBetTable->dwEntryCount = dwEntryCount;
1793
+ }
1794
+
1795
+ return pBetTable;
1796
+ }
1797
+
1798
+ static TMPQBetTable * TranslateBetTable(
1799
+ TMPQArchive * ha,
1800
+ TMPQBetHeader * pBetHeader)
1801
+ {
1802
+ TMPQBetTable * pBetTable = NULL;
1803
+ LPBYTE pbSrcData = (LPBYTE)(pBetHeader + 1);
1804
+ DWORD LengthInBytes = 0;
1805
+
1806
+ // Sanity check
1807
+ assert(pBetHeader->ExtHdr.dwSignature == BET_TABLE_SIGNATURE);
1808
+ assert(pBetHeader->ExtHdr.dwVersion == 1);
1809
+ assert(ha->pHetTable != NULL);
1810
+ ha = ha;
1811
+
1812
+ // Verify size of the HET table
1813
+ if(pBetHeader->ExtHdr.dwDataSize >= (sizeof(TMPQBetHeader) - sizeof(TMPQExtHeader)))
1814
+ {
1815
+ // Verify the size of the table in the header
1816
+ if(pBetHeader->ExtHdr.dwDataSize >= pBetHeader->dwTableSize)
1817
+ {
1818
+ // The number of entries in the BET table must be the same like number of entries in the block table
1819
+ // Note: Ignored if there is no block table
1820
+ //assert(pBetHeader->dwEntryCount == ha->pHeader->dwBlockTableSize);
1821
+ assert(pBetHeader->dwEntryCount <= ha->dwMaxFileCount);
1822
+
1823
+ // The number of entries in the BET table must be the same like number of entries in the HET table
1824
+ // Note that if it's not, it is not a problem
1825
+ //assert(pBetHeader->dwEntryCount == ha->pHetTable->dwEntryCount);
1826
+
1827
+ // Verify an obviously-wrong values
1828
+ if(VerifyBetHeaderSize(ha, pBetHeader))
1829
+ {
1830
+ // Create translated table
1831
+ pBetTable = CreateBetTable(pBetHeader->dwEntryCount);
1832
+ if(pBetTable != NULL)
1833
+ {
1834
+ // Copy the variables from the header to the BetTable
1835
+ pBetTable->dwTableEntrySize = pBetHeader->dwTableEntrySize;
1836
+ pBetTable->dwBitIndex_FilePos = pBetHeader->dwBitIndex_FilePos;
1837
+ pBetTable->dwBitIndex_FileSize = pBetHeader->dwBitIndex_FileSize;
1838
+ pBetTable->dwBitIndex_CmpSize = pBetHeader->dwBitIndex_CmpSize;
1839
+ pBetTable->dwBitIndex_FlagIndex = pBetHeader->dwBitIndex_FlagIndex;
1840
+ pBetTable->dwBitIndex_Unknown = pBetHeader->dwBitIndex_Unknown;
1841
+ pBetTable->dwBitCount_FilePos = pBetHeader->dwBitCount_FilePos;
1842
+ pBetTable->dwBitCount_FileSize = pBetHeader->dwBitCount_FileSize;
1843
+ pBetTable->dwBitCount_CmpSize = pBetHeader->dwBitCount_CmpSize;
1844
+ pBetTable->dwBitCount_FlagIndex = pBetHeader->dwBitCount_FlagIndex;
1845
+ pBetTable->dwBitCount_Unknown = pBetHeader->dwBitCount_Unknown;
1846
+
1847
+ // Since we don't know what the "unknown" is, we'll assert when it's zero
1848
+ assert(pBetTable->dwBitCount_Unknown == 0);
1849
+
1850
+ // Allocate array for flags
1851
+ if(pBetHeader->dwFlagCount != 0)
1852
+ {
1853
+ // Allocate array for file flags and load it
1854
+ pBetTable->pFileFlags = STORM_ALLOC(DWORD, pBetHeader->dwFlagCount);
1855
+ if(pBetTable->pFileFlags != NULL)
1856
+ {
1857
+ LengthInBytes = pBetHeader->dwFlagCount * sizeof(DWORD);
1858
+ memcpy(pBetTable->pFileFlags, pbSrcData, LengthInBytes);
1859
+ BSWAP_ARRAY32_UNSIGNED(pBetTable->pFileFlags, LengthInBytes);
1860
+ pbSrcData += LengthInBytes;
1861
+ }
1862
+
1863
+ // Save the number of flags
1864
+ pBetTable->dwFlagCount = pBetHeader->dwFlagCount;
1865
+ }
1866
+
1867
+ // Load the bit-based file table
1868
+ pBetTable->pFileTable = TMPQBits::Create(pBetTable->dwTableEntrySize * pBetHeader->dwEntryCount, 0);
1869
+ if(pBetTable->pFileTable != NULL)
1870
+ {
1871
+ LengthInBytes = (pBetTable->pFileTable->NumberOfBits + 7) / 8;
1872
+ memcpy(pBetTable->pFileTable->Elements, pbSrcData, LengthInBytes);
1873
+ pbSrcData += LengthInBytes;
1874
+ }
1875
+
1876
+ // Fill the sizes of BET hash
1877
+ pBetTable->dwBitTotal_NameHash2 = pBetHeader->dwBitTotal_NameHash2;
1878
+ pBetTable->dwBitExtra_NameHash2 = pBetHeader->dwBitExtra_NameHash2;
1879
+ pBetTable->dwBitCount_NameHash2 = pBetHeader->dwBitCount_NameHash2;
1880
+
1881
+ // Create and load the array of BET hashes
1882
+ pBetTable->pNameHashes = TMPQBits::Create(pBetTable->dwBitTotal_NameHash2 * pBetHeader->dwEntryCount, 0);
1883
+ if(pBetTable->pNameHashes != NULL)
1884
+ {
1885
+ LengthInBytes = (pBetTable->pNameHashes->NumberOfBits + 7) / 8;
1886
+ memcpy(pBetTable->pNameHashes->Elements, pbSrcData, LengthInBytes);
1887
+ // pbSrcData += LengthInBytes;
1888
+ }
1889
+
1890
+ // Dump both tables
1891
+ // DumpHetAndBetTable(ha->pHetTable, pBetTable);
1892
+ }
1893
+ }
1894
+ }
1895
+ }
1896
+
1897
+ return pBetTable;
1898
+ }
1899
+
1900
+ TMPQExtHeader * TranslateBetTable(
1901
+ TMPQArchive * ha,
1902
+ ULONGLONG * pcbBetTable)
1903
+ {
1904
+ TMPQBetHeader * pBetHeader = NULL;
1905
+ TMPQBetHeader BetHeader;
1906
+ TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
1907
+ TFileEntry * pFileEntry;
1908
+ TMPQBits * pBitArray = NULL;
1909
+ LPBYTE pbLinearTable = NULL;
1910
+ LPBYTE pbTrgData;
1911
+ DWORD LengthInBytes;
1912
+ DWORD FlagArray[MAX_FLAG_INDEX];
1913
+
1914
+ // Calculate the bit sizes of various entries
1915
+ InitFileFlagArray(FlagArray);
1916
+ CreateBetHeader(ha, &BetHeader);
1917
+
1918
+ // Allocate space
1919
+ pbLinearTable = STORM_ALLOC(BYTE, sizeof(TMPQExtHeader) + BetHeader.dwTableSize);
1920
+ if(pbLinearTable != NULL)
1921
+ {
1922
+ // Copy the BET header to the linear buffer
1923
+ pBetHeader = (TMPQBetHeader *)pbLinearTable;
1924
+ memcpy(pBetHeader, &BetHeader, sizeof(TMPQBetHeader));
1925
+ pbTrgData = (LPBYTE)(pBetHeader + 1);
1926
+
1927
+ // Save the bit-based block table
1928
+ pBitArray = TMPQBits::Create(BetHeader.dwEntryCount * BetHeader.dwTableEntrySize, 0);
1929
+ if(pBitArray != NULL)
1930
+ {
1931
+ DWORD dwFlagIndex = 0;
1932
+ DWORD nBitOffset = 0;
1933
+
1934
+ // Construct the bit-based file table
1935
+ pFileTableEnd = ha->pFileTable + BetHeader.dwEntryCount;
1936
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
1937
+ {
1938
+ //
1939
+ // Note: Missing files must be included as well
1940
+ //
1941
+
1942
+ // Save the byte offset
1943
+ pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FilePos,
1944
+ BetHeader.dwBitCount_FilePos,
1945
+ &pFileEntry->ByteOffset,
1946
+ 8);
1947
+ pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FileSize,
1948
+ BetHeader.dwBitCount_FileSize,
1949
+ &pFileEntry->dwFileSize,
1950
+ 4);
1951
+ pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_CmpSize,
1952
+ BetHeader.dwBitCount_CmpSize,
1953
+ &pFileEntry->dwCmpSize,
1954
+ 4);
1955
+
1956
+ // Save the flag index
1957
+ dwFlagIndex = GetFileFlagIndex(FlagArray, pFileEntry->dwFlags);
1958
+ pBitArray->SetBits(nBitOffset + BetHeader.dwBitIndex_FlagIndex,
1959
+ BetHeader.dwBitCount_FlagIndex,
1960
+ &dwFlagIndex,
1961
+ 4);
1962
+
1963
+ // Move the bit offset
1964
+ nBitOffset += BetHeader.dwTableEntrySize;
1965
+ }
1966
+
1967
+ // Write the array of flags
1968
+ LengthInBytes = BetHeader.dwFlagCount * sizeof(DWORD);
1969
+ memcpy(pbTrgData, FlagArray, LengthInBytes);
1970
+ BSWAP_ARRAY32_UNSIGNED(pbTrgData, LengthInBytes);
1971
+ pbTrgData += LengthInBytes;
1972
+
1973
+ // Write the bit-based block table
1974
+ LengthInBytes = (pBitArray->NumberOfBits + 7) / 8;
1975
+ memcpy(pbTrgData, pBitArray->Elements, LengthInBytes);
1976
+ pbTrgData += LengthInBytes;
1977
+
1978
+ // Free the bit array
1979
+ STORM_FREE(pBitArray);
1980
+ }
1981
+
1982
+ // Create bit array for name hashes
1983
+ pBitArray = TMPQBits::Create(BetHeader.dwBitTotal_NameHash2 * BetHeader.dwEntryCount, 0);
1984
+ if(pBitArray != NULL)
1985
+ {
1986
+ DWORD dwFileIndex = 0;
1987
+
1988
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
1989
+ {
1990
+ // Insert the name hash to the bit array
1991
+ pBitArray->SetBits(BetHeader.dwBitTotal_NameHash2 * dwFileIndex,
1992
+ BetHeader.dwBitCount_NameHash2,
1993
+ &pFileEntry->FileNameHash,
1994
+ 8);
1995
+
1996
+ assert(dwFileIndex < BetHeader.dwEntryCount);
1997
+ dwFileIndex++;
1998
+ }
1999
+
2000
+ // Write the array of BET hashes
2001
+ LengthInBytes = (pBitArray->NumberOfBits + 7) / 8;
2002
+ memcpy(pbTrgData, pBitArray->Elements, LengthInBytes);
2003
+ // pbTrgData += LengthInBytes;
2004
+
2005
+ // Free the bit array
2006
+ STORM_FREE(pBitArray);
2007
+ }
2008
+
2009
+ // Write the size of the BET table in the MPQ
2010
+ if(pcbBetTable != NULL)
2011
+ {
2012
+ *pcbBetTable = (ULONGLONG)(sizeof(TMPQExtHeader) + BetHeader.dwTableSize);
2013
+ }
2014
+ }
2015
+
2016
+ // Keep Coverity happy
2017
+ assert((TMPQExtHeader *)&pBetHeader->ExtHdr == (TMPQExtHeader *)pbLinearTable);
2018
+ return (TMPQExtHeader *)pbLinearTable;
2019
+ }
2020
+
2021
+ void FreeBetTable(TMPQBetTable * pBetTable)
2022
+ {
2023
+ if(pBetTable != NULL)
2024
+ {
2025
+ if(pBetTable->pFileTable != NULL)
2026
+ STORM_FREE(pBetTable->pFileTable);
2027
+ if(pBetTable->pFileFlags != NULL)
2028
+ STORM_FREE(pBetTable->pFileFlags);
2029
+ if(pBetTable->pNameHashes != NULL)
2030
+ STORM_FREE(pBetTable->pNameHashes);
2031
+
2032
+ STORM_FREE(pBetTable);
2033
+ }
2034
+ }
2035
+
2036
+ //-----------------------------------------------------------------------------
2037
+ // Support for file table
2038
+
2039
+ TFileEntry * GetFileEntryLocale(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex)
2040
+ {
2041
+ TMPQHash * pHash;
2042
+ DWORD dwFileIndex;
2043
+
2044
+ // First, we have to search the classic hash table
2045
+ // This is because on renaming, deleting, or changing locale,
2046
+ // we will need the pointer to hash table entry
2047
+ if(ha->pHashTable != NULL)
2048
+ {
2049
+ pHash = GetHashEntryLocale(ha, szFileName, lcFileLocale);
2050
+ if(pHash != NULL && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
2051
+ {
2052
+ if(PtrHashIndex != NULL)
2053
+ PtrHashIndex[0] = (DWORD)(pHash - ha->pHashTable);
2054
+ return ha->pFileTable + MPQ_BLOCK_INDEX(pHash);
2055
+ }
2056
+ }
2057
+
2058
+ // If we have HET table in the MPQ, try to find the file in HET table
2059
+ if(ha->pHetTable != NULL)
2060
+ {
2061
+ dwFileIndex = GetFileIndex_Het(ha, szFileName);
2062
+ if(dwFileIndex != HASH_ENTRY_FREE)
2063
+ return ha->pFileTable + dwFileIndex;
2064
+ }
2065
+
2066
+ // Not found
2067
+ return NULL;
2068
+ }
2069
+
2070
+ TFileEntry * GetFileEntryExact(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex)
2071
+ {
2072
+ TMPQHash * pHash;
2073
+ DWORD dwFileIndex;
2074
+
2075
+ // If the hash table is present, find the entry from hash table
2076
+ if(ha->pHashTable != NULL)
2077
+ {
2078
+ pHash = GetHashEntryExact(ha, szFileName, lcFileLocale);
2079
+ if(pHash != NULL && MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
2080
+ {
2081
+ if(PtrHashIndex != NULL)
2082
+ PtrHashIndex[0] = (DWORD)(pHash - ha->pHashTable);
2083
+ return ha->pFileTable + MPQ_BLOCK_INDEX(pHash);
2084
+ }
2085
+ }
2086
+
2087
+ // If we have HET table in the MPQ, try to find the file in HET table
2088
+ if(ha->pHetTable != NULL)
2089
+ {
2090
+ dwFileIndex = GetFileIndex_Het(ha, szFileName);
2091
+ if(dwFileIndex != HASH_ENTRY_FREE)
2092
+ {
2093
+ if(PtrHashIndex != NULL)
2094
+ PtrHashIndex[0] = HASH_ENTRY_FREE;
2095
+ return ha->pFileTable + dwFileIndex;
2096
+ }
2097
+ }
2098
+
2099
+ // Not found
2100
+ return NULL;
2101
+ }
2102
+
2103
+ void AllocateFileName(TMPQArchive * ha, TFileEntry * pFileEntry, const char * szFileName)
2104
+ {
2105
+ // Sanity check
2106
+ assert(pFileEntry != NULL);
2107
+
2108
+ // If the file name is pseudo file name, free it at this point
2109
+ if(IsPseudoFileName(pFileEntry->szFileName, NULL))
2110
+ {
2111
+ if(pFileEntry->szFileName != NULL)
2112
+ STORM_FREE(pFileEntry->szFileName);
2113
+ pFileEntry->szFileName = NULL;
2114
+ }
2115
+
2116
+ // Only allocate new file name if it's not there yet
2117
+ if(pFileEntry->szFileName == NULL)
2118
+ {
2119
+ pFileEntry->szFileName = STORM_ALLOC(char, strlen(szFileName) + 1);
2120
+ if(pFileEntry->szFileName != NULL)
2121
+ strcpy(pFileEntry->szFileName, szFileName);
2122
+ }
2123
+
2124
+ // We also need to create the file name hash
2125
+ if(ha->pHetTable != NULL)
2126
+ {
2127
+ ULONGLONG AndMask64 = ha->pHetTable->AndMask64;
2128
+ ULONGLONG OrMask64 = ha->pHetTable->OrMask64;
2129
+
2130
+ pFileEntry->FileNameHash = (HashStringJenkins(szFileName) & AndMask64) | OrMask64;
2131
+ }
2132
+ }
2133
+
2134
+ TFileEntry * AllocateFileEntry(TMPQArchive * ha, const char * szFileName, LCID lcFileLocale, LPDWORD PtrHashIndex)
2135
+ {
2136
+ TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
2137
+ TFileEntry * pFreeEntry = NULL;
2138
+ TFileEntry * pFileEntry;
2139
+ TMPQHash * pHash = NULL;
2140
+ DWORD dwReservedFiles = ha->dwReservedFiles;
2141
+ DWORD dwFreeCount = 0;
2142
+
2143
+ // Sanity check: File table size must be greater or equal to max file count
2144
+ assert(ha->dwFileTableSize >= ha->dwMaxFileCount);
2145
+
2146
+ // If we are saving MPQ tables, we don't tale number of reserved files into account
2147
+ dwReservedFiles = (ha->dwFlags & MPQ_FLAG_SAVING_TABLES) ? 0 : ha->dwReservedFiles;
2148
+
2149
+ // Now find a free entry in the file table.
2150
+ // Note that in the case when free entries are in the middle,
2151
+ // we need to use these
2152
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
2153
+ {
2154
+ if((pFileEntry->dwFlags & MPQ_FILE_EXISTS) == 0)
2155
+ {
2156
+ // Remember the first free entry
2157
+ if(pFreeEntry == NULL)
2158
+ pFreeEntry = pFileEntry;
2159
+ dwFreeCount++;
2160
+
2161
+ // If the number of free items is greater than number
2162
+ // of reserved items, We can add the file
2163
+ if(dwFreeCount > dwReservedFiles)
2164
+ break;
2165
+ }
2166
+ }
2167
+
2168
+ // If the total number of free entries is less than number of reserved files,
2169
+ // we cannot add the file to the archive
2170
+ if(pFreeEntry == NULL || dwFreeCount <= dwReservedFiles)
2171
+ return NULL;
2172
+
2173
+ // Initialize the file entry and set its file name
2174
+ memset(pFreeEntry, 0, sizeof(TFileEntry));
2175
+ AllocateFileName(ha, pFreeEntry, szFileName);
2176
+
2177
+ // If the archive has a hash table, we need to first free entry there
2178
+ if(ha->pHashTable != NULL)
2179
+ {
2180
+ // Make sure that the entry is not there yet
2181
+ assert(GetHashEntryExact(ha, szFileName, lcFileLocale) == NULL);
2182
+
2183
+ // Find a free hash table entry for the name
2184
+ pHash = AllocateHashEntry(ha, pFreeEntry, lcFileLocale);
2185
+ if(pHash == NULL)
2186
+ return NULL;
2187
+
2188
+ // Set the file index to the hash table
2189
+ pHash->dwBlockIndex = (DWORD)(pFreeEntry - ha->pFileTable);
2190
+ PtrHashIndex[0] = (DWORD)(pHash - ha->pHashTable);
2191
+ }
2192
+
2193
+ // If the archive has a HET table, just do some checks
2194
+ // Note: Don't bother modifying the HET table. It will be rebuilt from scratch after, anyway
2195
+ if(ha->pHetTable != NULL)
2196
+ {
2197
+ assert(GetFileIndex_Het(ha, szFileName) == HASH_ENTRY_FREE);
2198
+ }
2199
+
2200
+ // Return the free table entry
2201
+ return pFreeEntry;
2202
+ }
2203
+
2204
+ DWORD RenameFileEntry(
2205
+ TMPQArchive * ha,
2206
+ TMPQFile * hf,
2207
+ const char * szNewFileName)
2208
+ {
2209
+ TFileEntry * pFileEntry = hf->pFileEntry;
2210
+ TMPQHash * pHashEntry = hf->pHashEntry;
2211
+ LCID lcFileLocale = 0;
2212
+
2213
+ // If the archive hash hash table, we need to free the hash table entry
2214
+ if(ha->pHashTable != NULL)
2215
+ {
2216
+ // The file must have hash table entry assigned
2217
+ // Will exit if there are multiple HASH entries pointing to the same file entry
2218
+ if(pHashEntry == NULL)
2219
+ return ERROR_NOT_SUPPORTED;
2220
+
2221
+ // Save the locale
2222
+ lcFileLocale = SFILE_MAKE_LCID(pHashEntry->Locale, pHashEntry->Platform);
2223
+
2224
+ // Mark the hash table entry as deleted
2225
+ pHashEntry->dwName1 = 0xFFFFFFFF;
2226
+ pHashEntry->dwName2 = 0xFFFFFFFF;
2227
+ pHashEntry->Locale = 0xFFFF;
2228
+ pHashEntry->Platform = 0xFF;
2229
+ pHashEntry->Reserved = 0xFF;
2230
+ pHashEntry->dwBlockIndex = HASH_ENTRY_DELETED;
2231
+ }
2232
+
2233
+ // Free the old file name
2234
+ if(pFileEntry->szFileName != NULL)
2235
+ STORM_FREE(pFileEntry->szFileName);
2236
+ pFileEntry->szFileName = NULL;
2237
+
2238
+ // Allocate new file name
2239
+ AllocateFileName(ha, pFileEntry, szNewFileName);
2240
+
2241
+ // Allocate new hash entry
2242
+ if(ha->pHashTable != NULL)
2243
+ {
2244
+ // Since we freed one hash entry before, this must succeed
2245
+ hf->pHashEntry = AllocateHashEntry(ha, pFileEntry, lcFileLocale);
2246
+ assert(hf->pHashEntry != NULL);
2247
+ }
2248
+
2249
+ return ERROR_SUCCESS;
2250
+ }
2251
+
2252
+ DWORD DeleteFileEntry(TMPQArchive * ha, TMPQFile * hf)
2253
+ {
2254
+ TFileEntry * pFileEntry = hf->pFileEntry;
2255
+ TMPQHash * pHashEntry = hf->pHashEntry;
2256
+
2257
+ // If the archive hash hash table, we need to free the hash table entry
2258
+ if(ha->pHashTable != NULL)
2259
+ {
2260
+ // The file must have hash table entry assigned
2261
+ // Will exit if there are multiple HASH entries pointing to the same file entry
2262
+ if(pHashEntry == NULL)
2263
+ return ERROR_NOT_SUPPORTED;
2264
+
2265
+ // Mark the hash table entry as deleted
2266
+ pHashEntry->dwName1 = 0xFFFFFFFF;
2267
+ pHashEntry->dwName2 = 0xFFFFFFFF;
2268
+ pHashEntry->Locale = 0xFFFF;
2269
+ pHashEntry->Platform = 0xFF;
2270
+ pHashEntry->Reserved = 0xFF;
2271
+ pHashEntry->dwBlockIndex = HASH_ENTRY_DELETED;
2272
+ }
2273
+
2274
+ // Free the file name, and set the file entry as deleted
2275
+ if(pFileEntry->szFileName != NULL)
2276
+ STORM_FREE(pFileEntry->szFileName);
2277
+ pFileEntry->szFileName = NULL;
2278
+
2279
+ //
2280
+ // Don't modify the HET table, because it gets recreated by the caller
2281
+ // Don't decrement the number of entries in the file table
2282
+ // Keep Byte Offset, file size, compressed size, CRC32 and MD5
2283
+ // Clear the file name hash and the MPQ_FILE_EXISTS bit
2284
+ //
2285
+
2286
+ pFileEntry->dwFlags &= ~MPQ_FILE_EXISTS;
2287
+ pFileEntry->FileNameHash = 0;
2288
+ return ERROR_SUCCESS;
2289
+ }
2290
+
2291
+ DWORD InvalidateInternalFile(TMPQArchive * ha, const char * szFileName, DWORD dwFlagNone, DWORD dwFlagNew, DWORD dwForceAddTheFile = 0)
2292
+ {
2293
+ TMPQFile * hf = NULL;
2294
+ DWORD dwFileFlags = MPQ_FILE_DEFAULT_INTERNAL;
2295
+ DWORD dwErrCode = ERROR_FILE_NOT_FOUND;
2296
+
2297
+ // Open the file from the MPQ
2298
+ if(SFileOpenFileEx((HANDLE)ha, szFileName, SFILE_OPEN_BASE_FILE, (HANDLE *)&hf))
2299
+ {
2300
+ // Remember the file flags
2301
+ dwFileFlags = hf->pFileEntry->dwFlags;
2302
+
2303
+ // Delete the file entry
2304
+ dwErrCode = DeleteFileEntry(ha, hf);
2305
+ if(dwErrCode == ERROR_SUCCESS)
2306
+ dwForceAddTheFile = 1;
2307
+
2308
+ // Close the file
2309
+ FreeFileHandle(hf);
2310
+ }
2311
+
2312
+ // Are we going to add the file?
2313
+ if(dwForceAddTheFile)
2314
+ {
2315
+ ha->dwFlags |= dwFlagNew;
2316
+ ha->dwReservedFiles++;
2317
+ }
2318
+ else
2319
+ {
2320
+ ha->dwFlags |= dwFlagNone;
2321
+ dwFileFlags = 0;
2322
+ }
2323
+
2324
+ // Return the intended file flags
2325
+ return dwFileFlags;
2326
+ }
2327
+
2328
+ void InvalidateInternalFiles(TMPQArchive * ha)
2329
+ {
2330
+ // Do nothing if we are in the middle of saving internal files
2331
+ if(!(ha->dwFlags & MPQ_FLAG_SAVING_TABLES))
2332
+ {
2333
+ //
2334
+ // We clear the file entries for (listfile), (attributes) and (signature)
2335
+ // For each internal file cleared, we increment the number
2336
+ // of reserved entries in the file table.
2337
+ //
2338
+
2339
+ // Invalidate the (listfile), if not done yet
2340
+ if((ha->dwFlags & (MPQ_FLAG_LISTFILE_NONE | MPQ_FLAG_LISTFILE_NEW)) == 0)
2341
+ {
2342
+ ha->dwFileFlags1 = InvalidateInternalFile(ha, LISTFILE_NAME, MPQ_FLAG_LISTFILE_NONE, MPQ_FLAG_LISTFILE_NEW, (ha->dwFlags & MPQ_FLAG_LISTFILE_FORCE));
2343
+ }
2344
+
2345
+ // Invalidate the (attributes), if not done yet
2346
+ if((ha->dwFlags & (MPQ_FLAG_ATTRIBUTES_NONE | MPQ_FLAG_ATTRIBUTES_NEW)) == 0)
2347
+ {
2348
+ ha->dwFileFlags2 = InvalidateInternalFile(ha, ATTRIBUTES_NAME, MPQ_FLAG_ATTRIBUTES_NONE, MPQ_FLAG_ATTRIBUTES_NEW);
2349
+ }
2350
+
2351
+ // Invalidate the (signature), if not done yet
2352
+ if((ha->dwFlags & (MPQ_FLAG_SIGNATURE_NONE | MPQ_FLAG_SIGNATURE_NEW)) == 0)
2353
+ {
2354
+ ha->dwFileFlags3 = InvalidateInternalFile(ha, SIGNATURE_NAME, MPQ_FLAG_SIGNATURE_NONE, MPQ_FLAG_SIGNATURE_NEW);
2355
+ }
2356
+
2357
+ // Remember that the MPQ has been changed
2358
+ ha->dwFlags |= MPQ_FLAG_CHANGED;
2359
+ }
2360
+ }
2361
+
2362
+ //-----------------------------------------------------------------------------
2363
+ // Support for file tables - hash table, block table, hi-block table
2364
+
2365
+ DWORD CreateHashTable(TMPQArchive * ha, DWORD dwHashTableSize)
2366
+ {
2367
+ TMPQHash * pHashTable;
2368
+
2369
+ // Sanity checks
2370
+ assert((dwHashTableSize & (dwHashTableSize - 1)) == 0);
2371
+ assert(ha->pHashTable == NULL);
2372
+
2373
+ // If the required hash table size is zero, don't create anything
2374
+ if(dwHashTableSize == 0)
2375
+ dwHashTableSize = HASH_TABLE_SIZE_DEFAULT;
2376
+
2377
+ // Create the hash table
2378
+ pHashTable = STORM_ALLOC(TMPQHash, dwHashTableSize);
2379
+ if(pHashTable == NULL)
2380
+ return ERROR_NOT_ENOUGH_MEMORY;
2381
+
2382
+ // Fill it
2383
+ memset(pHashTable, 0xFF, dwHashTableSize * sizeof(TMPQHash));
2384
+ ha->pHeader->dwHashTableSize = dwHashTableSize;
2385
+ ha->dwMaxFileCount = dwHashTableSize;
2386
+ ha->pHashTable = pHashTable;
2387
+ return ERROR_SUCCESS;
2388
+ }
2389
+
2390
+ static TMPQHash * LoadHashTable(TMPQArchive * ha)
2391
+ {
2392
+ TMPQHeader * pHeader = ha->pHeader;
2393
+ ULONGLONG ByteOffset;
2394
+ TMPQHash * pHashTable = NULL;
2395
+ DWORD dwTableSize;
2396
+ DWORD dwCmpSize;
2397
+ DWORD dwRealTableSize = 0;
2398
+
2399
+ // Note: It is allowed to load hash table if it is at offset 0.
2400
+ // Example: MPQ_2016_v1_ProtectedMap_HashOffsIsZero.w3x
2401
+ // if(pHeader->dwHashTablePos == 0 && pHeader->wHashTablePosHi == 0)
2402
+ // return NULL;
2403
+
2404
+ // If the hash table size is zero, do nothing
2405
+ if(pHeader->dwHashTableSize == 0)
2406
+ return NULL;
2407
+
2408
+ // Load the hash table for MPQ variations
2409
+ switch(ha->dwSubType)
2410
+ {
2411
+ case MPQ_SUBTYPE_MPQ:
2412
+
2413
+ // Calculate the position and size of the hash table
2414
+ ByteOffset = FileOffsetFromMpqOffset(ha, MAKE_OFFSET64(pHeader->wHashTablePosHi, pHeader->dwHashTablePos));
2415
+ dwTableSize = pHeader->dwHashTableSize * sizeof(TMPQHash);
2416
+ dwCmpSize = (DWORD)pHeader->HashTableSize64;
2417
+
2418
+ // Read, decrypt and uncompress the hash table
2419
+ pHashTable = (TMPQHash *)LoadMpqTable(ha, ByteOffset, pHeader->MD5_HashTable, dwCmpSize, dwTableSize, g_dwHashTableKey, &dwRealTableSize);
2420
+ // DumpHashTable(pHashTable, pHeader->dwHashTableSize);
2421
+
2422
+ // If the hash table was cut, we can/have to defragment it
2423
+ if(pHashTable != NULL && dwRealTableSize != 0 && dwRealTableSize < dwTableSize)
2424
+ {
2425
+ ha->dwRealHashTableSize = dwRealTableSize;
2426
+ ha->dwFlags |= (MPQ_FLAG_MALFORMED | MPQ_FLAG_HASH_TABLE_CUT);
2427
+ }
2428
+ break;
2429
+
2430
+ case MPQ_SUBTYPE_SQP:
2431
+ pHashTable = LoadSqpHashTable(ha);
2432
+ break;
2433
+
2434
+ case MPQ_SUBTYPE_MPK:
2435
+ pHashTable = LoadMpkHashTable(ha);
2436
+ break;
2437
+ }
2438
+
2439
+ // Return the loaded hash table
2440
+ return pHashTable;
2441
+ }
2442
+
2443
+ DWORD CreateFileTable(TMPQArchive * ha, DWORD dwFileTableSize)
2444
+ {
2445
+ ha->pFileTable = STORM_ALLOC(TFileEntry, dwFileTableSize);
2446
+ if(ha->pFileTable == NULL)
2447
+ return ERROR_NOT_ENOUGH_MEMORY;
2448
+
2449
+ memset(ha->pFileTable, 0x00, sizeof(TFileEntry) * dwFileTableSize);
2450
+ ha->dwFileTableSize = dwFileTableSize;
2451
+ return ERROR_SUCCESS;
2452
+ }
2453
+
2454
+ TMPQBlock * LoadBlockTable(TMPQArchive * ha, bool /* bDontFixEntries */)
2455
+ {
2456
+ TMPQHeader * pHeader = ha->pHeader;
2457
+ TMPQBlock * pBlockTable = NULL;
2458
+ ULONGLONG ByteOffset;
2459
+ DWORD dwTableSize;
2460
+ DWORD dwCmpSize;
2461
+ DWORD dwRealTableSize;
2462
+
2463
+ // Note: It is possible that the block table starts at offset 0
2464
+ // Example: MPQ_2016_v1_ProtectedMap_HashOffsIsZero.w3x
2465
+ // if(pHeader->dwBlockTablePos == 0 && pHeader->wBlockTablePosHi == 0)
2466
+ // return NULL;
2467
+
2468
+ // Do nothing if the block table size is zero
2469
+ if(pHeader->dwBlockTableSize == 0)
2470
+ return NULL;
2471
+
2472
+ // Load the block table for MPQ variations
2473
+ switch(ha->dwSubType)
2474
+ {
2475
+ case MPQ_SUBTYPE_MPQ:
2476
+
2477
+ // Calculate byte position of the block table
2478
+ ByteOffset = FileOffsetFromMpqOffset(ha, MAKE_OFFSET64(pHeader->wBlockTablePosHi, pHeader->dwBlockTablePos));
2479
+ dwTableSize = pHeader->dwBlockTableSize * sizeof(TMPQBlock);
2480
+ dwCmpSize = (DWORD)pHeader->BlockTableSize64;
2481
+
2482
+ // Read, decrypt and uncompress the block table
2483
+ pBlockTable = (TMPQBlock * )LoadMpqTable(ha, ByteOffset, NULL, dwCmpSize, dwTableSize, g_dwBlockTableKey, &dwRealTableSize);
2484
+
2485
+ // If the block table was cut, we need to remember it
2486
+ if(pBlockTable != NULL && dwRealTableSize && dwRealTableSize < dwTableSize)
2487
+ ha->dwFlags |= (MPQ_FLAG_MALFORMED | MPQ_FLAG_BLOCK_TABLE_CUT);
2488
+ break;
2489
+
2490
+ case MPQ_SUBTYPE_SQP:
2491
+ pBlockTable = LoadSqpBlockTable(ha);
2492
+ break;
2493
+
2494
+ case MPQ_SUBTYPE_MPK:
2495
+ pBlockTable = LoadMpkBlockTable(ha);
2496
+ break;
2497
+ }
2498
+
2499
+ return pBlockTable;
2500
+ }
2501
+
2502
+ TMPQHetTable * LoadHetTable(TMPQArchive * ha)
2503
+ {
2504
+ TMPQExtHeader * pExtTable;
2505
+ TMPQHetTable * pHetTable = NULL;
2506
+ TMPQHeader * pHeader = ha->pHeader;
2507
+
2508
+ // If the HET table position is not 0, we expect the table to be present
2509
+ if(pHeader->HetTablePos64 && pHeader->HetTableSize64)
2510
+ {
2511
+ // Attempt to load the HET table (Hash Extended Table)
2512
+ pExtTable = LoadExtTable(ha, pHeader->HetTablePos64, (size_t)pHeader->HetTableSize64, HET_TABLE_SIGNATURE, MPQ_KEY_HASH_TABLE);
2513
+ if(pExtTable != NULL)
2514
+ {
2515
+ // Translate the loaded table into HET table.
2516
+ pHetTable = TranslateHetTable((TMPQHetHeader *)pExtTable);
2517
+ STORM_FREE(pExtTable);
2518
+ }
2519
+ }
2520
+
2521
+ return pHetTable;
2522
+ }
2523
+
2524
+ TMPQBetTable * LoadBetTable(TMPQArchive * ha)
2525
+ {
2526
+ TMPQExtHeader * pExtTable;
2527
+ TMPQBetTable * pBetTable = NULL;
2528
+ TMPQHeader * pHeader = ha->pHeader;
2529
+
2530
+ // If the BET table position is not 0, we expect the table to be present
2531
+ if(pHeader->BetTablePos64 && pHeader->BetTableSize64)
2532
+ {
2533
+ // Attempt to load the HET table (Hash Extended Table)
2534
+ pExtTable = LoadExtTable(ha, pHeader->BetTablePos64, (size_t)pHeader->BetTableSize64, BET_TABLE_SIGNATURE, MPQ_KEY_BLOCK_TABLE);
2535
+ if(pExtTable != NULL)
2536
+ {
2537
+ // If succeeded, we translate the BET table
2538
+ // to more readable form
2539
+ pBetTable = TranslateBetTable(ha, (TMPQBetHeader *)pExtTable);
2540
+ STORM_FREE(pExtTable);
2541
+ }
2542
+ }
2543
+
2544
+ return pBetTable;
2545
+ }
2546
+
2547
+ DWORD LoadAnyHashTable(TMPQArchive * ha)
2548
+ {
2549
+ TMPQHeader * pHeader = ha->pHeader;
2550
+
2551
+ // If the MPQ archive is empty, don't bother trying to load anything
2552
+ if(pHeader->dwHashTableSize == 0 && pHeader->HetTableSize64 == 0)
2553
+ return CreateHashTable(ha, HASH_TABLE_SIZE_DEFAULT);
2554
+
2555
+ // Try to load HET table
2556
+ if(pHeader->HetTablePos64 != 0)
2557
+ ha->pHetTable = LoadHetTable(ha);
2558
+
2559
+ // Try to load classic hash table
2560
+ // Note that we load the classic hash table even when HET table exists,
2561
+ // because if the MPQ gets modified and saved, hash table must be there
2562
+ if(pHeader->dwHashTableSize)
2563
+ ha->pHashTable = LoadHashTable(ha);
2564
+
2565
+ // At least one of the tables must be present
2566
+ if(ha->pHetTable == NULL && ha->pHashTable == NULL)
2567
+ return ERROR_FILE_CORRUPT;
2568
+
2569
+ // Set the maximum file count to the size of the hash table.
2570
+ // Note: We don't care about HET table limits, because HET table is rebuilt
2571
+ // after each file add/rename/delete.
2572
+ ha->dwMaxFileCount = (ha->pHashTable != NULL) ? pHeader->dwHashTableSize : HASH_TABLE_SIZE_MAX;
2573
+ return ERROR_SUCCESS;
2574
+ }
2575
+
2576
+ static DWORD BuildFileTable_Classic(TMPQArchive * ha)
2577
+ {
2578
+ TMPQHeader * pHeader = ha->pHeader;
2579
+ TMPQBlock * pBlockTable;
2580
+ DWORD dwErrCode = ERROR_SUCCESS;
2581
+
2582
+ // Sanity checks
2583
+ assert(ha->pHashTable != NULL);
2584
+ assert(ha->pFileTable != NULL);
2585
+
2586
+ // If the MPQ has no block table, do nothing
2587
+ if(pHeader->dwBlockTableSize == 0)
2588
+ return ERROR_SUCCESS;
2589
+ assert(ha->dwFileTableSize >= pHeader->dwBlockTableSize);
2590
+
2591
+ // Load the block table
2592
+ // WARNING! ha->pFileTable can change in the process!!
2593
+ pBlockTable = (TMPQBlock *)LoadBlockTable(ha);
2594
+ if(pBlockTable != NULL)
2595
+ {
2596
+ dwErrCode = BuildFileTableFromBlockTable(ha, pBlockTable);
2597
+ STORM_FREE(pBlockTable);
2598
+ }
2599
+ else
2600
+ {
2601
+ dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
2602
+ }
2603
+
2604
+ // Load the hi-block table
2605
+ if(dwErrCode == ERROR_SUCCESS && pHeader->HiBlockTablePos64 != 0)
2606
+ {
2607
+ ULONGLONG ByteOffset;
2608
+ USHORT * pHiBlockTable = NULL;
2609
+ DWORD dwTableSize = pHeader->dwBlockTableSize * sizeof(USHORT);
2610
+
2611
+ // Allocate space for the hi-block table
2612
+ // Note: pHeader->dwBlockTableSize can be zero !!!
2613
+ pHiBlockTable = STORM_ALLOC(USHORT, pHeader->dwBlockTableSize + 1);
2614
+ if(pHiBlockTable != NULL)
2615
+ {
2616
+ // Load the hi-block table. It is not encrypted, nor compressed
2617
+ ByteOffset = ha->MpqPos + pHeader->HiBlockTablePos64;
2618
+ if(!FileStream_Read(ha->pStream, &ByteOffset, pHiBlockTable, dwTableSize))
2619
+ dwErrCode = GetLastError();
2620
+
2621
+ // Now merge the hi-block table to the file table
2622
+ if(dwErrCode == ERROR_SUCCESS)
2623
+ {
2624
+ TFileEntry * pFileEntry = ha->pFileTable;
2625
+
2626
+ // Swap the hi-block table
2627
+ BSWAP_ARRAY16_UNSIGNED(pHiBlockTable, dwTableSize);
2628
+
2629
+ // Add the high file offset to the base file offset.
2630
+ for(DWORD i = 0; i < pHeader->dwBlockTableSize; i++, pFileEntry++)
2631
+ pFileEntry->ByteOffset = MAKE_OFFSET64(pHiBlockTable[i], pFileEntry->ByteOffset);
2632
+ }
2633
+
2634
+ // Free the hi-block table
2635
+ STORM_FREE(pHiBlockTable);
2636
+ }
2637
+ else
2638
+ {
2639
+ dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
2640
+ }
2641
+ }
2642
+
2643
+ return dwErrCode;
2644
+ }
2645
+
2646
+ static DWORD BuildFileTable_HetBet(TMPQArchive * ha)
2647
+ {
2648
+ TMPQHetTable * pHetTable = ha->pHetTable;
2649
+ TMPQBetTable * pBetTable;
2650
+ TFileEntry * pFileEntry = ha->pFileTable;
2651
+ TMPQBits * pBitArray;
2652
+ DWORD dwBitPosition = 0;
2653
+ DWORD i;
2654
+ DWORD dwErrCode = ERROR_SUCCESS;
2655
+
2656
+ // Load the BET table from the MPQ
2657
+ pBetTable = LoadBetTable(ha);
2658
+ if(pBetTable != NULL)
2659
+ {
2660
+ // Verify the size of NameHash2 in the BET table.
2661
+ // It has to be 8 bits less than the information in HET table
2662
+ if((pBetTable->dwBitCount_NameHash2 + 8) != pHetTable->dwNameHashBitSize)
2663
+ {
2664
+ FreeBetTable(pBetTable);
2665
+ return ERROR_FILE_CORRUPT;
2666
+ }
2667
+
2668
+ // Step one: Fill the name indexes
2669
+ for(i = 0; i < pHetTable->dwTotalCount; i++)
2670
+ {
2671
+ DWORD dwFileIndex = 0;
2672
+
2673
+ // Is the entry in the HET table occupied?
2674
+ if(pHetTable->pNameHashes[i] != HET_ENTRY_FREE)
2675
+ {
2676
+ // Load the index to the BET table
2677
+ dwErrCode = pHetTable->pBetIndexes->GetBits(pHetTable->dwIndexSizeTotal * i,
2678
+ pHetTable->dwIndexSize,
2679
+ &dwFileIndex,
2680
+ 4);
2681
+ if(dwErrCode != ERROR_SUCCESS)
2682
+ {
2683
+ FreeBetTable(pBetTable);
2684
+ return ERROR_FILE_CORRUPT;
2685
+ }
2686
+
2687
+ // Overflow test
2688
+ if(dwFileIndex < pBetTable->dwEntryCount)
2689
+ {
2690
+ ULONGLONG NameHash1 = pHetTable->pNameHashes[i];
2691
+ ULONGLONG NameHash2 = 0;
2692
+
2693
+ // Load the BET hash
2694
+ dwErrCode = pBetTable->pNameHashes->GetBits(pBetTable->dwBitTotal_NameHash2 * dwFileIndex,
2695
+ pBetTable->dwBitCount_NameHash2,
2696
+ &NameHash2,
2697
+ 8);
2698
+ if(dwErrCode != ERROR_SUCCESS)
2699
+ {
2700
+ FreeBetTable(pBetTable);
2701
+ return ERROR_FILE_CORRUPT;
2702
+ }
2703
+
2704
+ // Combine both part of the name hash and put it to the file table
2705
+ pFileEntry = ha->pFileTable + dwFileIndex;
2706
+ pFileEntry->FileNameHash = (NameHash1 << pBetTable->dwBitCount_NameHash2) | NameHash2;
2707
+ }
2708
+ }
2709
+ }
2710
+
2711
+ // Go through the entire BET table and convert it to the file table.
2712
+ pFileEntry = ha->pFileTable;
2713
+ pBitArray = pBetTable->pFileTable;
2714
+ for(i = 0; i < pBetTable->dwEntryCount; i++)
2715
+ {
2716
+ DWORD dwFlagIndex = 0;
2717
+
2718
+ // Read the file position
2719
+ if((dwErrCode = pBitArray->GetBits(dwBitPosition + pBetTable->dwBitIndex_FilePos,
2720
+ pBetTable->dwBitCount_FilePos,
2721
+ &pFileEntry->ByteOffset,
2722
+ 8)) != ERROR_SUCCESS)
2723
+ break;
2724
+
2725
+ // Read the file size
2726
+ if((dwErrCode = pBitArray->GetBits(dwBitPosition + pBetTable->dwBitIndex_FileSize,
2727
+ pBetTable->dwBitCount_FileSize,
2728
+ &pFileEntry->dwFileSize,
2729
+ 4)) != ERROR_SUCCESS)
2730
+ break;
2731
+
2732
+ // Read the compressed size
2733
+ if((dwErrCode = pBitArray->GetBits(dwBitPosition + pBetTable->dwBitIndex_CmpSize,
2734
+ pBetTable->dwBitCount_CmpSize,
2735
+ &pFileEntry->dwCmpSize,
2736
+ 4)) != ERROR_SUCCESS)
2737
+ break;
2738
+
2739
+ // Read the flag index
2740
+ if(pBetTable->dwFlagCount != 0)
2741
+ {
2742
+ if((dwErrCode = pBitArray->GetBits(dwBitPosition + pBetTable->dwBitIndex_FlagIndex,
2743
+ pBetTable->dwBitCount_FlagIndex,
2744
+ &dwFlagIndex,
2745
+ 4)) != ERROR_SUCCESS)
2746
+ break;
2747
+
2748
+ pFileEntry->dwFlags = pBetTable->pFileFlags[dwFlagIndex];
2749
+ }
2750
+
2751
+ //
2752
+ // TODO: Locale (?)
2753
+ //
2754
+
2755
+ // Move the current bit position
2756
+ dwBitPosition += pBetTable->dwTableEntrySize;
2757
+ pFileEntry++;
2758
+ }
2759
+
2760
+ // Set the current size of the file table
2761
+ FreeBetTable(pBetTable);
2762
+ }
2763
+ else
2764
+ {
2765
+ dwErrCode = ERROR_FILE_CORRUPT;
2766
+ }
2767
+ return dwErrCode;
2768
+ }
2769
+
2770
+ DWORD BuildFileTable(TMPQArchive * ha)
2771
+ {
2772
+ DWORD dwFileTableSize;
2773
+ bool bFileTableCreated = false;
2774
+
2775
+ // Sanity checks
2776
+ assert(ha->pFileTable == NULL);
2777
+ assert(ha->dwFileTableSize == 0);
2778
+ assert(ha->dwMaxFileCount != 0);
2779
+
2780
+ // Determine the allocation size for the file table
2781
+ dwFileTableSize = STORMLIB_MAX(ha->pHeader->dwBlockTableSize, ha->dwMaxFileCount);
2782
+
2783
+ // Allocate the file table with size determined before
2784
+ ha->pFileTable = STORM_ALLOC(TFileEntry, dwFileTableSize);
2785
+ if(ha->pFileTable == NULL)
2786
+ return ERROR_NOT_ENOUGH_MEMORY;
2787
+
2788
+ // Fill the table with zeros
2789
+ memset(ha->pFileTable, 0, dwFileTableSize * sizeof(TFileEntry));
2790
+ ha->dwFileTableSize = dwFileTableSize;
2791
+
2792
+ // If we have HET table, we load file table from the BET table
2793
+ // Note: If BET table is corrupt or missing, we set the archive as read only
2794
+ if(ha->pHetTable != NULL)
2795
+ {
2796
+ if(BuildFileTable_HetBet(ha) != ERROR_SUCCESS)
2797
+ ha->dwFlags |= MPQ_FLAG_READ_ONLY;
2798
+ else
2799
+ bFileTableCreated = true;
2800
+ }
2801
+
2802
+ // If we have hash table, we load the file table from the block table
2803
+ // Note: If block table is corrupt or missing, we set the archive as read only
2804
+ if(ha->pHashTable != NULL)
2805
+ {
2806
+ if(BuildFileTable_Classic(ha) != ERROR_SUCCESS)
2807
+ ha->dwFlags |= MPQ_FLAG_READ_ONLY;
2808
+ else
2809
+ bFileTableCreated = true;
2810
+ }
2811
+
2812
+ // Return result
2813
+ return bFileTableCreated ? ERROR_SUCCESS : ERROR_FILE_CORRUPT;
2814
+ }
2815
+
2816
+ /*
2817
+ void UpdateBlockTableSize(TMPQArchive * ha)
2818
+ {
2819
+ TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
2820
+ TFileEntry * pFileEntry;
2821
+ DWORD dwBlockTableSize = 0;
2822
+
2823
+ // Calculate the number of files
2824
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
2825
+ {
2826
+ // If the source table entry is valid,
2827
+ if(pFileEntry->dwFlags & MPQ_FILE_EXISTS)
2828
+ dwBlockTableSize = (DWORD)(pFileEntry - ha->pFileTable) + 1;
2829
+ }
2830
+
2831
+ // Save the block table size to the MPQ header
2832
+ ha->pHeader->dwBlockTableSize = ha->dwReservedFiles + dwBlockTableSize;
2833
+ }
2834
+ */
2835
+
2836
+ // Defragment the file table so it does not contain any gaps
2837
+ DWORD DefragmentFileTable(TMPQArchive * ha)
2838
+ {
2839
+ TFileEntry * pFileTableEnd = ha->pFileTable + ha->dwFileTableSize;
2840
+ TFileEntry * pSource = ha->pFileTable;
2841
+ TFileEntry * pTarget = ha->pFileTable;
2842
+ LPDWORD DefragmentTable;
2843
+ DWORD dwBlockTableSize = 0;
2844
+ DWORD dwSrcIndex;
2845
+ DWORD dwTrgIndex;
2846
+
2847
+ // Allocate brand new file table
2848
+ DefragmentTable = STORM_ALLOC(DWORD, ha->dwFileTableSize);
2849
+ if(DefragmentTable != NULL)
2850
+ {
2851
+ // Clear the file table
2852
+ memset(DefragmentTable, 0xFF, sizeof(DWORD) * ha->dwFileTableSize);
2853
+
2854
+ // Parse the entire file table and defragment it
2855
+ for(; pSource < pFileTableEnd; pSource++)
2856
+ {
2857
+ // If the source table entry is valid,
2858
+ if(pSource->dwFlags & MPQ_FILE_EXISTS)
2859
+ {
2860
+ // Remember the index conversion
2861
+ dwSrcIndex = (DWORD)(pSource - ha->pFileTable);
2862
+ dwTrgIndex = (DWORD)(pTarget - ha->pFileTable);
2863
+ DefragmentTable[dwSrcIndex] = dwTrgIndex;
2864
+
2865
+ // Move the entry, if needed
2866
+ if(pTarget != pSource)
2867
+ pTarget[0] = pSource[0];
2868
+ pTarget++;
2869
+
2870
+ // Update the block table size
2871
+ dwBlockTableSize = (DWORD)(pTarget - ha->pFileTable);
2872
+ }
2873
+ else
2874
+ {
2875
+ // If there is file name left, free it
2876
+ if(pSource->szFileName != NULL)
2877
+ STORM_FREE(pSource->szFileName);
2878
+ pSource->szFileName = NULL;
2879
+ }
2880
+ }
2881
+
2882
+ // Did we defragment something?
2883
+ if(pTarget < pFileTableEnd)
2884
+ {
2885
+ // Clear the remaining file entries
2886
+ memset(pTarget, 0, (pFileTableEnd - pTarget) * sizeof(TFileEntry));
2887
+
2888
+ // Go through the hash table and relocate the block indexes
2889
+ if(ha->pHashTable != NULL)
2890
+ {
2891
+ TMPQHash * pHashTableEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
2892
+ TMPQHash * pHash;
2893
+ DWORD dwNewBlockIndex;
2894
+
2895
+ for(pHash = ha->pHashTable; pHash < pHashTableEnd; pHash++)
2896
+ {
2897
+ if(MPQ_BLOCK_INDEX(pHash) < ha->dwFileTableSize)
2898
+ {
2899
+ // If that block entry is there, set it to the hash entry
2900
+ // If not, set it as DELETED
2901
+ dwNewBlockIndex = DefragmentTable[MPQ_BLOCK_INDEX(pHash)];
2902
+ pHash->dwBlockIndex = (dwNewBlockIndex != HASH_ENTRY_FREE) ? dwNewBlockIndex : HASH_ENTRY_DELETED;
2903
+ }
2904
+ }
2905
+ }
2906
+ }
2907
+
2908
+ // Save the block table size
2909
+ ha->pHeader->dwBlockTableSize = ha->dwReservedFiles + dwBlockTableSize;
2910
+
2911
+ // Free the defragment table
2912
+ STORM_FREE(DefragmentTable);
2913
+ }
2914
+
2915
+ return ERROR_SUCCESS;
2916
+ }
2917
+
2918
+ // Rebuilds the HET table from scratch based on the file table
2919
+ // Used after a modifying operation (add, rename, delete)
2920
+ DWORD RebuildHetTable(TMPQArchive * ha)
2921
+ {
2922
+ TMPQHetTable * pOldHetTable = ha->pHetTable;
2923
+ TFileEntry * pFileTableEnd;
2924
+ TFileEntry * pFileEntry;
2925
+ DWORD dwBlockTableSize = ha->dwFileTableSize;
2926
+ DWORD dwErrCode = ERROR_SUCCESS;
2927
+
2928
+ // If we are in the state of saving MPQ tables, the real size of block table
2929
+ // must already have been calculated. Use that value instead
2930
+ if(ha->dwFlags & MPQ_FLAG_SAVING_TABLES)
2931
+ {
2932
+ assert(ha->pHeader->dwBlockTableSize != 0);
2933
+ dwBlockTableSize = ha->pHeader->dwBlockTableSize;
2934
+ }
2935
+
2936
+ // Create new HET table based on the total number of entries in the file table
2937
+ // Note that if we fail to create it, we just stop using HET table
2938
+ ha->pHetTable = CreateHetTable(dwBlockTableSize, 0, 0x40, NULL);
2939
+ if(ha->pHetTable != NULL)
2940
+ {
2941
+ // Go through the file table again and insert all existing files
2942
+ pFileTableEnd = ha->pFileTable + dwBlockTableSize;
2943
+ for(pFileEntry = ha->pFileTable; pFileEntry < pFileTableEnd; pFileEntry++)
2944
+ {
2945
+ if(pFileEntry->dwFlags & MPQ_FILE_EXISTS)
2946
+ {
2947
+ // Get the high
2948
+ dwErrCode = InsertHetEntry(ha->pHetTable, pFileEntry->FileNameHash, (DWORD)(pFileEntry - ha->pFileTable));
2949
+ if(dwErrCode != ERROR_SUCCESS)
2950
+ break;
2951
+ }
2952
+ }
2953
+ }
2954
+
2955
+ // Free the old HET table
2956
+ FreeHetTable(pOldHetTable);
2957
+ return dwErrCode;
2958
+ }
2959
+
2960
+ // Rebuilds the file table, removing all deleted file entries.
2961
+ // Used when compacting the archive
2962
+ DWORD RebuildFileTable(TMPQArchive * ha, DWORD dwNewHashTableSize)
2963
+ {
2964
+ TFileEntry * pFileEntry;
2965
+ TMPQHash * pHashTableEnd = ha->pHashTable + ha->pHeader->dwHashTableSize;
2966
+ TMPQHash * pOldHashTable = ha->pHashTable;
2967
+ TMPQHash * pHashTable = NULL;
2968
+ TMPQHash * pHash;
2969
+ DWORD dwErrCode = ERROR_SUCCESS;
2970
+
2971
+ // The new hash table size must be greater or equal to the current hash table size
2972
+ assert(dwNewHashTableSize >= ha->pHeader->dwHashTableSize);
2973
+ assert(dwNewHashTableSize >= ha->dwMaxFileCount);
2974
+ assert((dwNewHashTableSize & (dwNewHashTableSize - 1)) == 0);
2975
+ assert(ha->pHashTable != NULL);
2976
+
2977
+ // Reallocate the new file table, if needed
2978
+ if(dwNewHashTableSize > ha->dwFileTableSize)
2979
+ {
2980
+ ha->pFileTable = STORM_REALLOC(TFileEntry, ha->pFileTable, dwNewHashTableSize);
2981
+ if(ha->pFileTable == NULL)
2982
+ return ERROR_NOT_ENOUGH_MEMORY;
2983
+
2984
+ memset(ha->pFileTable + ha->dwFileTableSize, 0, (dwNewHashTableSize - ha->dwFileTableSize) * sizeof(TFileEntry));
2985
+ }
2986
+
2987
+ // Allocate new hash table
2988
+ if(dwErrCode == ERROR_SUCCESS)
2989
+ {
2990
+ pHashTable = STORM_ALLOC(TMPQHash, dwNewHashTableSize);
2991
+ if(pHashTable == NULL)
2992
+ dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
2993
+ }
2994
+
2995
+ // If both succeeded, we need to rebuild the file table
2996
+ if(dwErrCode == ERROR_SUCCESS)
2997
+ {
2998
+ // Make sure that the hash table is properly filled
2999
+ memset(pHashTable, 0xFF, sizeof(TMPQHash) * dwNewHashTableSize);
3000
+ ha->pHashTable = pHashTable;
3001
+
3002
+ // Set the new limits to the MPQ archive
3003
+ ha->pHeader->dwHashTableSize = dwNewHashTableSize;
3004
+
3005
+ // Parse the old hash table and copy all entries to the new table
3006
+ for(pHash = pOldHashTable; pHash < pHashTableEnd; pHash++)
3007
+ {
3008
+ if(IsValidHashEntry(ha, pHash))
3009
+ {
3010
+ pFileEntry = ha->pFileTable + MPQ_BLOCK_INDEX(pHash);
3011
+ AllocateHashEntry(ha, pFileEntry, SFILE_MAKE_LCID(pHash->Locale, pHash->Platform));
3012
+ }
3013
+ }
3014
+
3015
+ // Increment the max file count for the file
3016
+ ha->dwFileTableSize = dwNewHashTableSize;
3017
+ ha->dwMaxFileCount = dwNewHashTableSize;
3018
+ ha->dwFlags |= MPQ_FLAG_CHANGED;
3019
+ }
3020
+
3021
+ // Now free the remaining entries
3022
+ if(pOldHashTable != NULL)
3023
+ STORM_FREE(pOldHashTable);
3024
+ return dwErrCode;
3025
+ }
3026
+
3027
+ // Saves MPQ header, hash table, block table and hi-block table.
3028
+ DWORD SaveMPQTables(TMPQArchive * ha)
3029
+ {
3030
+ TMPQExtHeader * pHetTable = NULL;
3031
+ TMPQExtHeader * pBetTable = NULL;
3032
+ TMPQHeader * pHeader = ha->pHeader;
3033
+ TMPQBlock * pBlockTable = NULL;
3034
+ TMPQHash * pHashTable = NULL;
3035
+ ULONGLONG HetTableSize64 = 0;
3036
+ ULONGLONG BetTableSize64 = 0;
3037
+ ULONGLONG HashTableSize64 = 0;
3038
+ ULONGLONG BlockTableSize64 = 0;
3039
+ ULONGLONG HiBlockTableSize64 = 0;
3040
+ ULONGLONG TablePos = 0; // A table position, relative to the begin of the MPQ
3041
+ USHORT * pHiBlockTable = NULL;
3042
+ DWORD cbTotalSize;
3043
+ bool bNeedHiBlockTable = false;
3044
+ DWORD dwErrCode = ERROR_SUCCESS;
3045
+
3046
+ // We expect this function to be called only when tables have been changed
3047
+ assert(ha->dwFlags & MPQ_FLAG_CHANGED);
3048
+
3049
+ // Find the space where the MPQ tables will be saved
3050
+ TablePos = FindFreeMpqSpace(ha);
3051
+
3052
+ // If the MPQ has HET table, we prepare a ready-to-save version
3053
+ if(dwErrCode == ERROR_SUCCESS && ha->pHetTable != NULL)
3054
+ {
3055
+ pHetTable = TranslateHetTable(ha->pHetTable, &HetTableSize64);
3056
+ if(pHetTable == NULL)
3057
+ dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
3058
+ }
3059
+
3060
+ // If the MPQ has HET table, we also must create BET table to be saved
3061
+ if(dwErrCode == ERROR_SUCCESS && ha->pHetTable != NULL)
3062
+ {
3063
+ pBetTable = TranslateBetTable(ha, &BetTableSize64);
3064
+ if(pBetTable == NULL)
3065
+ dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
3066
+ }
3067
+
3068
+ // Now create hash table
3069
+ if(dwErrCode == ERROR_SUCCESS && ha->pHashTable != NULL)
3070
+ {
3071
+ pHashTable = TranslateHashTable(ha, &HashTableSize64);
3072
+ if(pHashTable == NULL)
3073
+ dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
3074
+ }
3075
+
3076
+ // Create block table
3077
+ if(dwErrCode == ERROR_SUCCESS && ha->pFileTable != NULL)
3078
+ {
3079
+ pBlockTable = TranslateBlockTable(ha, &BlockTableSize64, &bNeedHiBlockTable);
3080
+ if(pBlockTable == NULL)
3081
+ dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
3082
+ }
3083
+
3084
+ // Create hi-block table, if needed
3085
+ if(dwErrCode == ERROR_SUCCESS && bNeedHiBlockTable)
3086
+ {
3087
+ pHiBlockTable = TranslateHiBlockTable(ha, &HiBlockTableSize64);
3088
+ if(pHiBlockTable == NULL)
3089
+ dwErrCode = ERROR_NOT_ENOUGH_MEMORY;
3090
+ }
3091
+
3092
+ // Write the HET table, if any
3093
+ if(dwErrCode == ERROR_SUCCESS && pHetTable != NULL)
3094
+ {
3095
+ pHeader->HetTableSize64 = HetTableSize64;
3096
+ pHeader->HetTablePos64 = TablePos;
3097
+ dwErrCode = SaveExtTable(ha, pHetTable, TablePos, (DWORD)HetTableSize64, pHeader->MD5_HetTable, MPQ_KEY_HASH_TABLE, false, &cbTotalSize);
3098
+ TablePos += cbTotalSize;
3099
+ }
3100
+
3101
+ // Write the BET table, if any
3102
+ if(dwErrCode == ERROR_SUCCESS && pBetTable != NULL)
3103
+ {
3104
+ pHeader->BetTableSize64 = BetTableSize64;
3105
+ pHeader->BetTablePos64 = TablePos;
3106
+ dwErrCode = SaveExtTable(ha, pBetTable, TablePos, (DWORD)BetTableSize64, pHeader->MD5_BetTable, MPQ_KEY_BLOCK_TABLE, false, &cbTotalSize);
3107
+ TablePos += cbTotalSize;
3108
+ }
3109
+
3110
+ // Write the hash table, if we have any
3111
+ if(dwErrCode == ERROR_SUCCESS && pHashTable != NULL)
3112
+ {
3113
+ pHeader->HashTableSize64 = HashTableSize64;
3114
+ pHeader->wHashTablePosHi = (USHORT)(TablePos >> 32);
3115
+ pHeader->dwHashTableSize = (DWORD)(HashTableSize64 / sizeof(TMPQHash));
3116
+ pHeader->dwHashTablePos = (DWORD)TablePos;
3117
+ dwErrCode = SaveMpqTable(ha, pHashTable, TablePos, (size_t)HashTableSize64, pHeader->MD5_HashTable, MPQ_KEY_HASH_TABLE, false);
3118
+ TablePos += HashTableSize64;
3119
+ }
3120
+
3121
+ // Write the block table, if we have any
3122
+ if(dwErrCode == ERROR_SUCCESS && pBlockTable != NULL)
3123
+ {
3124
+ pHeader->BlockTableSize64 = BlockTableSize64;
3125
+ pHeader->wBlockTablePosHi = (USHORT)(TablePos >> 32);
3126
+ pHeader->dwBlockTableSize = (DWORD)(BlockTableSize64 / sizeof(TMPQBlock));
3127
+ pHeader->dwBlockTablePos = (DWORD)TablePos;
3128
+ dwErrCode = SaveMpqTable(ha, pBlockTable, TablePos, (size_t)BlockTableSize64, pHeader->MD5_BlockTable, MPQ_KEY_BLOCK_TABLE, false);
3129
+ TablePos += BlockTableSize64;
3130
+ }
3131
+
3132
+ // Write the hi-block table, if we have any
3133
+ if(dwErrCode == ERROR_SUCCESS && pHiBlockTable != NULL)
3134
+ {
3135
+ ULONGLONG ByteOffset = ha->MpqPos + TablePos;
3136
+
3137
+ pHeader->HiBlockTableSize64 = HiBlockTableSize64;
3138
+ pHeader->HiBlockTablePos64 = TablePos;
3139
+ BSWAP_ARRAY16_UNSIGNED(pHiBlockTable, HiBlockTableSize64);
3140
+
3141
+ if(!FileStream_Write(ha->pStream, &ByteOffset, pHiBlockTable, (DWORD)HiBlockTableSize64))
3142
+ dwErrCode = GetLastError();
3143
+ TablePos += HiBlockTableSize64;
3144
+ }
3145
+
3146
+ // Cut the MPQ
3147
+ if(dwErrCode == ERROR_SUCCESS)
3148
+ {
3149
+ ULONGLONG FileSize = ha->MpqPos + TablePos;
3150
+
3151
+ if(!FileStream_SetSize(ha->pStream, FileSize))
3152
+ dwErrCode = GetLastError();
3153
+ }
3154
+
3155
+ // Write the MPQ header
3156
+ if(dwErrCode == ERROR_SUCCESS)
3157
+ {
3158
+ TMPQHeader SaveMpqHeader;
3159
+
3160
+ // Update the size of the archive
3161
+ pHeader->ArchiveSize64 = TablePos;
3162
+ pHeader->dwArchiveSize = (DWORD)TablePos;
3163
+
3164
+ // Update the MD5 of the archive header
3165
+ CalculateDataBlockHash(pHeader, MPQ_HEADER_SIZE_V4 - MD5_DIGEST_SIZE, pHeader->MD5_MpqHeader);
3166
+
3167
+ // Write the MPQ header to the file
3168
+ assert(pHeader->dwHeaderSize <= sizeof(SaveMpqHeader));
3169
+ memcpy(&SaveMpqHeader, pHeader, pHeader->dwHeaderSize);
3170
+ BSWAP_TMPQHEADER(&SaveMpqHeader, MPQ_FORMAT_VERSION_1);
3171
+ BSWAP_TMPQHEADER(&SaveMpqHeader, MPQ_FORMAT_VERSION_2);
3172
+ BSWAP_TMPQHEADER(&SaveMpqHeader, MPQ_FORMAT_VERSION_3);
3173
+ BSWAP_TMPQHEADER(&SaveMpqHeader, MPQ_FORMAT_VERSION_4);
3174
+ if(!FileStream_Write(ha->pStream, &ha->MpqPos, &SaveMpqHeader, pHeader->dwHeaderSize))
3175
+ dwErrCode = GetLastError();
3176
+ }
3177
+
3178
+ // Clear the changed flag
3179
+ if(dwErrCode == ERROR_SUCCESS)
3180
+ ha->dwFlags &= ~MPQ_FLAG_CHANGED;
3181
+
3182
+ // Cleanup and exit
3183
+ if(pHetTable != NULL)
3184
+ STORM_FREE(pHetTable);
3185
+ if(pBetTable != NULL)
3186
+ STORM_FREE(pBetTable);
3187
+ if(pHashTable != NULL)
3188
+ STORM_FREE(pHashTable);
3189
+ if(pBlockTable != NULL)
3190
+ STORM_FREE(pBlockTable);
3191
+ if(pHiBlockTable != NULL)
3192
+ STORM_FREE(pHiBlockTable);
3193
+ return dwErrCode;
3194
+ }