stormlib 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }