stormlib 1.0.0 → 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CMakeCCompiler.cmake +72 -0
- data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CMakeCXXCompiler.cmake +83 -0
- data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CMakeDetermineCompilerABI_C.bin +0 -0
- data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CMakeDetermineCompilerABI_CXX.bin +0 -0
- data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CMakeSystem.cmake +15 -0
- data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CompilerIdC/CMakeCCompilerId.c +803 -0
- data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CompilerIdC/a.out +0 -0
- data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CompilerIdCXX/CMakeCXXCompilerId.cpp +791 -0
- data/ext/stormlib/StormLib/CMakeFiles/3.22.1/CompilerIdCXX/a.out +0 -0
- data/ext/stormlib/StormLib/CMakeFiles/CMakeDirectoryInformation.cmake +16 -0
- data/ext/stormlib/StormLib/CMakeFiles/CMakeOutput.log +478 -0
- data/ext/stormlib/StormLib/CMakeFiles/Export/share/StormLib/StormLibConfig-noconfig.cmake +19 -0
- data/ext/stormlib/StormLib/CMakeFiles/Export/share/StormLib/StormLibConfig.cmake +99 -0
- data/ext/stormlib/StormLib/CMakeFiles/Makefile.cmake +61 -0
- data/ext/stormlib/StormLib/CMakeFiles/Makefile2 +112 -0
- data/ext/stormlib/StormLib/CMakeFiles/TargetDirectories.txt +9 -0
- data/ext/stormlib/StormLib/CMakeFiles/cmake.check_cache +1 -0
- data/ext/stormlib/StormLib/CMakeFiles/progress.marks +1 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/DependInfo.cmake +243 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/build.make +3695 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/cmake_clean.cmake +459 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/cmake_clean_target.cmake +3 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/compiler_depend.make +2 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/compiler_depend.ts +2 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/depend.make +2 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/flags.make +17 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/link.txt +2 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/progress.make +227 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/FileStream.cpp.o.d +160 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SBaseCommon.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SBaseDumpData.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SBaseFileTable.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SBaseSubTypes.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SCompression.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileAddFile.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileAttributes.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileCompactArchive.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileCreateArchive.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileExtractFile.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileFindFile.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileGetFileInfo.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileListFile.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileOpenArchive.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileOpenFileEx.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFilePatchArchives.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileReadFile.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/SFileVerify.cpp.o.d +159 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/adpcm/adpcm.cpp.o.d +12 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/huffman/huff.cpp.o.d +16 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/jenkins/lookup3.c.o.d +88 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/hashes/hash_memory.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/hashes/md5.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/hashes/sha1.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/hashes/sha256.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/math/ltm_desc.c.o.d +105 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/math/multi.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/math/rand_prime.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/base64_decode.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_argchk.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_find_hash.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_find_prng.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_hash_descriptor.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_hash_is_valid.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_libc.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_prng_descriptor.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_prng_is_valid.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_register_hash.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/crypt_register_prng.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/misc/zeromem.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_bit_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_boolean.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_choice.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_integer.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_octet_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_printable_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_sequence_ex.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_sequence_multi.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_short_integer.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_utctime.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_decode_utf8_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_bit_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_boolean.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_ia5_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_integer.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_object_identifier.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_octet_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_printable_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_sequence_ex.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_sequence_multi.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_set.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_setof.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_short_integer.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_utctime.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_encode_utf8_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_bit_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_boolean.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_ia5_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_integer.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_object_identifier.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_octet_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_printable_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_sequence.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_short_integer.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_utctime.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_length_utf8_string.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/asn1/der_sequence_free.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/ecc/ltc_ecc_map.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/ecc/ltc_ecc_points.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/rsa/rsa_exptmod.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/rsa/rsa_free.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/rsa/rsa_import.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/rsa/rsa_make_key.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/rsa/rsa_sign_hash.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/rsa/rsa_verify_hash.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtomcrypt/src/pk/rsa/rsa_verify_simple.c.o.d +102 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_fast_mp_invmod.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_fast_mp_montgomery_reduce.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_fast_s_mp_mul_digs.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_fast_s_mp_mul_high_digs.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_fast_s_mp_sqr.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_2expt.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_abs.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_add.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_add_d.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_addmod.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_and.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_clamp.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_clear.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_clear_multi.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_cmp.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_cmp_d.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_cmp_mag.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_cnt_lsb.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_copy.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_count_bits.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_div.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_div_2.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_div_2d.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_div_3.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_div_d.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_dr_is_modulus.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_dr_reduce.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_dr_setup.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_exch.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_expt_d.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_exptmod.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_exptmod_fast.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_exteuclid.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_fread.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_fwrite.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_gcd.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_get_int.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_grow.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_init.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_init_copy.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_init_multi.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_init_set.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_init_set_int.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_init_size.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_invmod.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_invmod_slow.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_is_square.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_jacobi.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_karatsuba_mul.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_karatsuba_sqr.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_lcm.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_lshd.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mod.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mod_2d.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mod_d.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_montgomery_calc_normalization.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_montgomery_reduce.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_montgomery_setup.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mul.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mul_2.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mul_2d.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mul_d.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_mulmod.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_n_root.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_neg.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_or.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_prime_fermat.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_prime_is_divisible.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_prime_is_prime.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_prime_miller_rabin.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_prime_next_prime.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_prime_rabin_miller_trials.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_prime_random_ex.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_radix_size.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_radix_smap.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_rand.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_read_radix.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_read_signed_bin.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_read_unsigned_bin.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce_2k.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce_2k_l.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce_2k_setup.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce_2k_setup_l.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce_is_2k.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce_is_2k_l.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_reduce_setup.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_rshd.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_set.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_set_int.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_shrink.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_signed_bin_size.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_sqr.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_sqrmod.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_sqrt.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_sub.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_sub_d.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_submod.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_to_signed_bin.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_to_signed_bin_n.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_to_unsigned_bin.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_to_unsigned_bin_n.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_toom_mul.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_toom_sqr.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_toradix.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_toradix_n.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_unsigned_bin_size.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_xor.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_mp_zero.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_prime_tab.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_reverse.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_s_mp_add.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_s_mp_exptmod.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_s_mp_mul_digs.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_s_mp_mul_high_digs.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_s_mp_sqr.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bn_s_mp_sub.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/libtommath/bncore.c.o.d +65 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/lzma/C/LzFind.c.o.d +18 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/lzma/C/LzmaDec.c.o.d +17 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/lzma/C/LzmaEnc.c.o.d +18 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/pklib/explode.c.o.d +16 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/pklib/implode.c.o.d +23 -0
- data/ext/stormlib/StormLib/CMakeFiles/storm.dir/src/sparse/sparse.cpp.o.d +16 -0
- data/ext/stormlib/StormLib/CMakeLists.txt +418 -0
- data/ext/stormlib/StormLib/Info.plist +22 -0
- data/ext/stormlib/StormLib/LICENSE +21 -0
- data/ext/stormlib/StormLib/Premake5.lua +132 -0
- data/ext/stormlib/StormLib/README.md +39 -0
- data/ext/stormlib/StormLib/StormLib.sln +162 -0
- data/ext/stormlib/StormLib/StormLib.vcxproj +1024 -0
- data/ext/stormlib/StormLib/StormLib.vcxproj.filters +221 -0
- data/ext/stormlib/StormLib/StormLib.xcodeproj/project.pbxproj +2104 -0
- data/ext/stormlib/StormLib/StormLib_dll.vcxproj +348 -0
- data/ext/stormlib/StormLib/StormLib_dll.vcxproj.filters +229 -0
- data/ext/stormlib/StormLib/StormLib_test.vcxproj +360 -0
- data/ext/stormlib/StormLib/StormLib_test.vcxproj.filters +230 -0
- data/ext/stormlib/StormLib/StormLib_vs08.sln +139 -0
- data/ext/stormlib/StormLib/StormLib_vs08.vcproj +4205 -0
- data/ext/stormlib/StormLib/StormLib_vs08_dll.vcproj +1851 -0
- data/ext/stormlib/StormLib/StormLib_vs08_test.vcproj +1289 -0
- data/ext/stormlib/StormLib/doc/History.txt +78 -0
- data/ext/stormlib/StormLib/doc/The MoPaQ File Format 0.9.txt +318 -0
- data/ext/stormlib/StormLib/doc/The MoPaQ File Format 1.0.txt +433 -0
- data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-deDE.txt +1 -0
- data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-enGB.txt +1 -0
- data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-enSG.txt +1 -0
- data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-enUS.txt +1 -0
- data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-esES.txt +1 -0
- data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-esMX.txt +1 -0
- data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-frFR.txt +1 -0
- data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-itIT.txt +1 -0
- data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-koKR.txt +1 -0
- data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-plPL.txt +1 -0
- data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-ptBR.txt +1 -0
- data/ext/stormlib/StormLib/doc/d3-authenticationcode/d3-authenticationcode-zhTW.txt +1 -0
- data/ext/stormlib/StormLib/doc/hots-authenticationcode/hots-authenticationcode-bgdl.txt +1 -0
- data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-deDE.txt +1 -0
- data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-enGB.txt +1 -0
- data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-enUS.txt +1 -0
- data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-esES.txt +1 -0
- data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-esMX.txt +1 -0
- data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-frFR.txt +1 -0
- data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-itIT.txt +1 -0
- data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-koKR.txt +1 -0
- data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-plPL.txt +1 -0
- data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-ptBR.txt +1 -0
- data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-ruRU.txt +1 -0
- data/ext/stormlib/StormLib/doc/sc2-authenticationcode/sc2-authenticationcode-zhTW.txt +1 -0
- data/ext/stormlib/StormLib/make-msvc.bat +95 -0
- data/ext/stormlib/StormLib/make.bat +46 -0
- data/ext/stormlib/StormLib/sources +14 -0
- data/ext/stormlib/StormLib/src/DllMain.c +24 -0
- data/ext/stormlib/StormLib/src/DllMain.def +79 -0
- data/ext/stormlib/StormLib/src/DllMain.rc +110 -0
- data/ext/stormlib/StormLib/src/FileStream.cpp +2928 -0
- data/ext/stormlib/StormLib/src/FileStream.h +217 -0
- data/ext/stormlib/StormLib/src/LibTomCrypt.c +85 -0
- data/ext/stormlib/StormLib/src/LibTomMath.c +125 -0
- data/ext/stormlib/StormLib/src/LibTomMathDesc.c +4 -0
- data/ext/stormlib/StormLib/src/SBaseCommon.cpp +1970 -0
- data/ext/stormlib/StormLib/src/SBaseDumpData.cpp +183 -0
- data/ext/stormlib/StormLib/src/SBaseFileTable.cpp +3194 -0
- data/ext/stormlib/StormLib/src/SBaseSubTypes.cpp +688 -0
- data/ext/stormlib/StormLib/src/SCompression.cpp +1183 -0
- data/ext/stormlib/StormLib/src/SFileAddFile.cpp +1337 -0
- data/ext/stormlib/StormLib/src/SFileAttributes.cpp +573 -0
- data/ext/stormlib/StormLib/src/SFileCompactArchive.cpp +654 -0
- data/ext/stormlib/StormLib/src/SFileCreateArchive.cpp +285 -0
- data/ext/stormlib/StormLib/src/SFileExtractFile.cpp +64 -0
- data/ext/stormlib/StormLib/src/SFileFindFile.cpp +484 -0
- data/ext/stormlib/StormLib/src/SFileGetFileInfo.cpp +627 -0
- data/ext/stormlib/StormLib/src/SFileListFile.cpp +750 -0
- data/ext/stormlib/StormLib/src/SFileOpenArchive.cpp +723 -0
- data/ext/stormlib/StormLib/src/SFileOpenFileEx.cpp +423 -0
- data/ext/stormlib/StormLib/src/SFilePatchArchives.cpp +1175 -0
- data/ext/stormlib/StormLib/src/SFileReadFile.cpp +922 -0
- data/ext/stormlib/StormLib/src/SFileVerify.cpp +1059 -0
- data/ext/stormlib/StormLib/src/StormCommon.h +450 -0
- data/ext/stormlib/StormLib/src/StormLib.exp +74 -0
- data/ext/stormlib/StormLib/src/StormLib.h +1157 -0
- data/ext/stormlib/StormLib/src/StormPort.h +474 -0
- data/ext/stormlib/StormLib/src/adpcm/adpcm.cpp +539 -0
- data/ext/stormlib/StormLib/src/adpcm/adpcm.h +27 -0
- data/ext/stormlib/StormLib/src/bzip2/blocksort.c +1094 -0
- data/ext/stormlib/StormLib/src/bzip2/bzlib.c +1573 -0
- data/ext/stormlib/StormLib/src/bzip2/bzlib.h +282 -0
- data/ext/stormlib/StormLib/src/bzip2/bzlib_private.h +509 -0
- data/ext/stormlib/StormLib/src/bzip2/compress.c +672 -0
- data/ext/stormlib/StormLib/src/bzip2/crctable.c +104 -0
- data/ext/stormlib/StormLib/src/bzip2/decompress.c +626 -0
- data/ext/stormlib/StormLib/src/bzip2/huffman.c +205 -0
- data/ext/stormlib/StormLib/src/bzip2/randtable.c +84 -0
- data/ext/stormlib/StormLib/src/huffman/huff.cpp +915 -0
- data/ext/stormlib/StormLib/src/huffman/huff.h +143 -0
- data/ext/stormlib/StormLib/src/jenkins/lookup.h +24 -0
- data/ext/stormlib/StormLib/src/jenkins/lookup3.c +1003 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/hashes/hash_memory.c +69 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/hashes/md5.c +368 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/hashes/sha1.c +288 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/hashes/sha256.c +340 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt.h +91 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_argchk.h +38 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_cfg.h +144 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_cipher.h +891 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_custom.h +424 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_hash.h +378 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_mac.h +384 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_macros.h +424 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_math.h +500 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_misc.h +23 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_pk.h +558 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_pkcs.h +89 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/headers/tomcrypt_prng.h +199 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/math/ltm_desc.c +483 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/math/multi.c +61 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/math/rand_prime.c +87 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/base64_decode.c +104 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_argchk.c +30 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_find_hash.c +40 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_find_prng.c +41 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_hash_descriptor.c +27 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_hash_is_valid.c +36 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_libc.c +43 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_ltc_mp_descriptor.c +13 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_prng_descriptor.c +26 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_prng_is_valid.c +36 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_register_hash.c +54 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/crypt_register_prng.c +54 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/misc/zeromem.c +34 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_bit_string.c +102 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_boolean.c +47 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_choice.c +182 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_ia5_string.c +96 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_integer.c +110 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_object_identifier.c +99 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_octet_string.c +91 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_printable_string.c +96 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_ex.c +287 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_flexi.c +386 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_sequence_multi.c +139 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_short_integer.c +68 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_utctime.c +127 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_decode_utf8_string.c +111 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_bit_string.c +89 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_boolean.c +51 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_ia5_string.c +85 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_integer.c +130 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_object_identifier.c +111 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_octet_string.c +86 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_printable_string.c +85 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_sequence_ex.c +335 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_sequence_multi.c +138 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_set.c +103 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_setof.c +162 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_short_integer.c +97 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_utctime.c +83 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_encode_utf8_string.c +105 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_bit_string.c +54 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_boolean.c +35 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_ia5_string.c +194 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_integer.c +82 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_object_identifier.c +89 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_octet_string.c +53 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_printable_string.c +166 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_sequence.c +169 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_short_integer.c +70 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_utctime.c +46 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_length_utf8_string.c +83 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/asn1/der_sequence_free.c +65 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_map.c +76 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_mul2add.c +207 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_mulmod.c +222 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_points.c +60 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_add_point.c +196 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/ecc/ltc_ecc_projective_dbl_point.c +147 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_mgf1.c +108 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_oaep_decode.c +189 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_decode.c +177 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_pss_encode.c +175 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_decode.c +110 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/pkcs1/pkcs_1_v1_5_encode.c +111 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/rsa/rsa_exptmod.c +113 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/rsa/rsa_free.c +34 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/rsa/rsa_import.c +143 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/rsa/rsa_make_key.c +112 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/rsa/rsa_sign_hash.c +134 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/rsa/rsa_verify_hash.c +167 -0
- data/ext/stormlib/StormLib/src/libtomcrypt/src/pk/rsa/rsa_verify_simple.c +87 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_fast_mp_invmod.c +148 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_fast_mp_montgomery_reduce.c +172 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_fast_s_mp_mul_digs.c +107 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_fast_s_mp_mul_high_digs.c +98 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_fast_s_mp_sqr.c +114 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_2expt.c +48 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_abs.c +43 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_add.c +53 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_add_d.c +112 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_addmod.c +41 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_and.c +57 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_clamp.c +44 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_clear.c +44 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_clear_multi.c +34 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_cmp.c +43 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_cmp_d.c +44 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_cmp_mag.c +55 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_cnt_lsb.c +53 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_copy.c +68 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_count_bits.c +45 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_div.c +292 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_div_2.c +68 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_div_2d.c +97 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_div_3.c +79 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_div_d.c +115 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_dr_is_modulus.c +43 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_dr_reduce.c +94 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_dr_setup.c +32 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_exch.c +34 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_expt_d.c +57 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_exptmod.c +112 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_exptmod_fast.c +321 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_exteuclid.c +82 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_fread.c +67 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_fwrite.c +52 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_gcd.c +105 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_get_int.c +45 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_grow.c +57 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_init.c +46 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_init_copy.c +32 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_init_multi.c +59 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_init_set.c +32 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_init_set_int.c +31 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_init_size.c +48 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_invmod.c +43 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_invmod_slow.c +175 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_is_square.c +109 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_jacobi.c +105 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_karatsuba_mul.c +167 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_karatsuba_sqr.c +121 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_lcm.c +60 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_lshd.c +67 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_mod.c +48 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_mod_2d.c +55 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_mod_d.c +27 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_montgomery_calc_normalization.c +59 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_montgomery_reduce.c +118 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_montgomery_setup.c +59 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_mul.c +66 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_mul_2.c +82 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_mul_2d.c +85 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_mul_d.c +79 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_mulmod.c +40 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_n_root.c +132 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_neg.c +40 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_or.c +50 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_prime_fermat.c +62 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_prime_is_divisible.c +50 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_prime_is_prime.c +83 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_prime_miller_rabin.c +103 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_prime_next_prime.c +170 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_prime_rabin_miller_trials.c +52 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_prime_random_ex.c +125 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_radix_size.c +78 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_radix_smap.c +24 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_rand.c +55 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_read_radix.c +85 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_read_signed_bin.c +41 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_read_unsigned_bin.c +55 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce.c +100 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce_2k.c +61 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce_2k_l.c +62 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce_2k_setup.c +47 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce_2k_setup_l.c +44 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce_is_2k.c +52 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce_is_2k_l.c +44 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_reduce_setup.c +34 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_rshd.c +72 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_set.c +29 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_set_int.c +48 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_shrink.c +35 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_signed_bin_size.c +27 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_sqr.c +58 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_sqrmod.c +41 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_sqrt.c +81 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_sub.c +59 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_sub_d.c +93 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_submod.c +42 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_to_signed_bin.c +33 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_to_signed_bin_n.c +31 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_to_unsigned_bin.c +48 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_to_unsigned_bin_n.c +31 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_toom_mul.c +284 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_toom_sqr.c +226 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_toradix.c +75 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_toradix_n.c +88 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_unsigned_bin_size.c +28 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_xor.c +51 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_mp_zero.c +36 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_prime_tab.c +61 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_reverse.c +39 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_s_mp_add.c +109 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_s_mp_exptmod.c +252 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_s_mp_mul_digs.c +90 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_s_mp_mul_high_digs.c +81 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_s_mp_sqr.c +84 -0
- data/ext/stormlib/StormLib/src/libtommath/bn_s_mp_sub.c +89 -0
- data/ext/stormlib/StormLib/src/libtommath/bncore.c +36 -0
- data/ext/stormlib/StormLib/src/libtommath/tommath.h +584 -0
- data/ext/stormlib/StormLib/src/libtommath/tommath_class.h +999 -0
- data/ext/stormlib/StormLib/src/libtommath/tommath_superclass.h +76 -0
- data/ext/stormlib/StormLib/src/lzma/C/LzFind.c +761 -0
- data/ext/stormlib/StormLib/src/lzma/C/LzFind.h +115 -0
- data/ext/stormlib/StormLib/src/lzma/C/LzFindMt.c +793 -0
- data/ext/stormlib/StormLib/src/lzma/C/LzFindMt.h +105 -0
- data/ext/stormlib/StormLib/src/lzma/C/LzHash.h +54 -0
- data/ext/stormlib/StormLib/src/lzma/C/LzmaDec.c +999 -0
- data/ext/stormlib/StormLib/src/lzma/C/LzmaDec.h +231 -0
- data/ext/stormlib/StormLib/src/lzma/C/LzmaEnc.c +2268 -0
- data/ext/stormlib/StormLib/src/lzma/C/LzmaEnc.h +80 -0
- data/ext/stormlib/StormLib/src/lzma/C/Threads.c +84 -0
- data/ext/stormlib/StormLib/src/lzma/C/Threads.h +59 -0
- data/ext/stormlib/StormLib/src/lzma/C/Types.h +236 -0
- data/ext/stormlib/StormLib/src/lzma/info.txt +1 -0
- data/ext/stormlib/StormLib/src/pklib/crc32.c +66 -0
- data/ext/stormlib/StormLib/src/pklib/explode.c +521 -0
- data/ext/stormlib/StormLib/src/pklib/implode.c +674 -0
- data/ext/stormlib/StormLib/src/pklib/pklib.h +160 -0
- data/ext/stormlib/StormLib/src/resource.h +15 -0
- data/ext/stormlib/StormLib/src/sparse/sparse.cpp +287 -0
- data/ext/stormlib/StormLib/src/sparse/sparse.h +17 -0
- data/ext/stormlib/StormLib/src/wdk/sources-cpp.cpp +26 -0
- data/ext/stormlib/StormLib/src/wdk/sources-wdk-bzip2.c +13 -0
- data/ext/stormlib/StormLib/src/wdk/sources-wdk-ltc.c +4 -0
- data/ext/stormlib/StormLib/src/wdk/sources-wdk-lzma.c +8 -0
- data/ext/stormlib/StormLib/src/wdk/sources-wdk-misc.c +6 -0
- data/ext/stormlib/StormLib/src/wdk/sources-wdk-tomcrypt.c +82 -0
- data/ext/stormlib/StormLib/src/wdk/sources-wdk-tommath.c +123 -0
- data/ext/stormlib/StormLib/src/wdk/sources-wdk-zlib.c +21 -0
- data/ext/stormlib/StormLib/src/zlib/adler32.c +169 -0
- data/ext/stormlib/StormLib/src/zlib/compress.c +80 -0
- data/ext/stormlib/StormLib/src/zlib/compress_zlib.c +5 -0
- data/ext/stormlib/StormLib/src/zlib/crc32.c +442 -0
- data/ext/stormlib/StormLib/src/zlib/crc32.h +441 -0
- data/ext/stormlib/StormLib/src/zlib/deflate.c +1834 -0
- data/ext/stormlib/StormLib/src/zlib/deflate.h +342 -0
- data/ext/stormlib/StormLib/src/zlib/gzguts.h +218 -0
- data/ext/stormlib/StormLib/src/zlib/inffast.c +340 -0
- data/ext/stormlib/StormLib/src/zlib/inffast.h +11 -0
- data/ext/stormlib/StormLib/src/zlib/inffixed.h +94 -0
- data/ext/stormlib/StormLib/src/zlib/inflate.c +1480 -0
- data/ext/stormlib/StormLib/src/zlib/inflate.h +130 -0
- data/ext/stormlib/StormLib/src/zlib/inftrees.c +330 -0
- data/ext/stormlib/StormLib/src/zlib/inftrees.h +67 -0
- data/ext/stormlib/StormLib/src/zlib/trees.c +1244 -0
- data/ext/stormlib/StormLib/src/zlib/trees.h +128 -0
- data/ext/stormlib/StormLib/src/zlib/zconf.h +428 -0
- data/ext/stormlib/StormLib/src/zlib/zlib.h +1613 -0
- data/ext/stormlib/StormLib/src/zlib/zutil.c +318 -0
- data/ext/stormlib/StormLib/src/zlib/zutil.h +274 -0
- data/ext/stormlib/StormLib/storm_dll/storm.cpp +117 -0
- data/ext/stormlib/StormLib/storm_dll/storm.def +25 -0
- data/ext/stormlib/StormLib/storm_dll/storm.h +65 -0
- data/ext/stormlib/StormLib/storm_dll/storm.vcxproj +209 -0
- data/ext/stormlib/StormLib/storm_dll/storm.vcxproj.filters +28 -0
- data/ext/stormlib/StormLib/storm_dll/storm_test.cpp +182 -0
- data/ext/stormlib/StormLib/storm_dll/storm_test.vcxproj +202 -0
- data/ext/stormlib/StormLib/storm_dll/storm_test.vcxproj.filters +22 -0
- data/ext/stormlib/StormLib/test/StormTest.cpp +4393 -0
- data/ext/stormlib/StormLib/test/TLogHelper.cpp +567 -0
- data/ext/stormlib/StormLib/test/stormlib-test-001.txt +164 -0
- data/ext/stormlib/extconf.rb +0 -2
- data/lib/stormlib/version.rb +1 -1
- data/stormlib.gemspec +1 -1
- metadata +621 -2
@@ -0,0 +1,2928 @@
|
|
1
|
+
/*****************************************************************************/
|
2
|
+
/* FileStream.cpp Copyright (c) Ladislav Zezula 2010 */
|
3
|
+
/*---------------------------------------------------------------------------*/
|
4
|
+
/* File stream support for StormLib */
|
5
|
+
/* */
|
6
|
+
/* Windows support: Written by Ladislav Zezula */
|
7
|
+
/* Mac support: Written by Sam Wilkins */
|
8
|
+
/* Linux support: Written by Sam Wilkins and Ivan Komissarov */
|
9
|
+
/* Big-endian: Written & debugged by Sam Wilkins */
|
10
|
+
/*---------------------------------------------------------------------------*/
|
11
|
+
/* Date Ver Who Comment */
|
12
|
+
/* -------- ---- --- ------- */
|
13
|
+
/* 11.06.10 1.00 Lad Derived from StormPortMac.cpp and StormPortLinux.cpp */
|
14
|
+
/*****************************************************************************/
|
15
|
+
|
16
|
+
#define __STORMLIB_SELF__
|
17
|
+
#include "StormLib.h"
|
18
|
+
#include "StormCommon.h"
|
19
|
+
#include "FileStream.h"
|
20
|
+
|
21
|
+
#ifdef _MSC_VER
|
22
|
+
#pragma comment(lib, "wininet.lib") // Internet functions for HTTP stream
|
23
|
+
#pragma warning(disable: 4800) // 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)
|
24
|
+
#endif
|
25
|
+
|
26
|
+
//-----------------------------------------------------------------------------
|
27
|
+
// Local defines
|
28
|
+
|
29
|
+
#ifndef INVALID_HANDLE_VALUE
|
30
|
+
#define INVALID_HANDLE_VALUE ((HANDLE)-1)
|
31
|
+
#endif
|
32
|
+
|
33
|
+
//-----------------------------------------------------------------------------
|
34
|
+
// Local functions - platform-specific functions
|
35
|
+
|
36
|
+
#ifndef STORMLIB_WINDOWS
|
37
|
+
|
38
|
+
#ifndef STORMLIB_WIIU
|
39
|
+
static thread_local DWORD dwLastError = ERROR_SUCCESS;
|
40
|
+
#else
|
41
|
+
static DWORD dwLastError = ERROR_SUCCESS;
|
42
|
+
#endif
|
43
|
+
|
44
|
+
DWORD GetLastError()
|
45
|
+
{
|
46
|
+
return dwLastError;
|
47
|
+
}
|
48
|
+
|
49
|
+
void SetLastError(DWORD dwErrCode)
|
50
|
+
{
|
51
|
+
dwLastError = dwErrCode;
|
52
|
+
}
|
53
|
+
#endif
|
54
|
+
|
55
|
+
static DWORD StringToInt(const char * szString)
|
56
|
+
{
|
57
|
+
DWORD dwValue = 0;
|
58
|
+
|
59
|
+
while('0' <= szString[0] && szString[0] <= '9')
|
60
|
+
{
|
61
|
+
dwValue = (dwValue * 10) + (szString[0] - '0');
|
62
|
+
szString++;
|
63
|
+
}
|
64
|
+
|
65
|
+
return dwValue;
|
66
|
+
}
|
67
|
+
|
68
|
+
static void CreateNameWithSuffix(LPTSTR szBuffer, size_t cchMaxChars, LPCTSTR szName, unsigned int nValue)
|
69
|
+
{
|
70
|
+
LPTSTR szBufferEnd = szBuffer + cchMaxChars - 1;
|
71
|
+
|
72
|
+
// Copy the name
|
73
|
+
while(szBuffer < szBufferEnd && szName[0] != 0)
|
74
|
+
*szBuffer++ = *szName++;
|
75
|
+
|
76
|
+
// Append "."
|
77
|
+
if(szBuffer < szBufferEnd)
|
78
|
+
*szBuffer++ = '.';
|
79
|
+
|
80
|
+
// Append the number
|
81
|
+
IntToString(szBuffer, szBufferEnd - szBuffer + 1, nValue);
|
82
|
+
}
|
83
|
+
|
84
|
+
//-----------------------------------------------------------------------------
|
85
|
+
// Dummy init function
|
86
|
+
|
87
|
+
static void BaseNone_Init(TFileStream *)
|
88
|
+
{
|
89
|
+
// Nothing here
|
90
|
+
}
|
91
|
+
|
92
|
+
//-----------------------------------------------------------------------------
|
93
|
+
// Local functions - base file support
|
94
|
+
|
95
|
+
static bool BaseFile_Create(TFileStream * pStream)
|
96
|
+
{
|
97
|
+
#ifdef STORMLIB_WINDOWS
|
98
|
+
{
|
99
|
+
DWORD dwWriteShare = (pStream->dwFlags & STREAM_FLAG_WRITE_SHARE) ? FILE_SHARE_WRITE : 0;
|
100
|
+
|
101
|
+
pStream->Base.File.hFile = CreateFile(pStream->szFileName,
|
102
|
+
GENERIC_READ | GENERIC_WRITE,
|
103
|
+
dwWriteShare | FILE_SHARE_READ,
|
104
|
+
NULL,
|
105
|
+
CREATE_ALWAYS,
|
106
|
+
0,
|
107
|
+
NULL);
|
108
|
+
if(pStream->Base.File.hFile == INVALID_HANDLE_VALUE)
|
109
|
+
return false;
|
110
|
+
}
|
111
|
+
#endif
|
112
|
+
|
113
|
+
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
|
114
|
+
{
|
115
|
+
intptr_t handle;
|
116
|
+
|
117
|
+
handle = open(pStream->szFileName, O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
|
118
|
+
if(handle == -1)
|
119
|
+
{
|
120
|
+
pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
|
121
|
+
dwLastError = errno;
|
122
|
+
return false;
|
123
|
+
}
|
124
|
+
|
125
|
+
pStream->Base.File.hFile = (HANDLE)handle;
|
126
|
+
}
|
127
|
+
#endif
|
128
|
+
|
129
|
+
// Reset the file size and position
|
130
|
+
pStream->Base.File.FileSize = 0;
|
131
|
+
pStream->Base.File.FilePos = 0;
|
132
|
+
return true;
|
133
|
+
}
|
134
|
+
|
135
|
+
static bool BaseFile_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD dwStreamFlags)
|
136
|
+
{
|
137
|
+
#ifdef STORMLIB_WINDOWS
|
138
|
+
{
|
139
|
+
ULARGE_INTEGER FileSize;
|
140
|
+
DWORD dwWriteAccess = (dwStreamFlags & STREAM_FLAG_READ_ONLY) ? 0 : FILE_WRITE_DATA | FILE_APPEND_DATA | FILE_WRITE_ATTRIBUTES;
|
141
|
+
DWORD dwWriteShare = (dwStreamFlags & STREAM_FLAG_WRITE_SHARE) ? FILE_SHARE_WRITE : 0;
|
142
|
+
|
143
|
+
// Open the file
|
144
|
+
pStream->Base.File.hFile = CreateFile(szFileName,
|
145
|
+
FILE_READ_DATA | FILE_READ_ATTRIBUTES | dwWriteAccess,
|
146
|
+
FILE_SHARE_READ | dwWriteShare,
|
147
|
+
NULL,
|
148
|
+
OPEN_EXISTING,
|
149
|
+
0,
|
150
|
+
NULL);
|
151
|
+
if(pStream->Base.File.hFile == INVALID_HANDLE_VALUE)
|
152
|
+
return false;
|
153
|
+
|
154
|
+
// Query the file size
|
155
|
+
FileSize.LowPart = GetFileSize(pStream->Base.File.hFile, &FileSize.HighPart);
|
156
|
+
pStream->Base.File.FileSize = FileSize.QuadPart;
|
157
|
+
|
158
|
+
// Query last write time
|
159
|
+
GetFileTime(pStream->Base.File.hFile, NULL, NULL, (LPFILETIME)&pStream->Base.File.FileTime);
|
160
|
+
}
|
161
|
+
#endif
|
162
|
+
|
163
|
+
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
|
164
|
+
{
|
165
|
+
struct stat64 fileinfo;
|
166
|
+
int oflag = (dwStreamFlags & STREAM_FLAG_READ_ONLY) ? O_RDONLY : O_RDWR;
|
167
|
+
intptr_t handle;
|
168
|
+
|
169
|
+
// Open the file
|
170
|
+
handle = open(szFileName, oflag | O_LARGEFILE);
|
171
|
+
if(handle == -1)
|
172
|
+
{
|
173
|
+
pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
|
174
|
+
dwLastError = errno;
|
175
|
+
return false;
|
176
|
+
}
|
177
|
+
|
178
|
+
// Get the file size
|
179
|
+
if(fstat64(handle, &fileinfo) == -1)
|
180
|
+
{
|
181
|
+
pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
|
182
|
+
dwLastError = errno;
|
183
|
+
close(handle);
|
184
|
+
return false;
|
185
|
+
}
|
186
|
+
|
187
|
+
// time_t is number of seconds since 1.1.1970, UTC.
|
188
|
+
// 1 second = 10000000 (decimal) in FILETIME
|
189
|
+
// Set the start to 1.1.1970 00:00:00
|
190
|
+
pStream->Base.File.FileTime = 0x019DB1DED53E8000ULL + (10000000 * fileinfo.st_mtime);
|
191
|
+
pStream->Base.File.FileSize = (ULONGLONG)fileinfo.st_size;
|
192
|
+
pStream->Base.File.hFile = (HANDLE)handle;
|
193
|
+
}
|
194
|
+
#endif
|
195
|
+
|
196
|
+
// Reset the file position
|
197
|
+
pStream->Base.File.FilePos = 0;
|
198
|
+
return true;
|
199
|
+
}
|
200
|
+
|
201
|
+
static bool BaseFile_Read(
|
202
|
+
TFileStream * pStream, // Pointer to an open stream
|
203
|
+
ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position
|
204
|
+
void * pvBuffer, // Pointer to data to be read
|
205
|
+
DWORD dwBytesToRead) // Number of bytes to read from the file
|
206
|
+
{
|
207
|
+
ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
|
208
|
+
DWORD dwBytesRead = 0; // Must be set by platform-specific code
|
209
|
+
|
210
|
+
#ifdef STORMLIB_WINDOWS
|
211
|
+
{
|
212
|
+
// Note: StormLib no longer supports Windows 9x.
|
213
|
+
// Thus, we can use the OVERLAPPED structure to specify
|
214
|
+
// file offset to read from file. This allows us to skip
|
215
|
+
// one system call to SetFilePointer
|
216
|
+
|
217
|
+
// Update the byte offset
|
218
|
+
pStream->Base.File.FilePos = ByteOffset;
|
219
|
+
|
220
|
+
// Read the data
|
221
|
+
if(dwBytesToRead != 0)
|
222
|
+
{
|
223
|
+
OVERLAPPED Overlapped;
|
224
|
+
|
225
|
+
Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
|
226
|
+
Overlapped.Offset = (DWORD)ByteOffset;
|
227
|
+
Overlapped.hEvent = NULL;
|
228
|
+
if(!ReadFile(pStream->Base.File.hFile, pvBuffer, dwBytesToRead, &dwBytesRead, &Overlapped))
|
229
|
+
return false;
|
230
|
+
}
|
231
|
+
}
|
232
|
+
#endif
|
233
|
+
|
234
|
+
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
|
235
|
+
{
|
236
|
+
ssize_t bytes_read;
|
237
|
+
|
238
|
+
// If the byte offset is different from the current file position,
|
239
|
+
// we have to update the file position xxx
|
240
|
+
if(ByteOffset != pStream->Base.File.FilePos)
|
241
|
+
{
|
242
|
+
lseek64((intptr_t)pStream->Base.File.hFile, (off64_t)(ByteOffset), SEEK_SET);
|
243
|
+
pStream->Base.File.FilePos = ByteOffset;
|
244
|
+
}
|
245
|
+
|
246
|
+
// Perform the read operation
|
247
|
+
if(dwBytesToRead != 0)
|
248
|
+
{
|
249
|
+
bytes_read = read((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToRead);
|
250
|
+
if(bytes_read == -1)
|
251
|
+
{
|
252
|
+
dwLastError = errno;
|
253
|
+
return false;
|
254
|
+
}
|
255
|
+
|
256
|
+
dwBytesRead = (DWORD)(size_t)bytes_read;
|
257
|
+
}
|
258
|
+
}
|
259
|
+
#endif
|
260
|
+
|
261
|
+
// Increment the current file position by number of bytes read
|
262
|
+
// If the number of bytes read doesn't match to required amount, return false
|
263
|
+
pStream->Base.File.FilePos = ByteOffset + dwBytesRead;
|
264
|
+
if(dwBytesRead != dwBytesToRead)
|
265
|
+
SetLastError(ERROR_HANDLE_EOF);
|
266
|
+
return (dwBytesRead == dwBytesToRead);
|
267
|
+
}
|
268
|
+
|
269
|
+
/**
|
270
|
+
* \a pStream Pointer to an open stream
|
271
|
+
* \a pByteOffset Pointer to file byte offset. If NULL, writes to current position
|
272
|
+
* \a pvBuffer Pointer to data to be written
|
273
|
+
* \a dwBytesToWrite Number of bytes to write to the file
|
274
|
+
*/
|
275
|
+
|
276
|
+
static bool BaseFile_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void * pvBuffer, DWORD dwBytesToWrite)
|
277
|
+
{
|
278
|
+
ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.File.FilePos;
|
279
|
+
DWORD dwBytesWritten = 0; // Must be set by platform-specific code
|
280
|
+
|
281
|
+
#ifdef STORMLIB_WINDOWS
|
282
|
+
{
|
283
|
+
// Note: StormLib no longer supports Windows 9x.
|
284
|
+
// Thus, we can use the OVERLAPPED structure to specify
|
285
|
+
// file offset to read from file. This allows us to skip
|
286
|
+
// one system call to SetFilePointer
|
287
|
+
|
288
|
+
// Update the byte offset
|
289
|
+
pStream->Base.File.FilePos = ByteOffset;
|
290
|
+
|
291
|
+
// Read the data
|
292
|
+
if(dwBytesToWrite != 0)
|
293
|
+
{
|
294
|
+
OVERLAPPED Overlapped;
|
295
|
+
|
296
|
+
Overlapped.OffsetHigh = (DWORD)(ByteOffset >> 32);
|
297
|
+
Overlapped.Offset = (DWORD)ByteOffset;
|
298
|
+
Overlapped.hEvent = NULL;
|
299
|
+
if(!WriteFile(pStream->Base.File.hFile, pvBuffer, dwBytesToWrite, &dwBytesWritten, &Overlapped))
|
300
|
+
return false;
|
301
|
+
}
|
302
|
+
}
|
303
|
+
#endif
|
304
|
+
|
305
|
+
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
|
306
|
+
{
|
307
|
+
ssize_t bytes_written;
|
308
|
+
|
309
|
+
// If the byte offset is different from the current file position,
|
310
|
+
// we have to update the file position
|
311
|
+
if(ByteOffset != pStream->Base.File.FilePos)
|
312
|
+
{
|
313
|
+
lseek64((intptr_t)pStream->Base.File.hFile, (off64_t)(ByteOffset), SEEK_SET);
|
314
|
+
pStream->Base.File.FilePos = ByteOffset;
|
315
|
+
}
|
316
|
+
|
317
|
+
// Perform the read operation
|
318
|
+
bytes_written = write((intptr_t)pStream->Base.File.hFile, pvBuffer, (size_t)dwBytesToWrite);
|
319
|
+
if(bytes_written == -1)
|
320
|
+
{
|
321
|
+
dwLastError = errno;
|
322
|
+
return false;
|
323
|
+
}
|
324
|
+
|
325
|
+
dwBytesWritten = (DWORD)(size_t)bytes_written;
|
326
|
+
}
|
327
|
+
#endif
|
328
|
+
|
329
|
+
// Increment the current file position by number of bytes read
|
330
|
+
pStream->Base.File.FilePos = ByteOffset + dwBytesWritten;
|
331
|
+
|
332
|
+
// Also modify the file size, if needed
|
333
|
+
if(pStream->Base.File.FilePos > pStream->Base.File.FileSize)
|
334
|
+
pStream->Base.File.FileSize = pStream->Base.File.FilePos;
|
335
|
+
|
336
|
+
if(dwBytesWritten != dwBytesToWrite)
|
337
|
+
SetLastError(ERROR_DISK_FULL);
|
338
|
+
return (dwBytesWritten == dwBytesToWrite);
|
339
|
+
}
|
340
|
+
|
341
|
+
/**
|
342
|
+
* \a pStream Pointer to an open stream
|
343
|
+
* \a NewFileSize New size of the file
|
344
|
+
*/
|
345
|
+
static bool BaseFile_Resize(TFileStream * pStream, ULONGLONG NewFileSize)
|
346
|
+
{
|
347
|
+
#ifdef STORMLIB_WINDOWS
|
348
|
+
{
|
349
|
+
LONG FileSizeHi = (LONG)(NewFileSize >> 32);
|
350
|
+
LONG FileSizeLo;
|
351
|
+
DWORD dwNewPos;
|
352
|
+
bool bResult;
|
353
|
+
|
354
|
+
// Set the position at the new file size
|
355
|
+
dwNewPos = SetFilePointer(pStream->Base.File.hFile, (LONG)NewFileSize, &FileSizeHi, FILE_BEGIN);
|
356
|
+
if(dwNewPos == INVALID_SET_FILE_POINTER && GetLastError() != ERROR_SUCCESS)
|
357
|
+
return false;
|
358
|
+
|
359
|
+
// Set the current file pointer as the end of the file
|
360
|
+
bResult = (bool)SetEndOfFile(pStream->Base.File.hFile);
|
361
|
+
if(bResult)
|
362
|
+
pStream->Base.File.FileSize = NewFileSize;
|
363
|
+
|
364
|
+
// Restore the file position
|
365
|
+
FileSizeHi = (LONG)(pStream->Base.File.FilePos >> 32);
|
366
|
+
FileSizeLo = (LONG)(pStream->Base.File.FilePos);
|
367
|
+
SetFilePointer(pStream->Base.File.hFile, FileSizeLo, &FileSizeHi, FILE_BEGIN);
|
368
|
+
return bResult;
|
369
|
+
}
|
370
|
+
#endif
|
371
|
+
|
372
|
+
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
|
373
|
+
{
|
374
|
+
if(ftruncate64((intptr_t)pStream->Base.File.hFile, (off64_t)NewFileSize) == -1)
|
375
|
+
{
|
376
|
+
dwLastError = errno;
|
377
|
+
return false;
|
378
|
+
}
|
379
|
+
|
380
|
+
pStream->Base.File.FileSize = NewFileSize;
|
381
|
+
return true;
|
382
|
+
}
|
383
|
+
#endif
|
384
|
+
}
|
385
|
+
|
386
|
+
// Gives the current file size
|
387
|
+
static bool BaseFile_GetSize(TFileStream * pStream, ULONGLONG * pFileSize)
|
388
|
+
{
|
389
|
+
// Note: Used by all thre base providers.
|
390
|
+
// Requires the TBaseData union to have the same layout for all three base providers
|
391
|
+
*pFileSize = pStream->Base.File.FileSize;
|
392
|
+
return true;
|
393
|
+
}
|
394
|
+
|
395
|
+
// Gives the current file position
|
396
|
+
static bool BaseFile_GetPos(TFileStream * pStream, ULONGLONG * pByteOffset)
|
397
|
+
{
|
398
|
+
// Note: Used by all thre base providers.
|
399
|
+
// Requires the TBaseData union to have the same layout for all three base providers
|
400
|
+
*pByteOffset = pStream->Base.File.FilePos;
|
401
|
+
return true;
|
402
|
+
}
|
403
|
+
|
404
|
+
// Renames the file pointed by pStream so that it contains data from pNewStream
|
405
|
+
static bool BaseFile_Replace(TFileStream * pStream, TFileStream * pNewStream)
|
406
|
+
{
|
407
|
+
#ifdef STORMLIB_WINDOWS
|
408
|
+
// Delete the original stream file. Don't check the result value,
|
409
|
+
// because if the file doesn't exist, it would fail
|
410
|
+
DeleteFile(pStream->szFileName);
|
411
|
+
|
412
|
+
// Rename the new file to the old stream's file
|
413
|
+
return (bool)MoveFile(pNewStream->szFileName, pStream->szFileName);
|
414
|
+
#endif
|
415
|
+
|
416
|
+
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
|
417
|
+
// "rename" on Linux also works if the target file exists
|
418
|
+
if(rename(pNewStream->szFileName, pStream->szFileName) == -1)
|
419
|
+
{
|
420
|
+
dwLastError = errno;
|
421
|
+
return false;
|
422
|
+
}
|
423
|
+
|
424
|
+
return true;
|
425
|
+
#endif
|
426
|
+
}
|
427
|
+
|
428
|
+
static void BaseFile_Close(TFileStream * pStream)
|
429
|
+
{
|
430
|
+
if(pStream->Base.File.hFile != INVALID_HANDLE_VALUE)
|
431
|
+
{
|
432
|
+
#ifdef STORMLIB_WINDOWS
|
433
|
+
CloseHandle(pStream->Base.File.hFile);
|
434
|
+
#endif
|
435
|
+
|
436
|
+
#if defined(STORMLIB_MAC) || defined(STORMLIB_LINUX)
|
437
|
+
close((intptr_t)pStream->Base.File.hFile);
|
438
|
+
#endif
|
439
|
+
}
|
440
|
+
|
441
|
+
// Also invalidate the handle
|
442
|
+
pStream->Base.File.hFile = INVALID_HANDLE_VALUE;
|
443
|
+
}
|
444
|
+
|
445
|
+
// Initializes base functions for the disk file
|
446
|
+
static void BaseFile_Init(TFileStream * pStream)
|
447
|
+
{
|
448
|
+
pStream->BaseCreate = BaseFile_Create;
|
449
|
+
pStream->BaseOpen = BaseFile_Open;
|
450
|
+
pStream->BaseRead = BaseFile_Read;
|
451
|
+
pStream->BaseWrite = BaseFile_Write;
|
452
|
+
pStream->BaseResize = BaseFile_Resize;
|
453
|
+
pStream->BaseGetSize = BaseFile_GetSize;
|
454
|
+
pStream->BaseGetPos = BaseFile_GetPos;
|
455
|
+
pStream->BaseClose = BaseFile_Close;
|
456
|
+
}
|
457
|
+
|
458
|
+
//-----------------------------------------------------------------------------
|
459
|
+
// Local functions - base memory-mapped file support
|
460
|
+
|
461
|
+
#ifdef STORMLIB_WINDOWS
|
462
|
+
|
463
|
+
typedef struct _SECTION_BASIC_INFORMATION
|
464
|
+
{
|
465
|
+
PVOID BaseAddress;
|
466
|
+
ULONG Attributes;
|
467
|
+
LARGE_INTEGER Size;
|
468
|
+
} SECTION_BASIC_INFORMATION, *PSECTION_BASIC_INFORMATION;
|
469
|
+
|
470
|
+
typedef ULONG (WINAPI * NTQUERYSECTION)(
|
471
|
+
IN HANDLE SectionHandle,
|
472
|
+
IN ULONG SectionInformationClass,
|
473
|
+
OUT PVOID SectionInformation,
|
474
|
+
IN SIZE_T Length,
|
475
|
+
OUT PSIZE_T ResultLength);
|
476
|
+
|
477
|
+
static bool RetrieveFileMappingSize(HANDLE hSection, ULARGE_INTEGER & RefFileSize)
|
478
|
+
{
|
479
|
+
SECTION_BASIC_INFORMATION BasicInfo = {0};
|
480
|
+
NTQUERYSECTION PfnQuerySection;
|
481
|
+
HMODULE hNtdll;
|
482
|
+
SIZE_T ReturnLength = 0;
|
483
|
+
|
484
|
+
if((hNtdll = GetModuleHandle(_T("ntdll.dll"))) != NULL)
|
485
|
+
{
|
486
|
+
PfnQuerySection = (NTQUERYSECTION)GetProcAddress(hNtdll, "NtQuerySection");
|
487
|
+
if(PfnQuerySection != NULL)
|
488
|
+
{
|
489
|
+
if(PfnQuerySection(hSection, 0, &BasicInfo, sizeof(SECTION_BASIC_INFORMATION), &ReturnLength) == 0)
|
490
|
+
{
|
491
|
+
RefFileSize.HighPart = BasicInfo.Size.HighPart;
|
492
|
+
RefFileSize.LowPart = BasicInfo.Size.LowPart;
|
493
|
+
return true;
|
494
|
+
}
|
495
|
+
}
|
496
|
+
}
|
497
|
+
|
498
|
+
return false;
|
499
|
+
}
|
500
|
+
#endif
|
501
|
+
|
502
|
+
static bool BaseMap_Open(TFileStream * pStream, LPCTSTR szFileName, DWORD dwStreamFlags)
|
503
|
+
{
|
504
|
+
#ifdef STORMLIB_WINDOWS
|
505
|
+
|
506
|
+
ULARGE_INTEGER FileSize = {0};
|
507
|
+
HANDLE hFile = INVALID_HANDLE_VALUE;
|
508
|
+
HANDLE hMap = NULL;
|
509
|
+
bool bResult = false;
|
510
|
+
|
511
|
+
// Keep compilers happy
|
512
|
+
STORMLIB_UNUSED(dwStreamFlags);
|
513
|
+
|
514
|
+
// 1) Try to treat "szFileName" as a section name
|
515
|
+
hMap = OpenFileMapping(SECTION_QUERY | FILE_MAP_READ, FALSE, szFileName);
|
516
|
+
if(hMap != NULL)
|
517
|
+
{
|
518
|
+
// Try to retrieve the size of the mapping
|
519
|
+
if(!RetrieveFileMappingSize(hMap, FileSize))
|
520
|
+
{
|
521
|
+
CloseHandle(hMap);
|
522
|
+
hMap = NULL;
|
523
|
+
}
|
524
|
+
}
|
525
|
+
|
526
|
+
// 2) Treat the name as file name
|
527
|
+
else
|
528
|
+
{
|
529
|
+
hFile = CreateFile(szFileName, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
|
530
|
+
if(hFile != INVALID_HANDLE_VALUE)
|
531
|
+
{
|
532
|
+
// Retrieve file size. Don't allow mapping file of a zero size.
|
533
|
+
FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart);
|
534
|
+
if(FileSize.QuadPart != 0)
|
535
|
+
{
|
536
|
+
// Now create file mapping over the file
|
537
|
+
hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL);
|
538
|
+
}
|
539
|
+
}
|
540
|
+
}
|
541
|
+
|
542
|
+
// Did it succeed?
|
543
|
+
if(hMap != NULL)
|
544
|
+
{
|
545
|
+
// Map the entire view into memory
|
546
|
+
// Note that this operation will fail if the file can't fit
|
547
|
+
// into usermode address space
|
548
|
+
pStream->Base.Map.pbFile = (LPBYTE)MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0);
|
549
|
+
if(pStream->Base.Map.pbFile != NULL)
|
550
|
+
{
|
551
|
+
// Retrieve file time. If it's named section, put 0
|
552
|
+
if(hFile != INVALID_HANDLE_VALUE)
|
553
|
+
GetFileTime(hFile, NULL, NULL, (LPFILETIME)&pStream->Base.Map.FileTime);
|
554
|
+
|
555
|
+
// Retrieve file size and position
|
556
|
+
pStream->Base.Map.FileSize = FileSize.QuadPart;
|
557
|
+
pStream->Base.Map.FilePos = 0;
|
558
|
+
bResult = true;
|
559
|
+
}
|
560
|
+
|
561
|
+
// Close the map handle
|
562
|
+
CloseHandle(hMap);
|
563
|
+
}
|
564
|
+
|
565
|
+
// Close the file handle
|
566
|
+
if(hFile != INVALID_HANDLE_VALUE)
|
567
|
+
CloseHandle(hFile);
|
568
|
+
|
569
|
+
// Return the result of the operation
|
570
|
+
return bResult;
|
571
|
+
|
572
|
+
#elif defined(STORMLIB_HAS_MMAP)
|
573
|
+
|
574
|
+
struct stat64 fileinfo;
|
575
|
+
intptr_t handle;
|
576
|
+
bool bResult = false;
|
577
|
+
|
578
|
+
// Open the file
|
579
|
+
handle = open(szFileName, O_RDONLY);
|
580
|
+
if(handle != -1)
|
581
|
+
{
|
582
|
+
// Get the file size
|
583
|
+
if(fstat64(handle, &fileinfo) != -1)
|
584
|
+
{
|
585
|
+
pStream->Base.Map.pbFile = (LPBYTE)mmap(NULL, (size_t)fileinfo.st_size, PROT_READ, MAP_PRIVATE, handle, 0);
|
586
|
+
if(pStream->Base.Map.pbFile != NULL)
|
587
|
+
{
|
588
|
+
// time_t is number of seconds since 1.1.1970, UTC.
|
589
|
+
// 1 second = 10000000 (decimal) in FILETIME
|
590
|
+
// Set the start to 1.1.1970 00:00:00
|
591
|
+
pStream->Base.Map.FileTime = 0x019DB1DED53E8000ULL + (10000000 * fileinfo.st_mtime);
|
592
|
+
pStream->Base.Map.FileSize = (ULONGLONG)fileinfo.st_size;
|
593
|
+
pStream->Base.Map.FilePos = 0;
|
594
|
+
bResult = true;
|
595
|
+
}
|
596
|
+
}
|
597
|
+
close(handle);
|
598
|
+
}
|
599
|
+
|
600
|
+
// Did the mapping fail?
|
601
|
+
if(bResult == false)
|
602
|
+
dwLastError = errno;
|
603
|
+
return bResult;
|
604
|
+
|
605
|
+
#else
|
606
|
+
|
607
|
+
// File mapping is not supported
|
608
|
+
return false;
|
609
|
+
|
610
|
+
#endif
|
611
|
+
}
|
612
|
+
|
613
|
+
static bool BaseMap_Read(
|
614
|
+
TFileStream * pStream, // Pointer to an open stream
|
615
|
+
ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position
|
616
|
+
void * pvBuffer, // Pointer to data to be read
|
617
|
+
DWORD dwBytesToRead) // Number of bytes to read from the file
|
618
|
+
{
|
619
|
+
ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.Map.FilePos;
|
620
|
+
|
621
|
+
// Do we have to read anything at all?
|
622
|
+
if(dwBytesToRead != 0)
|
623
|
+
{
|
624
|
+
// Don't allow reading past file size
|
625
|
+
if((ByteOffset + dwBytesToRead) > pStream->Base.Map.FileSize)
|
626
|
+
return false;
|
627
|
+
|
628
|
+
// Copy the required data
|
629
|
+
memcpy(pvBuffer, pStream->Base.Map.pbFile + (size_t)ByteOffset, dwBytesToRead);
|
630
|
+
}
|
631
|
+
|
632
|
+
// Move the current file position
|
633
|
+
pStream->Base.Map.FilePos += dwBytesToRead;
|
634
|
+
return true;
|
635
|
+
}
|
636
|
+
|
637
|
+
static void BaseMap_Close(TFileStream * pStream)
|
638
|
+
{
|
639
|
+
|
640
|
+
#ifdef STORMLIB_WINDOWS
|
641
|
+
|
642
|
+
if(pStream->Base.Map.pbFile != NULL)
|
643
|
+
UnmapViewOfFile(pStream->Base.Map.pbFile);
|
644
|
+
|
645
|
+
#elif defined(STORMLIB_HAS_MMAP)
|
646
|
+
|
647
|
+
if(pStream->Base.Map.pbFile != NULL)
|
648
|
+
munmap(pStream->Base.Map.pbFile, (size_t )pStream->Base.Map.FileSize);
|
649
|
+
|
650
|
+
#endif
|
651
|
+
|
652
|
+
pStream->Base.Map.pbFile = NULL;
|
653
|
+
}
|
654
|
+
|
655
|
+
// Initializes base functions for the mapped file
|
656
|
+
static void BaseMap_Init(TFileStream * pStream)
|
657
|
+
{
|
658
|
+
// Supply the file stream functions
|
659
|
+
pStream->BaseOpen = BaseMap_Open;
|
660
|
+
pStream->BaseRead = BaseMap_Read;
|
661
|
+
pStream->BaseGetSize = BaseFile_GetSize; // Reuse BaseFile function
|
662
|
+
pStream->BaseGetPos = BaseFile_GetPos; // Reuse BaseFile function
|
663
|
+
pStream->BaseClose = BaseMap_Close;
|
664
|
+
|
665
|
+
// Mapped files are read-only
|
666
|
+
pStream->dwFlags |= STREAM_FLAG_READ_ONLY;
|
667
|
+
}
|
668
|
+
|
669
|
+
//-----------------------------------------------------------------------------
|
670
|
+
// Local functions - base HTTP file support
|
671
|
+
|
672
|
+
static const TCHAR * BaseHttp_ExtractServerName(const TCHAR * szFileName, TCHAR * szServerName)
|
673
|
+
{
|
674
|
+
// Check for HTTP
|
675
|
+
if(!_tcsnicmp(szFileName, _T("http://"), 7))
|
676
|
+
szFileName += 7;
|
677
|
+
|
678
|
+
// Cut off the server name
|
679
|
+
if(szServerName != NULL)
|
680
|
+
{
|
681
|
+
while(szFileName[0] != 0 && szFileName[0] != _T('/'))
|
682
|
+
*szServerName++ = *szFileName++;
|
683
|
+
*szServerName = 0;
|
684
|
+
}
|
685
|
+
else
|
686
|
+
{
|
687
|
+
while(szFileName[0] != 0 && szFileName[0] != _T('/'))
|
688
|
+
szFileName++;
|
689
|
+
}
|
690
|
+
|
691
|
+
// Return the remainder
|
692
|
+
return szFileName;
|
693
|
+
}
|
694
|
+
|
695
|
+
static bool BaseHttp_Open(TFileStream * pStream, const TCHAR * szFileName, DWORD dwStreamFlags)
|
696
|
+
{
|
697
|
+
#ifdef STORMLIB_WINDOWS
|
698
|
+
|
699
|
+
HINTERNET hRequest;
|
700
|
+
DWORD dwTemp = 0;
|
701
|
+
|
702
|
+
// Keep compilers happy
|
703
|
+
STORMLIB_UNUSED(dwStreamFlags);
|
704
|
+
|
705
|
+
// Don't connect to the internet
|
706
|
+
if(!InternetGetConnectedState(&dwTemp, 0))
|
707
|
+
return false;
|
708
|
+
|
709
|
+
// Initiate the connection to the internet
|
710
|
+
pStream->Base.Http.hInternet = InternetOpen(_T("StormLib HTTP MPQ reader"),
|
711
|
+
INTERNET_OPEN_TYPE_PRECONFIG,
|
712
|
+
NULL,
|
713
|
+
NULL,
|
714
|
+
0);
|
715
|
+
if(pStream->Base.Http.hInternet != NULL)
|
716
|
+
{
|
717
|
+
TCHAR szServerName[MAX_PATH];
|
718
|
+
DWORD dwFlags = INTERNET_FLAG_KEEP_CONNECTION | INTERNET_FLAG_NO_UI | INTERNET_FLAG_NO_CACHE_WRITE;
|
719
|
+
|
720
|
+
// Initiate connection with the server
|
721
|
+
szFileName = BaseHttp_ExtractServerName(szFileName, szServerName);
|
722
|
+
pStream->Base.Http.hConnect = InternetConnect(pStream->Base.Http.hInternet,
|
723
|
+
szServerName,
|
724
|
+
INTERNET_DEFAULT_HTTP_PORT,
|
725
|
+
NULL,
|
726
|
+
NULL,
|
727
|
+
INTERNET_SERVICE_HTTP,
|
728
|
+
dwFlags,
|
729
|
+
0);
|
730
|
+
if(pStream->Base.Http.hConnect != NULL)
|
731
|
+
{
|
732
|
+
// Open HTTP request to the file
|
733
|
+
hRequest = HttpOpenRequest(pStream->Base.Http.hConnect, _T("GET"), szFileName, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
|
734
|
+
if(hRequest != NULL)
|
735
|
+
{
|
736
|
+
if(HttpSendRequest(hRequest, NULL, 0, NULL, 0))
|
737
|
+
{
|
738
|
+
ULONGLONG FileTime = 0;
|
739
|
+
DWORD dwFileSize = 0;
|
740
|
+
DWORD dwDataSize;
|
741
|
+
DWORD dwIndex = 0;
|
742
|
+
TCHAR StatusCode[0x08];
|
743
|
+
|
744
|
+
// Check if the file succeeded to open
|
745
|
+
dwDataSize = sizeof(StatusCode);
|
746
|
+
if(HttpQueryInfo(hRequest, HTTP_QUERY_STATUS_CODE, StatusCode, &dwDataSize, &dwIndex))
|
747
|
+
{
|
748
|
+
if(_tcscmp(StatusCode, _T("200")))
|
749
|
+
{
|
750
|
+
InternetCloseHandle(hRequest);
|
751
|
+
SetLastError(ERROR_FILE_NOT_FOUND);
|
752
|
+
return false;
|
753
|
+
}
|
754
|
+
}
|
755
|
+
|
756
|
+
// Check if the MPQ has Last Modified field
|
757
|
+
dwDataSize = sizeof(ULONGLONG);
|
758
|
+
if(HttpQueryInfo(hRequest, HTTP_QUERY_LAST_MODIFIED | HTTP_QUERY_FLAG_SYSTEMTIME, &FileTime, &dwDataSize, &dwIndex))
|
759
|
+
pStream->Base.Http.FileTime = FileTime;
|
760
|
+
|
761
|
+
// Verify if the server supports random access
|
762
|
+
dwDataSize = sizeof(DWORD);
|
763
|
+
if(HttpQueryInfo(hRequest, HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, &dwFileSize, &dwDataSize, &dwIndex))
|
764
|
+
{
|
765
|
+
if(dwFileSize != 0)
|
766
|
+
{
|
767
|
+
InternetCloseHandle(hRequest);
|
768
|
+
pStream->Base.Http.FileSize = dwFileSize;
|
769
|
+
pStream->Base.Http.FilePos = 0;
|
770
|
+
return true;
|
771
|
+
}
|
772
|
+
}
|
773
|
+
}
|
774
|
+
|
775
|
+
// Close the request
|
776
|
+
InternetCloseHandle(hRequest);
|
777
|
+
}
|
778
|
+
|
779
|
+
// Close the connection handle
|
780
|
+
InternetCloseHandle(pStream->Base.Http.hConnect);
|
781
|
+
pStream->Base.Http.hConnect = NULL;
|
782
|
+
}
|
783
|
+
|
784
|
+
// Close the internet handle
|
785
|
+
InternetCloseHandle(pStream->Base.Http.hInternet);
|
786
|
+
pStream->Base.Http.hInternet = NULL;
|
787
|
+
}
|
788
|
+
|
789
|
+
// If the file is not there or is not available for random access, report error
|
790
|
+
pStream->BaseClose(pStream);
|
791
|
+
return false;
|
792
|
+
|
793
|
+
#else
|
794
|
+
|
795
|
+
// Not supported
|
796
|
+
SetLastError(ERROR_NOT_SUPPORTED);
|
797
|
+
pStream = pStream;
|
798
|
+
return false;
|
799
|
+
|
800
|
+
#endif
|
801
|
+
}
|
802
|
+
|
803
|
+
static bool BaseHttp_Read(
|
804
|
+
TFileStream * pStream, // Pointer to an open stream
|
805
|
+
ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position
|
806
|
+
void * pvBuffer, // Pointer to data to be read
|
807
|
+
DWORD dwBytesToRead) // Number of bytes to read from the file
|
808
|
+
{
|
809
|
+
#ifdef STORMLIB_WINDOWS
|
810
|
+
ULONGLONG ByteOffset = (pByteOffset != NULL) ? *pByteOffset : pStream->Base.Http.FilePos;
|
811
|
+
DWORD dwTotalBytesRead = 0;
|
812
|
+
|
813
|
+
// Do we have to read anything at all?
|
814
|
+
if(dwBytesToRead != 0)
|
815
|
+
{
|
816
|
+
HINTERNET hRequest;
|
817
|
+
LPCTSTR szFileName;
|
818
|
+
LPBYTE pbBuffer = (LPBYTE)pvBuffer;
|
819
|
+
TCHAR szRangeRequest[0x80];
|
820
|
+
DWORD dwStartOffset = (DWORD)ByteOffset;
|
821
|
+
DWORD dwEndOffset = dwStartOffset + dwBytesToRead;
|
822
|
+
|
823
|
+
// Open HTTP request to the file
|
824
|
+
szFileName = BaseHttp_ExtractServerName(pStream->szFileName, NULL);
|
825
|
+
hRequest = HttpOpenRequest(pStream->Base.Http.hConnect, _T("GET"), szFileName, NULL, NULL, NULL, INTERNET_FLAG_NO_CACHE_WRITE, 0);
|
826
|
+
if(hRequest != NULL)
|
827
|
+
{
|
828
|
+
// Add range request to the HTTP headers
|
829
|
+
// http://www.clevercomponents.com/articles/article015/resuming.asp
|
830
|
+
wsprintf(szRangeRequest, _T("Range: bytes=%u-%u"), (unsigned int)dwStartOffset, (unsigned int)dwEndOffset);
|
831
|
+
HttpAddRequestHeaders(hRequest, szRangeRequest, 0xFFFFFFFF, HTTP_ADDREQ_FLAG_ADD_IF_NEW);
|
832
|
+
|
833
|
+
// Send the request to the server
|
834
|
+
if(HttpSendRequest(hRequest, NULL, 0, NULL, 0))
|
835
|
+
{
|
836
|
+
while(dwTotalBytesRead < dwBytesToRead)
|
837
|
+
{
|
838
|
+
DWORD dwBlockBytesToRead = dwBytesToRead - dwTotalBytesRead;
|
839
|
+
DWORD dwBlockBytesRead = 0;
|
840
|
+
|
841
|
+
// Read the block from the file
|
842
|
+
if(dwBlockBytesToRead > 0x200)
|
843
|
+
dwBlockBytesToRead = 0x200;
|
844
|
+
InternetReadFile(hRequest, pbBuffer, dwBlockBytesToRead, &dwBlockBytesRead);
|
845
|
+
|
846
|
+
// Check for end
|
847
|
+
if(dwBlockBytesRead == 0)
|
848
|
+
break;
|
849
|
+
|
850
|
+
// Move buffers
|
851
|
+
dwTotalBytesRead += dwBlockBytesRead;
|
852
|
+
pbBuffer += dwBlockBytesRead;
|
853
|
+
}
|
854
|
+
}
|
855
|
+
InternetCloseHandle(hRequest);
|
856
|
+
}
|
857
|
+
}
|
858
|
+
|
859
|
+
// Increment the current file position by number of bytes read
|
860
|
+
pStream->Base.Http.FilePos = ByteOffset + dwTotalBytesRead;
|
861
|
+
|
862
|
+
// If the number of bytes read doesn't match the required amount, return false
|
863
|
+
if(dwTotalBytesRead != dwBytesToRead)
|
864
|
+
SetLastError(ERROR_HANDLE_EOF);
|
865
|
+
return (dwTotalBytesRead == dwBytesToRead);
|
866
|
+
|
867
|
+
#else
|
868
|
+
|
869
|
+
// Not supported
|
870
|
+
pStream = pStream;
|
871
|
+
pByteOffset = pByteOffset;
|
872
|
+
pvBuffer = pvBuffer;
|
873
|
+
dwBytesToRead = dwBytesToRead;
|
874
|
+
SetLastError(ERROR_NOT_SUPPORTED);
|
875
|
+
return false;
|
876
|
+
|
877
|
+
#endif
|
878
|
+
}
|
879
|
+
|
880
|
+
static void BaseHttp_Close(TFileStream * pStream)
|
881
|
+
{
|
882
|
+
#ifdef STORMLIB_WINDOWS
|
883
|
+
if(pStream->Base.Http.hConnect != NULL)
|
884
|
+
InternetCloseHandle(pStream->Base.Http.hConnect);
|
885
|
+
pStream->Base.Http.hConnect = NULL;
|
886
|
+
|
887
|
+
if(pStream->Base.Http.hInternet != NULL)
|
888
|
+
InternetCloseHandle(pStream->Base.Http.hInternet);
|
889
|
+
pStream->Base.Http.hInternet = NULL;
|
890
|
+
#else
|
891
|
+
pStream = pStream;
|
892
|
+
#endif
|
893
|
+
}
|
894
|
+
|
895
|
+
// Initializes base functions for the mapped file
|
896
|
+
static void BaseHttp_Init(TFileStream * pStream)
|
897
|
+
{
|
898
|
+
// Supply the stream functions
|
899
|
+
pStream->BaseOpen = BaseHttp_Open;
|
900
|
+
pStream->BaseRead = BaseHttp_Read;
|
901
|
+
pStream->BaseGetSize = BaseFile_GetSize; // Reuse BaseFile function
|
902
|
+
pStream->BaseGetPos = BaseFile_GetPos; // Reuse BaseFile function
|
903
|
+
pStream->BaseClose = BaseHttp_Close;
|
904
|
+
|
905
|
+
// HTTP files are read-only
|
906
|
+
pStream->dwFlags |= STREAM_FLAG_READ_ONLY;
|
907
|
+
}
|
908
|
+
|
909
|
+
//-----------------------------------------------------------------------------
|
910
|
+
// Local functions - base block-based support
|
911
|
+
|
912
|
+
// Generic function that loads blocks from the file
|
913
|
+
// The function groups the block with the same availability,
|
914
|
+
// so the called BlockRead can finish the request in a single system call
|
915
|
+
static bool BlockStream_Read(
|
916
|
+
TBlockStream * pStream, // Pointer to an open stream
|
917
|
+
ULONGLONG * pByteOffset, // Pointer to file byte offset. If NULL, it reads from the current position
|
918
|
+
void * pvBuffer, // Pointer to data to be read
|
919
|
+
DWORD dwBytesToRead) // Number of bytes to read from the file
|
920
|
+
{
|
921
|
+
ULONGLONG BlockOffset0;
|
922
|
+
ULONGLONG BlockOffset;
|
923
|
+
ULONGLONG ByteOffset;
|
924
|
+
ULONGLONG EndOffset;
|
925
|
+
LPBYTE TransferBuffer;
|
926
|
+
LPBYTE BlockBuffer;
|
927
|
+
DWORD BlockBufferOffset; // Offset of the desired data in the block buffer
|
928
|
+
DWORD BytesNeeded; // Number of bytes that really need to be read
|
929
|
+
DWORD BlockSize = pStream->BlockSize;
|
930
|
+
DWORD BlockCount;
|
931
|
+
bool bPrevBlockAvailable;
|
932
|
+
bool bCallbackCalled = false;
|
933
|
+
bool bBlockAvailable;
|
934
|
+
bool bResult = true;
|
935
|
+
|
936
|
+
// The base block read function must be present
|
937
|
+
assert(pStream->BlockRead != NULL);
|
938
|
+
|
939
|
+
// NOP reading of zero bytes
|
940
|
+
if(dwBytesToRead == 0)
|
941
|
+
return true;
|
942
|
+
|
943
|
+
// Get the current position in the stream
|
944
|
+
ByteOffset = (pByteOffset != NULL) ? pByteOffset[0] : pStream->StreamPos;
|
945
|
+
EndOffset = ByteOffset + dwBytesToRead;
|
946
|
+
if(EndOffset > pStream->StreamSize)
|
947
|
+
{
|
948
|
+
SetLastError(ERROR_HANDLE_EOF);
|
949
|
+
return false;
|
950
|
+
}
|
951
|
+
|
952
|
+
// Calculate the block parameters
|
953
|
+
BlockOffset0 = BlockOffset = ByteOffset & ~((ULONGLONG)BlockSize - 1);
|
954
|
+
BlockCount = (DWORD)(((EndOffset - BlockOffset) + (BlockSize - 1)) / BlockSize);
|
955
|
+
BytesNeeded = (DWORD)(EndOffset - BlockOffset);
|
956
|
+
|
957
|
+
// Remember where we have our data
|
958
|
+
assert((BlockSize & (BlockSize - 1)) == 0);
|
959
|
+
BlockBufferOffset = (DWORD)(ByteOffset & (BlockSize - 1));
|
960
|
+
|
961
|
+
// Allocate buffer for reading blocks
|
962
|
+
TransferBuffer = BlockBuffer = STORM_ALLOC(BYTE, (BlockCount * BlockSize));
|
963
|
+
if(TransferBuffer == NULL)
|
964
|
+
{
|
965
|
+
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
966
|
+
return false;
|
967
|
+
}
|
968
|
+
|
969
|
+
// If all blocks are available, just read all blocks at once
|
970
|
+
if(pStream->IsComplete == 0)
|
971
|
+
{
|
972
|
+
// Now parse the blocks and send the block read request
|
973
|
+
// to all blocks with the same availability
|
974
|
+
assert(pStream->BlockCheck != NULL);
|
975
|
+
bPrevBlockAvailable = pStream->BlockCheck(pStream, BlockOffset);
|
976
|
+
|
977
|
+
// Loop as long as we have something to read
|
978
|
+
while(BlockOffset < EndOffset)
|
979
|
+
{
|
980
|
+
// Determine availability of the next block
|
981
|
+
bBlockAvailable = pStream->BlockCheck(pStream, BlockOffset);
|
982
|
+
|
983
|
+
// If the availability has changed, read all blocks up to this one
|
984
|
+
if(bBlockAvailable != bPrevBlockAvailable)
|
985
|
+
{
|
986
|
+
// Call the file stream callback, if the block is not available
|
987
|
+
if(pStream->pMaster && pStream->pfnCallback && bPrevBlockAvailable == false)
|
988
|
+
{
|
989
|
+
pStream->pfnCallback(pStream->UserData, BlockOffset0, (DWORD)(BlockOffset - BlockOffset0));
|
990
|
+
bCallbackCalled = true;
|
991
|
+
}
|
992
|
+
|
993
|
+
// Load the continuous blocks with the same availability
|
994
|
+
assert(BlockOffset > BlockOffset0);
|
995
|
+
bResult = pStream->BlockRead(pStream, BlockOffset0, BlockOffset, BlockBuffer, BytesNeeded, bPrevBlockAvailable);
|
996
|
+
if(!bResult)
|
997
|
+
break;
|
998
|
+
|
999
|
+
// Move the block offset
|
1000
|
+
BlockBuffer += (DWORD)(BlockOffset - BlockOffset0);
|
1001
|
+
BytesNeeded -= (DWORD)(BlockOffset - BlockOffset0);
|
1002
|
+
bPrevBlockAvailable = bBlockAvailable;
|
1003
|
+
BlockOffset0 = BlockOffset;
|
1004
|
+
}
|
1005
|
+
|
1006
|
+
// Move to the block offset in the stream
|
1007
|
+
BlockOffset += BlockSize;
|
1008
|
+
}
|
1009
|
+
|
1010
|
+
// If there is a block(s) remaining to be read, do it
|
1011
|
+
if(BlockOffset > BlockOffset0)
|
1012
|
+
{
|
1013
|
+
// Call the file stream callback, if the block is not available
|
1014
|
+
if(pStream->pMaster && pStream->pfnCallback && bPrevBlockAvailable == false)
|
1015
|
+
{
|
1016
|
+
pStream->pfnCallback(pStream->UserData, BlockOffset0, (DWORD)(BlockOffset - BlockOffset0));
|
1017
|
+
bCallbackCalled = true;
|
1018
|
+
}
|
1019
|
+
|
1020
|
+
// Read the complete blocks from the file
|
1021
|
+
if(BlockOffset > pStream->StreamSize)
|
1022
|
+
BlockOffset = pStream->StreamSize;
|
1023
|
+
bResult = pStream->BlockRead(pStream, BlockOffset0, BlockOffset, BlockBuffer, BytesNeeded, bPrevBlockAvailable);
|
1024
|
+
}
|
1025
|
+
}
|
1026
|
+
else
|
1027
|
+
{
|
1028
|
+
// Read the complete blocks from the file
|
1029
|
+
if(EndOffset > pStream->StreamSize)
|
1030
|
+
EndOffset = pStream->StreamSize;
|
1031
|
+
bResult = pStream->BlockRead(pStream, BlockOffset, EndOffset, BlockBuffer, BytesNeeded, true);
|
1032
|
+
}
|
1033
|
+
|
1034
|
+
// Now copy the data to the user buffer
|
1035
|
+
if(bResult)
|
1036
|
+
{
|
1037
|
+
memcpy(pvBuffer, TransferBuffer + BlockBufferOffset, dwBytesToRead);
|
1038
|
+
pStream->StreamPos = ByteOffset + dwBytesToRead;
|
1039
|
+
}
|
1040
|
+
else
|
1041
|
+
{
|
1042
|
+
// If the block read failed, set the last error
|
1043
|
+
SetLastError(ERROR_FILE_INCOMPLETE);
|
1044
|
+
}
|
1045
|
+
|
1046
|
+
// Call the callback to indicate we are done
|
1047
|
+
if(bCallbackCalled)
|
1048
|
+
pStream->pfnCallback(pStream->UserData, 0, 0);
|
1049
|
+
|
1050
|
+
// Free the block buffer and return
|
1051
|
+
STORM_FREE(TransferBuffer);
|
1052
|
+
return bResult;
|
1053
|
+
}
|
1054
|
+
|
1055
|
+
static bool BlockStream_GetSize(TFileStream * pStream, ULONGLONG * pFileSize)
|
1056
|
+
{
|
1057
|
+
*pFileSize = pStream->StreamSize;
|
1058
|
+
return true;
|
1059
|
+
}
|
1060
|
+
|
1061
|
+
static bool BlockStream_GetPos(TFileStream * pStream, ULONGLONG * pByteOffset)
|
1062
|
+
{
|
1063
|
+
*pByteOffset = pStream->StreamPos;
|
1064
|
+
return true;
|
1065
|
+
}
|
1066
|
+
|
1067
|
+
static void BlockStream_Close(TBlockStream * pStream)
|
1068
|
+
{
|
1069
|
+
// Free the data map, if any
|
1070
|
+
if(pStream->FileBitmap != NULL)
|
1071
|
+
STORM_FREE(pStream->FileBitmap);
|
1072
|
+
pStream->FileBitmap = NULL;
|
1073
|
+
|
1074
|
+
// Call the base class for closing the stream
|
1075
|
+
pStream->BaseClose(pStream);
|
1076
|
+
}
|
1077
|
+
|
1078
|
+
//-----------------------------------------------------------------------------
|
1079
|
+
// File stream allocation function
|
1080
|
+
|
1081
|
+
static STREAM_INIT StreamBaseInit[4] =
|
1082
|
+
{
|
1083
|
+
BaseFile_Init,
|
1084
|
+
BaseMap_Init,
|
1085
|
+
BaseHttp_Init,
|
1086
|
+
BaseNone_Init
|
1087
|
+
};
|
1088
|
+
|
1089
|
+
// This function allocates an empty structure for the file stream
|
1090
|
+
// The stream structure is created as flat block, variable length
|
1091
|
+
// The file name is placed after the end of the stream structure data
|
1092
|
+
static TFileStream * AllocateFileStream(
|
1093
|
+
const TCHAR * szFileName,
|
1094
|
+
size_t StreamSize,
|
1095
|
+
DWORD dwStreamFlags)
|
1096
|
+
{
|
1097
|
+
TFileStream * pMaster = NULL;
|
1098
|
+
TFileStream * pStream;
|
1099
|
+
const TCHAR * szNextFile = szFileName;
|
1100
|
+
size_t FileNameSize;
|
1101
|
+
|
1102
|
+
// Sanity check
|
1103
|
+
assert(StreamSize != 0);
|
1104
|
+
|
1105
|
+
// The caller can specify chain of files in the following form:
|
1106
|
+
// C:\archive.MPQ*http://www.server.com/MPQs/archive-server.MPQ
|
1107
|
+
// In that case, we use the part after "*" as master file name
|
1108
|
+
while(szNextFile[0] != 0 && szNextFile[0] != _T('*'))
|
1109
|
+
szNextFile++;
|
1110
|
+
FileNameSize = (size_t)((szNextFile - szFileName) * sizeof(TCHAR));
|
1111
|
+
|
1112
|
+
// If we have a next file, we need to open it as master stream
|
1113
|
+
// Note that we don't care if the master stream exists or not,
|
1114
|
+
// If it doesn't, later attempts to read missing file block will fail
|
1115
|
+
if(szNextFile[0] == _T('*'))
|
1116
|
+
{
|
1117
|
+
// Don't allow another master file in the string
|
1118
|
+
if(_tcschr(szNextFile + 1, _T('*')) != NULL)
|
1119
|
+
{
|
1120
|
+
SetLastError(ERROR_INVALID_PARAMETER);
|
1121
|
+
return NULL;
|
1122
|
+
}
|
1123
|
+
|
1124
|
+
// Open the master file
|
1125
|
+
pMaster = FileStream_OpenFile(szNextFile + 1, STREAM_FLAG_READ_ONLY);
|
1126
|
+
}
|
1127
|
+
|
1128
|
+
// Allocate the stream structure for the given stream type
|
1129
|
+
pStream = (TFileStream *)STORM_ALLOC(BYTE, StreamSize + FileNameSize + sizeof(TCHAR));
|
1130
|
+
if(pStream != NULL)
|
1131
|
+
{
|
1132
|
+
// Zero the entire structure
|
1133
|
+
memset(pStream, 0, StreamSize);
|
1134
|
+
pStream->pMaster = pMaster;
|
1135
|
+
pStream->dwFlags = dwStreamFlags;
|
1136
|
+
|
1137
|
+
// Initialize the file name
|
1138
|
+
pStream->szFileName = (TCHAR *)((BYTE *)pStream + StreamSize);
|
1139
|
+
memcpy(pStream->szFileName, szFileName, FileNameSize);
|
1140
|
+
pStream->szFileName[FileNameSize / sizeof(TCHAR)] = 0;
|
1141
|
+
|
1142
|
+
// Initialize the stream functions
|
1143
|
+
StreamBaseInit[dwStreamFlags & 0x03](pStream);
|
1144
|
+
}
|
1145
|
+
|
1146
|
+
return pStream;
|
1147
|
+
}
|
1148
|
+
|
1149
|
+
//-----------------------------------------------------------------------------
|
1150
|
+
// Local functions - flat stream support
|
1151
|
+
|
1152
|
+
static DWORD FlatStream_CheckFile(TBlockStream * pStream)
|
1153
|
+
{
|
1154
|
+
LPBYTE FileBitmap = (LPBYTE)pStream->FileBitmap;
|
1155
|
+
DWORD WholeByteCount = (pStream->BlockCount / 8);
|
1156
|
+
DWORD ExtraBitsCount = (pStream->BlockCount & 7);
|
1157
|
+
BYTE ExpectedValue;
|
1158
|
+
|
1159
|
+
// Verify the whole bytes - their value must be 0xFF
|
1160
|
+
for(DWORD i = 0; i < WholeByteCount; i++)
|
1161
|
+
{
|
1162
|
+
if(FileBitmap[i] != 0xFF)
|
1163
|
+
return 0;
|
1164
|
+
}
|
1165
|
+
|
1166
|
+
// If there are extra bits, calculate the mask
|
1167
|
+
if(ExtraBitsCount != 0)
|
1168
|
+
{
|
1169
|
+
ExpectedValue = (BYTE)((1 << ExtraBitsCount) - 1);
|
1170
|
+
if(FileBitmap[WholeByteCount] != ExpectedValue)
|
1171
|
+
return 0;
|
1172
|
+
}
|
1173
|
+
|
1174
|
+
// Yes, the file is complete
|
1175
|
+
return 1;
|
1176
|
+
}
|
1177
|
+
|
1178
|
+
static bool FlatStream_LoadBitmap(TBlockStream * pStream)
|
1179
|
+
{
|
1180
|
+
FILE_BITMAP_FOOTER Footer;
|
1181
|
+
ULONGLONG ByteOffset;
|
1182
|
+
LPBYTE FileBitmap;
|
1183
|
+
DWORD BlockCount;
|
1184
|
+
DWORD BitmapSize;
|
1185
|
+
|
1186
|
+
// Do not load the bitmap if we should not have to
|
1187
|
+
if(!(pStream->dwFlags & STREAM_FLAG_USE_BITMAP))
|
1188
|
+
return false;
|
1189
|
+
|
1190
|
+
// Only if the size is greater than size of bitmap footer
|
1191
|
+
if(pStream->Base.File.FileSize > sizeof(FILE_BITMAP_FOOTER))
|
1192
|
+
{
|
1193
|
+
// Load the bitmap footer
|
1194
|
+
ByteOffset = pStream->Base.File.FileSize - sizeof(FILE_BITMAP_FOOTER);
|
1195
|
+
if(pStream->BaseRead(pStream, &ByteOffset, &Footer, sizeof(FILE_BITMAP_FOOTER)))
|
1196
|
+
{
|
1197
|
+
// Make sure that the array is properly BSWAP-ed
|
1198
|
+
BSWAP_ARRAY32_UNSIGNED((LPDWORD)(&Footer), sizeof(FILE_BITMAP_FOOTER));
|
1199
|
+
|
1200
|
+
// Verify if there is actually a footer
|
1201
|
+
if(Footer.Signature == ID_FILE_BITMAP_FOOTER && Footer.Version == 0x03 && Footer.BlockSize != 0)
|
1202
|
+
{
|
1203
|
+
// Get the offset of the bitmap, number of blocks and size of the bitmap
|
1204
|
+
ByteOffset = MAKE_OFFSET64(Footer.MapOffsetHi, Footer.MapOffsetLo);
|
1205
|
+
BlockCount = (DWORD)(((ByteOffset - 1) / Footer.BlockSize) + 1);
|
1206
|
+
BitmapSize = ((BlockCount + 7) / 8);
|
1207
|
+
|
1208
|
+
// Check if the sizes match
|
1209
|
+
if(ByteOffset + BitmapSize + sizeof(FILE_BITMAP_FOOTER) == pStream->Base.File.FileSize)
|
1210
|
+
{
|
1211
|
+
// Allocate space for the bitmap
|
1212
|
+
FileBitmap = STORM_ALLOC(BYTE, BitmapSize);
|
1213
|
+
if(FileBitmap != NULL)
|
1214
|
+
{
|
1215
|
+
// Load the bitmap bits
|
1216
|
+
if(!pStream->BaseRead(pStream, &ByteOffset, FileBitmap, BitmapSize))
|
1217
|
+
{
|
1218
|
+
STORM_FREE(FileBitmap);
|
1219
|
+
return false;
|
1220
|
+
}
|
1221
|
+
|
1222
|
+
// Update the stream size
|
1223
|
+
pStream->BuildNumber = Footer.BuildNumber;
|
1224
|
+
pStream->StreamSize = ByteOffset;
|
1225
|
+
|
1226
|
+
// Fill the bitmap information
|
1227
|
+
pStream->FileBitmap = FileBitmap;
|
1228
|
+
pStream->BitmapSize = BitmapSize;
|
1229
|
+
pStream->BlockSize = Footer.BlockSize;
|
1230
|
+
pStream->BlockCount = BlockCount;
|
1231
|
+
pStream->IsComplete = FlatStream_CheckFile(pStream);
|
1232
|
+
return true;
|
1233
|
+
}
|
1234
|
+
}
|
1235
|
+
}
|
1236
|
+
}
|
1237
|
+
}
|
1238
|
+
|
1239
|
+
return false;
|
1240
|
+
}
|
1241
|
+
|
1242
|
+
static void FlatStream_UpdateBitmap(
|
1243
|
+
TBlockStream * pStream, // Pointer to an open stream
|
1244
|
+
ULONGLONG StartOffset,
|
1245
|
+
ULONGLONG EndOffset)
|
1246
|
+
{
|
1247
|
+
LPBYTE FileBitmap = (LPBYTE)pStream->FileBitmap;
|
1248
|
+
DWORD BlockIndex;
|
1249
|
+
DWORD BlockSize = pStream->BlockSize;
|
1250
|
+
DWORD ByteIndex;
|
1251
|
+
BYTE BitMask;
|
1252
|
+
|
1253
|
+
// Sanity checks
|
1254
|
+
assert((StartOffset & (BlockSize - 1)) == 0);
|
1255
|
+
assert(FileBitmap != NULL);
|
1256
|
+
|
1257
|
+
// Calculate the index of the block
|
1258
|
+
BlockIndex = (DWORD)(StartOffset / BlockSize);
|
1259
|
+
ByteIndex = (BlockIndex / 0x08);
|
1260
|
+
BitMask = (BYTE)(1 << (BlockIndex & 0x07));
|
1261
|
+
|
1262
|
+
// Set all bits for the specified range
|
1263
|
+
while(StartOffset < EndOffset)
|
1264
|
+
{
|
1265
|
+
// Set the bit
|
1266
|
+
FileBitmap[ByteIndex] |= BitMask;
|
1267
|
+
|
1268
|
+
// Move all
|
1269
|
+
StartOffset += BlockSize;
|
1270
|
+
ByteIndex += (BitMask >> 0x07);
|
1271
|
+
BitMask = (BitMask >> 0x07) | (BitMask << 0x01);
|
1272
|
+
}
|
1273
|
+
|
1274
|
+
// Increment the bitmap update count
|
1275
|
+
pStream->IsModified = 1;
|
1276
|
+
}
|
1277
|
+
|
1278
|
+
static bool FlatStream_BlockCheck(
|
1279
|
+
TBlockStream * pStream, // Pointer to an open stream
|
1280
|
+
ULONGLONG BlockOffset)
|
1281
|
+
{
|
1282
|
+
LPBYTE FileBitmap = (LPBYTE)pStream->FileBitmap;
|
1283
|
+
DWORD BlockIndex;
|
1284
|
+
BYTE BitMask;
|
1285
|
+
|
1286
|
+
// Sanity checks
|
1287
|
+
assert((BlockOffset & (pStream->BlockSize - 1)) == 0);
|
1288
|
+
assert(FileBitmap != NULL);
|
1289
|
+
|
1290
|
+
// Calculate the index of the block
|
1291
|
+
BlockIndex = (DWORD)(BlockOffset / pStream->BlockSize);
|
1292
|
+
BitMask = (BYTE)(1 << (BlockIndex & 0x07));
|
1293
|
+
|
1294
|
+
// Check if the bit is present
|
1295
|
+
return (FileBitmap[BlockIndex / 0x08] & BitMask) ? true : false;
|
1296
|
+
}
|
1297
|
+
|
1298
|
+
static bool FlatStream_BlockRead(
|
1299
|
+
TBlockStream * pStream, // Pointer to an open stream
|
1300
|
+
ULONGLONG StartOffset,
|
1301
|
+
ULONGLONG EndOffset,
|
1302
|
+
LPBYTE BlockBuffer,
|
1303
|
+
DWORD BytesNeeded,
|
1304
|
+
bool bAvailable)
|
1305
|
+
{
|
1306
|
+
DWORD BytesToRead = (DWORD)(EndOffset - StartOffset);
|
1307
|
+
|
1308
|
+
// The starting offset must be aligned to size of the block
|
1309
|
+
assert(pStream->FileBitmap != NULL);
|
1310
|
+
assert((StartOffset & (pStream->BlockSize - 1)) == 0);
|
1311
|
+
assert(StartOffset < EndOffset);
|
1312
|
+
|
1313
|
+
// If the blocks are not available, we need to load them from the master
|
1314
|
+
// and then save to the mirror
|
1315
|
+
if(bAvailable == false)
|
1316
|
+
{
|
1317
|
+
// If we have no master, we cannot satisfy read request
|
1318
|
+
if(pStream->pMaster == NULL)
|
1319
|
+
return false;
|
1320
|
+
|
1321
|
+
// Load the blocks from the master stream
|
1322
|
+
// Note that we always have to read complete blocks
|
1323
|
+
// so they get properly stored to the mirror stream
|
1324
|
+
if(!FileStream_Read(pStream->pMaster, &StartOffset, BlockBuffer, BytesToRead))
|
1325
|
+
return false;
|
1326
|
+
|
1327
|
+
// Store the loaded blocks to the mirror file.
|
1328
|
+
// Note that this operation is not required to succeed
|
1329
|
+
if(pStream->BaseWrite(pStream, &StartOffset, BlockBuffer, BytesToRead))
|
1330
|
+
FlatStream_UpdateBitmap(pStream, StartOffset, EndOffset);
|
1331
|
+
|
1332
|
+
return true;
|
1333
|
+
}
|
1334
|
+
else
|
1335
|
+
{
|
1336
|
+
if(BytesToRead > BytesNeeded)
|
1337
|
+
BytesToRead = BytesNeeded;
|
1338
|
+
return pStream->BaseRead(pStream, &StartOffset, BlockBuffer, BytesToRead);
|
1339
|
+
}
|
1340
|
+
}
|
1341
|
+
|
1342
|
+
static void FlatStream_Close(TBlockStream * pStream)
|
1343
|
+
{
|
1344
|
+
FILE_BITMAP_FOOTER Footer;
|
1345
|
+
|
1346
|
+
if(pStream->FileBitmap && pStream->IsModified)
|
1347
|
+
{
|
1348
|
+
// Write the file bitmap
|
1349
|
+
pStream->BaseWrite(pStream, &pStream->StreamSize, pStream->FileBitmap, pStream->BitmapSize);
|
1350
|
+
|
1351
|
+
// Prepare and write the file footer
|
1352
|
+
Footer.Signature = ID_FILE_BITMAP_FOOTER;
|
1353
|
+
Footer.Version = 3;
|
1354
|
+
Footer.BuildNumber = pStream->BuildNumber;
|
1355
|
+
Footer.MapOffsetLo = (DWORD)(pStream->StreamSize & 0xFFFFFFFF);
|
1356
|
+
Footer.MapOffsetHi = (DWORD)(pStream->StreamSize >> 0x20);
|
1357
|
+
Footer.BlockSize = pStream->BlockSize;
|
1358
|
+
BSWAP_ARRAY32_UNSIGNED(&Footer, sizeof(FILE_BITMAP_FOOTER));
|
1359
|
+
pStream->BaseWrite(pStream, NULL, &Footer, sizeof(FILE_BITMAP_FOOTER));
|
1360
|
+
}
|
1361
|
+
|
1362
|
+
// Close the base class
|
1363
|
+
BlockStream_Close(pStream);
|
1364
|
+
}
|
1365
|
+
|
1366
|
+
static bool FlatStream_CreateMirror(TBlockStream * pStream)
|
1367
|
+
{
|
1368
|
+
ULONGLONG MasterSize = 0;
|
1369
|
+
ULONGLONG MirrorSize = 0;
|
1370
|
+
LPBYTE FileBitmap = NULL;
|
1371
|
+
DWORD dwBitmapSize;
|
1372
|
+
DWORD dwBlockCount;
|
1373
|
+
bool bNeedCreateMirrorStream = true;
|
1374
|
+
bool bNeedResizeMirrorStream = true;
|
1375
|
+
|
1376
|
+
// Do we have master function and base creation function?
|
1377
|
+
if(pStream->pMaster == NULL || pStream->BaseCreate == NULL)
|
1378
|
+
return false;
|
1379
|
+
|
1380
|
+
// Retrieve the master file size, block count and bitmap size
|
1381
|
+
FileStream_GetSize(pStream->pMaster, &MasterSize);
|
1382
|
+
dwBlockCount = (DWORD)((MasterSize + DEFAULT_BLOCK_SIZE - 1) / DEFAULT_BLOCK_SIZE);
|
1383
|
+
dwBitmapSize = (DWORD)((dwBlockCount + 7) / 8);
|
1384
|
+
|
1385
|
+
// Setup stream size and position
|
1386
|
+
pStream->BuildNumber = DEFAULT_BUILD_NUMBER; // BUGBUG: Really???
|
1387
|
+
pStream->StreamSize = MasterSize;
|
1388
|
+
pStream->StreamPos = 0;
|
1389
|
+
|
1390
|
+
// Open the base stream for write access
|
1391
|
+
if(pStream->BaseOpen(pStream, pStream->szFileName, 0))
|
1392
|
+
{
|
1393
|
+
// If the file open succeeded, check if the file size matches required size
|
1394
|
+
pStream->BaseGetSize(pStream, &MirrorSize);
|
1395
|
+
if(MirrorSize == MasterSize + dwBitmapSize + sizeof(FILE_BITMAP_FOOTER))
|
1396
|
+
{
|
1397
|
+
// Attempt to load an existing file bitmap
|
1398
|
+
if(FlatStream_LoadBitmap(pStream))
|
1399
|
+
return true;
|
1400
|
+
|
1401
|
+
// We need to create new file bitmap
|
1402
|
+
bNeedResizeMirrorStream = false;
|
1403
|
+
}
|
1404
|
+
|
1405
|
+
// We need to create mirror stream
|
1406
|
+
bNeedCreateMirrorStream = false;
|
1407
|
+
}
|
1408
|
+
|
1409
|
+
// Create a new stream, if needed
|
1410
|
+
if(bNeedCreateMirrorStream)
|
1411
|
+
{
|
1412
|
+
if(!pStream->BaseCreate(pStream))
|
1413
|
+
return false;
|
1414
|
+
}
|
1415
|
+
|
1416
|
+
// If we need to, then resize the mirror stream
|
1417
|
+
if(bNeedResizeMirrorStream)
|
1418
|
+
{
|
1419
|
+
if(!pStream->BaseResize(pStream, MasterSize + dwBitmapSize + sizeof(FILE_BITMAP_FOOTER)))
|
1420
|
+
return false;
|
1421
|
+
}
|
1422
|
+
|
1423
|
+
// Allocate the bitmap array
|
1424
|
+
FileBitmap = STORM_ALLOC(BYTE, dwBitmapSize);
|
1425
|
+
if(FileBitmap == NULL)
|
1426
|
+
return false;
|
1427
|
+
|
1428
|
+
// Initialize the bitmap
|
1429
|
+
memset(FileBitmap, 0, dwBitmapSize);
|
1430
|
+
pStream->FileBitmap = FileBitmap;
|
1431
|
+
pStream->BitmapSize = dwBitmapSize;
|
1432
|
+
pStream->BlockSize = DEFAULT_BLOCK_SIZE;
|
1433
|
+
pStream->BlockCount = dwBlockCount;
|
1434
|
+
pStream->IsComplete = 0;
|
1435
|
+
pStream->IsModified = 1;
|
1436
|
+
|
1437
|
+
// Note: Don't write the stream bitmap right away.
|
1438
|
+
// Doing so would cause sparse file resize on NTFS,
|
1439
|
+
// which would take long time on larger files.
|
1440
|
+
return true;
|
1441
|
+
}
|
1442
|
+
|
1443
|
+
static TFileStream * FlatStream_Open(const TCHAR * szFileName, DWORD dwStreamFlags)
|
1444
|
+
{
|
1445
|
+
TBlockStream * pStream;
|
1446
|
+
ULONGLONG ByteOffset = 0;
|
1447
|
+
|
1448
|
+
// Create new empty stream
|
1449
|
+
pStream = (TBlockStream *)AllocateFileStream(szFileName, sizeof(TBlockStream), dwStreamFlags);
|
1450
|
+
if(pStream == NULL)
|
1451
|
+
return NULL;
|
1452
|
+
|
1453
|
+
// Do we have a master stream?
|
1454
|
+
if(pStream->pMaster != NULL)
|
1455
|
+
{
|
1456
|
+
if(!FlatStream_CreateMirror(pStream))
|
1457
|
+
{
|
1458
|
+
FileStream_Close(pStream);
|
1459
|
+
SetLastError(ERROR_FILE_NOT_FOUND);
|
1460
|
+
return NULL;
|
1461
|
+
}
|
1462
|
+
}
|
1463
|
+
else
|
1464
|
+
{
|
1465
|
+
// Attempt to open the base stream
|
1466
|
+
if(!pStream->BaseOpen(pStream, pStream->szFileName, dwStreamFlags))
|
1467
|
+
{
|
1468
|
+
FileStream_Close(pStream);
|
1469
|
+
return NULL;
|
1470
|
+
}
|
1471
|
+
|
1472
|
+
// Load the bitmap, if required to
|
1473
|
+
if(dwStreamFlags & STREAM_FLAG_USE_BITMAP)
|
1474
|
+
FlatStream_LoadBitmap(pStream);
|
1475
|
+
}
|
1476
|
+
|
1477
|
+
// If we have a stream bitmap, set the reading functions
|
1478
|
+
// which check presence of each file block
|
1479
|
+
if(pStream->FileBitmap != NULL)
|
1480
|
+
{
|
1481
|
+
// Set the stream position to zero. Stream size is already set
|
1482
|
+
assert(pStream->StreamSize != 0);
|
1483
|
+
pStream->StreamPos = 0;
|
1484
|
+
pStream->dwFlags |= STREAM_FLAG_READ_ONLY;
|
1485
|
+
|
1486
|
+
// Supply the stream functions
|
1487
|
+
pStream->StreamRead = (STREAM_READ)BlockStream_Read;
|
1488
|
+
pStream->StreamGetSize = BlockStream_GetSize;
|
1489
|
+
pStream->StreamGetPos = BlockStream_GetPos;
|
1490
|
+
pStream->StreamClose = (STREAM_CLOSE)FlatStream_Close;
|
1491
|
+
|
1492
|
+
// Supply the block functions
|
1493
|
+
pStream->BlockCheck = (BLOCK_CHECK)FlatStream_BlockCheck;
|
1494
|
+
pStream->BlockRead = (BLOCK_READ)FlatStream_BlockRead;
|
1495
|
+
}
|
1496
|
+
else
|
1497
|
+
{
|
1498
|
+
// Reset the base position to zero
|
1499
|
+
pStream->BaseRead(pStream, &ByteOffset, NULL, 0);
|
1500
|
+
|
1501
|
+
// Setup stream size and position
|
1502
|
+
pStream->StreamSize = pStream->Base.File.FileSize;
|
1503
|
+
pStream->StreamPos = 0;
|
1504
|
+
|
1505
|
+
// Set the base functions
|
1506
|
+
pStream->StreamRead = pStream->BaseRead;
|
1507
|
+
pStream->StreamWrite = pStream->BaseWrite;
|
1508
|
+
pStream->StreamResize = pStream->BaseResize;
|
1509
|
+
pStream->StreamGetSize = pStream->BaseGetSize;
|
1510
|
+
pStream->StreamGetPos = pStream->BaseGetPos;
|
1511
|
+
pStream->StreamClose = pStream->BaseClose;
|
1512
|
+
}
|
1513
|
+
|
1514
|
+
return pStream;
|
1515
|
+
}
|
1516
|
+
|
1517
|
+
//-----------------------------------------------------------------------------
|
1518
|
+
// Local functions - partial stream support
|
1519
|
+
|
1520
|
+
static bool IsPartHeader(PPART_FILE_HEADER pPartHdr)
|
1521
|
+
{
|
1522
|
+
// Version number must be 2
|
1523
|
+
if(pPartHdr->PartialVersion == 2)
|
1524
|
+
{
|
1525
|
+
// GameBuildNumber must be an ASCII number
|
1526
|
+
if(isdigit(pPartHdr->GameBuildNumber[0]) && isdigit(pPartHdr->GameBuildNumber[1]) && isdigit(pPartHdr->GameBuildNumber[2]))
|
1527
|
+
{
|
1528
|
+
// Block size must be power of 2
|
1529
|
+
if((pPartHdr->BlockSize & (pPartHdr->BlockSize - 1)) == 0)
|
1530
|
+
return true;
|
1531
|
+
}
|
1532
|
+
}
|
1533
|
+
|
1534
|
+
return false;
|
1535
|
+
}
|
1536
|
+
|
1537
|
+
static DWORD PartStream_CheckFile(TBlockStream * pStream)
|
1538
|
+
{
|
1539
|
+
PPART_FILE_MAP_ENTRY FileBitmap = (PPART_FILE_MAP_ENTRY)pStream->FileBitmap;
|
1540
|
+
DWORD dwBlockCount;
|
1541
|
+
|
1542
|
+
// Get the number of blocks
|
1543
|
+
dwBlockCount = (DWORD)((pStream->StreamSize + pStream->BlockSize - 1) / pStream->BlockSize);
|
1544
|
+
|
1545
|
+
// Check all blocks
|
1546
|
+
for(DWORD i = 0; i < dwBlockCount; i++, FileBitmap++)
|
1547
|
+
{
|
1548
|
+
// Few sanity checks
|
1549
|
+
assert(FileBitmap->LargeValueHi == 0);
|
1550
|
+
assert(FileBitmap->LargeValueLo == 0);
|
1551
|
+
assert(FileBitmap->Flags == 0 || FileBitmap->Flags == 3);
|
1552
|
+
|
1553
|
+
// Check if this block is present
|
1554
|
+
if(FileBitmap->Flags != 3)
|
1555
|
+
return 0;
|
1556
|
+
}
|
1557
|
+
|
1558
|
+
// Yes, the file is complete
|
1559
|
+
return 1;
|
1560
|
+
}
|
1561
|
+
|
1562
|
+
static bool PartStream_LoadBitmap(TBlockStream * pStream)
|
1563
|
+
{
|
1564
|
+
PPART_FILE_MAP_ENTRY FileBitmap;
|
1565
|
+
PART_FILE_HEADER PartHdr;
|
1566
|
+
ULONGLONG ByteOffset = 0;
|
1567
|
+
ULONGLONG StreamSize = 0;
|
1568
|
+
DWORD BlockCount;
|
1569
|
+
DWORD BitmapSize;
|
1570
|
+
|
1571
|
+
// Only if the size is greater than size of the bitmap header
|
1572
|
+
if(pStream->Base.File.FileSize > sizeof(PART_FILE_HEADER))
|
1573
|
+
{
|
1574
|
+
// Attempt to read PART file header
|
1575
|
+
if(pStream->BaseRead(pStream, &ByteOffset, &PartHdr, sizeof(PART_FILE_HEADER)))
|
1576
|
+
{
|
1577
|
+
// We need to swap PART file header on big-endian platforms
|
1578
|
+
BSWAP_ARRAY32_UNSIGNED(&PartHdr, sizeof(PART_FILE_HEADER));
|
1579
|
+
|
1580
|
+
// Verify the PART file header
|
1581
|
+
if(IsPartHeader(&PartHdr))
|
1582
|
+
{
|
1583
|
+
// Get the number of blocks and size of one block
|
1584
|
+
StreamSize = MAKE_OFFSET64(PartHdr.FileSizeHi, PartHdr.FileSizeLo);
|
1585
|
+
ByteOffset = sizeof(PART_FILE_HEADER);
|
1586
|
+
BlockCount = (DWORD)((StreamSize + PartHdr.BlockSize - 1) / PartHdr.BlockSize);
|
1587
|
+
BitmapSize = BlockCount * sizeof(PART_FILE_MAP_ENTRY);
|
1588
|
+
|
1589
|
+
// Check if sizes match
|
1590
|
+
if((ByteOffset + BitmapSize) < pStream->Base.File.FileSize)
|
1591
|
+
{
|
1592
|
+
// Allocate space for the array of PART_FILE_MAP_ENTRY
|
1593
|
+
FileBitmap = STORM_ALLOC(PART_FILE_MAP_ENTRY, BlockCount);
|
1594
|
+
if(FileBitmap != NULL)
|
1595
|
+
{
|
1596
|
+
// Load the block map
|
1597
|
+
if(!pStream->BaseRead(pStream, &ByteOffset, FileBitmap, BitmapSize))
|
1598
|
+
{
|
1599
|
+
STORM_FREE(FileBitmap);
|
1600
|
+
return false;
|
1601
|
+
}
|
1602
|
+
|
1603
|
+
// Make sure that the byte order is correct
|
1604
|
+
BSWAP_ARRAY32_UNSIGNED(FileBitmap, BitmapSize);
|
1605
|
+
|
1606
|
+
// Update the stream size
|
1607
|
+
pStream->BuildNumber = StringToInt(PartHdr.GameBuildNumber);
|
1608
|
+
pStream->StreamSize = StreamSize;
|
1609
|
+
|
1610
|
+
// Fill the bitmap information
|
1611
|
+
pStream->FileBitmap = FileBitmap;
|
1612
|
+
pStream->BitmapSize = BitmapSize;
|
1613
|
+
pStream->BlockSize = PartHdr.BlockSize;
|
1614
|
+
pStream->BlockCount = BlockCount;
|
1615
|
+
pStream->IsComplete = PartStream_CheckFile(pStream);
|
1616
|
+
return true;
|
1617
|
+
}
|
1618
|
+
}
|
1619
|
+
}
|
1620
|
+
}
|
1621
|
+
}
|
1622
|
+
|
1623
|
+
return false;
|
1624
|
+
}
|
1625
|
+
|
1626
|
+
static void PartStream_UpdateBitmap(
|
1627
|
+
TBlockStream * pStream, // Pointer to an open stream
|
1628
|
+
ULONGLONG StartOffset,
|
1629
|
+
ULONGLONG EndOffset,
|
1630
|
+
ULONGLONG RealOffset)
|
1631
|
+
{
|
1632
|
+
PPART_FILE_MAP_ENTRY FileBitmap;
|
1633
|
+
DWORD BlockSize = pStream->BlockSize;
|
1634
|
+
|
1635
|
+
// Sanity checks
|
1636
|
+
assert((StartOffset & (BlockSize - 1)) == 0);
|
1637
|
+
assert(pStream->FileBitmap != NULL);
|
1638
|
+
|
1639
|
+
// Calculate the first entry in the block map
|
1640
|
+
FileBitmap = (PPART_FILE_MAP_ENTRY)pStream->FileBitmap + (StartOffset / BlockSize);
|
1641
|
+
|
1642
|
+
// Set all bits for the specified range
|
1643
|
+
while(StartOffset < EndOffset)
|
1644
|
+
{
|
1645
|
+
// Set the bit
|
1646
|
+
FileBitmap->BlockOffsHi = (DWORD)(RealOffset >> 0x20);
|
1647
|
+
FileBitmap->BlockOffsLo = (DWORD)(RealOffset & 0xFFFFFFFF);
|
1648
|
+
FileBitmap->Flags = 3;
|
1649
|
+
|
1650
|
+
// Move all
|
1651
|
+
StartOffset += BlockSize;
|
1652
|
+
RealOffset += BlockSize;
|
1653
|
+
FileBitmap++;
|
1654
|
+
}
|
1655
|
+
|
1656
|
+
// Increment the bitmap update count
|
1657
|
+
pStream->IsModified = 1;
|
1658
|
+
}
|
1659
|
+
|
1660
|
+
static bool PartStream_BlockCheck(
|
1661
|
+
TBlockStream * pStream, // Pointer to an open stream
|
1662
|
+
ULONGLONG BlockOffset)
|
1663
|
+
{
|
1664
|
+
PPART_FILE_MAP_ENTRY FileBitmap;
|
1665
|
+
|
1666
|
+
// Sanity checks
|
1667
|
+
assert((BlockOffset & (pStream->BlockSize - 1)) == 0);
|
1668
|
+
assert(pStream->FileBitmap != NULL);
|
1669
|
+
|
1670
|
+
// Calculate the block map entry
|
1671
|
+
FileBitmap = (PPART_FILE_MAP_ENTRY)pStream->FileBitmap + (BlockOffset / pStream->BlockSize);
|
1672
|
+
|
1673
|
+
// Check if the flags are present
|
1674
|
+
return (FileBitmap->Flags & 0x03) ? true : false;
|
1675
|
+
}
|
1676
|
+
|
1677
|
+
static bool PartStream_BlockRead(
|
1678
|
+
TBlockStream * pStream,
|
1679
|
+
ULONGLONG StartOffset,
|
1680
|
+
ULONGLONG EndOffset,
|
1681
|
+
LPBYTE BlockBuffer,
|
1682
|
+
DWORD BytesNeeded,
|
1683
|
+
bool bAvailable)
|
1684
|
+
{
|
1685
|
+
PPART_FILE_MAP_ENTRY FileBitmap;
|
1686
|
+
ULONGLONG ByteOffset;
|
1687
|
+
DWORD BytesToRead;
|
1688
|
+
DWORD BlockIndex = (DWORD)(StartOffset / pStream->BlockSize);
|
1689
|
+
|
1690
|
+
// The starting offset must be aligned to size of the block
|
1691
|
+
assert(pStream->FileBitmap != NULL);
|
1692
|
+
assert((StartOffset & (pStream->BlockSize - 1)) == 0);
|
1693
|
+
assert(StartOffset < EndOffset);
|
1694
|
+
|
1695
|
+
// If the blocks are not available, we need to load them from the master
|
1696
|
+
// and then save to the mirror
|
1697
|
+
if(bAvailable == false)
|
1698
|
+
{
|
1699
|
+
// If we have no master, we cannot satisfy read request
|
1700
|
+
if(pStream->pMaster == NULL)
|
1701
|
+
return false;
|
1702
|
+
|
1703
|
+
// Load the blocks from the master stream
|
1704
|
+
// Note that we always have to read complete blocks
|
1705
|
+
// so they get properly stored to the mirror stream
|
1706
|
+
BytesToRead = (DWORD)(EndOffset - StartOffset);
|
1707
|
+
if(!FileStream_Read(pStream->pMaster, &StartOffset, BlockBuffer, BytesToRead))
|
1708
|
+
return false;
|
1709
|
+
|
1710
|
+
// The loaded blocks are going to be stored to the end of the file
|
1711
|
+
// Note that this operation is not required to succeed
|
1712
|
+
if(pStream->BaseGetSize(pStream, &ByteOffset))
|
1713
|
+
{
|
1714
|
+
// Store the loaded blocks to the mirror file.
|
1715
|
+
if(pStream->BaseWrite(pStream, &ByteOffset, BlockBuffer, BytesToRead))
|
1716
|
+
{
|
1717
|
+
PartStream_UpdateBitmap(pStream, StartOffset, EndOffset, ByteOffset);
|
1718
|
+
}
|
1719
|
+
}
|
1720
|
+
}
|
1721
|
+
else
|
1722
|
+
{
|
1723
|
+
// Get the file map entry
|
1724
|
+
FileBitmap = (PPART_FILE_MAP_ENTRY)pStream->FileBitmap + BlockIndex;
|
1725
|
+
|
1726
|
+
// Read all blocks
|
1727
|
+
while(StartOffset < EndOffset)
|
1728
|
+
{
|
1729
|
+
// Get the number of bytes to be read
|
1730
|
+
BytesToRead = (DWORD)(EndOffset - StartOffset);
|
1731
|
+
if(BytesToRead > pStream->BlockSize)
|
1732
|
+
BytesToRead = pStream->BlockSize;
|
1733
|
+
if(BytesToRead > BytesNeeded)
|
1734
|
+
BytesToRead = BytesNeeded;
|
1735
|
+
|
1736
|
+
// Read the block
|
1737
|
+
ByteOffset = MAKE_OFFSET64(FileBitmap->BlockOffsHi, FileBitmap->BlockOffsLo);
|
1738
|
+
if(!pStream->BaseRead(pStream, &ByteOffset, BlockBuffer, BytesToRead))
|
1739
|
+
return false;
|
1740
|
+
|
1741
|
+
// Move the pointers
|
1742
|
+
StartOffset += pStream->BlockSize;
|
1743
|
+
BlockBuffer += pStream->BlockSize;
|
1744
|
+
BytesNeeded -= pStream->BlockSize;
|
1745
|
+
FileBitmap++;
|
1746
|
+
}
|
1747
|
+
}
|
1748
|
+
|
1749
|
+
return true;
|
1750
|
+
}
|
1751
|
+
|
1752
|
+
static void PartStream_Close(TBlockStream * pStream)
|
1753
|
+
{
|
1754
|
+
PART_FILE_HEADER PartHeader;
|
1755
|
+
ULONGLONG ByteOffset = 0;
|
1756
|
+
|
1757
|
+
if(pStream->FileBitmap && pStream->IsModified)
|
1758
|
+
{
|
1759
|
+
// Prepare the part file header
|
1760
|
+
memset(&PartHeader, 0, sizeof(PART_FILE_HEADER));
|
1761
|
+
PartHeader.PartialVersion = 2;
|
1762
|
+
PartHeader.FileSizeHi = (DWORD)(pStream->StreamSize >> 0x20);
|
1763
|
+
PartHeader.FileSizeLo = (DWORD)(pStream->StreamSize & 0xFFFFFFFF);
|
1764
|
+
PartHeader.BlockSize = pStream->BlockSize;
|
1765
|
+
|
1766
|
+
// Make sure that the header is properly BSWAPed
|
1767
|
+
BSWAP_ARRAY32_UNSIGNED(&PartHeader, sizeof(PART_FILE_HEADER));
|
1768
|
+
IntToString(PartHeader.GameBuildNumber, _countof(PartHeader.GameBuildNumber), pStream->BuildNumber);
|
1769
|
+
|
1770
|
+
// Write the part header
|
1771
|
+
pStream->BaseWrite(pStream, &ByteOffset, &PartHeader, sizeof(PART_FILE_HEADER));
|
1772
|
+
|
1773
|
+
// Write the block bitmap
|
1774
|
+
BSWAP_ARRAY32_UNSIGNED(pStream->FileBitmap, pStream->BitmapSize);
|
1775
|
+
pStream->BaseWrite(pStream, NULL, pStream->FileBitmap, pStream->BitmapSize);
|
1776
|
+
}
|
1777
|
+
|
1778
|
+
// Close the base class
|
1779
|
+
BlockStream_Close(pStream);
|
1780
|
+
}
|
1781
|
+
|
1782
|
+
static bool PartStream_CreateMirror(TBlockStream * pStream)
|
1783
|
+
{
|
1784
|
+
ULONGLONG RemainingSize;
|
1785
|
+
ULONGLONG MasterSize = 0;
|
1786
|
+
ULONGLONG MirrorSize = 0;
|
1787
|
+
LPBYTE FileBitmap = NULL;
|
1788
|
+
DWORD dwBitmapSize;
|
1789
|
+
DWORD dwBlockCount;
|
1790
|
+
bool bNeedCreateMirrorStream = true;
|
1791
|
+
bool bNeedResizeMirrorStream = true;
|
1792
|
+
|
1793
|
+
// Do we have master function and base creation function?
|
1794
|
+
if(pStream->pMaster == NULL || pStream->BaseCreate == NULL)
|
1795
|
+
return false;
|
1796
|
+
|
1797
|
+
// Retrieve the master file size, block count and bitmap size
|
1798
|
+
FileStream_GetSize(pStream->pMaster, &MasterSize);
|
1799
|
+
dwBlockCount = (DWORD)((MasterSize + DEFAULT_BLOCK_SIZE - 1) / DEFAULT_BLOCK_SIZE);
|
1800
|
+
dwBitmapSize = (DWORD)(dwBlockCount * sizeof(PART_FILE_MAP_ENTRY));
|
1801
|
+
|
1802
|
+
// Setup stream size and position
|
1803
|
+
pStream->BuildNumber = DEFAULT_BUILD_NUMBER; // BUGBUG: Really???
|
1804
|
+
pStream->StreamSize = MasterSize;
|
1805
|
+
pStream->StreamPos = 0;
|
1806
|
+
|
1807
|
+
// Open the base stream for write access
|
1808
|
+
if(pStream->BaseOpen(pStream, pStream->szFileName, 0))
|
1809
|
+
{
|
1810
|
+
// If the file open succeeded, check if the file size matches required size
|
1811
|
+
pStream->BaseGetSize(pStream, &MirrorSize);
|
1812
|
+
if(MirrorSize >= sizeof(PART_FILE_HEADER) + dwBitmapSize)
|
1813
|
+
{
|
1814
|
+
// Check if the remaining size is aligned to block
|
1815
|
+
RemainingSize = MirrorSize - sizeof(PART_FILE_HEADER) - dwBitmapSize;
|
1816
|
+
if((RemainingSize & (DEFAULT_BLOCK_SIZE - 1)) == 0 || RemainingSize == MasterSize)
|
1817
|
+
{
|
1818
|
+
// Attempt to load an existing file bitmap
|
1819
|
+
if(PartStream_LoadBitmap(pStream))
|
1820
|
+
return true;
|
1821
|
+
}
|
1822
|
+
}
|
1823
|
+
|
1824
|
+
// We need to create mirror stream
|
1825
|
+
bNeedCreateMirrorStream = false;
|
1826
|
+
}
|
1827
|
+
|
1828
|
+
// Create a new stream, if needed
|
1829
|
+
if(bNeedCreateMirrorStream)
|
1830
|
+
{
|
1831
|
+
if(!pStream->BaseCreate(pStream))
|
1832
|
+
return false;
|
1833
|
+
}
|
1834
|
+
|
1835
|
+
// If we need to, then resize the mirror stream
|
1836
|
+
if(bNeedResizeMirrorStream)
|
1837
|
+
{
|
1838
|
+
if(!pStream->BaseResize(pStream, sizeof(PART_FILE_HEADER) + dwBitmapSize))
|
1839
|
+
return false;
|
1840
|
+
}
|
1841
|
+
|
1842
|
+
// Allocate the bitmap array
|
1843
|
+
FileBitmap = STORM_ALLOC(BYTE, dwBitmapSize);
|
1844
|
+
if(FileBitmap == NULL)
|
1845
|
+
return false;
|
1846
|
+
|
1847
|
+
// Initialize the bitmap
|
1848
|
+
memset(FileBitmap, 0, dwBitmapSize);
|
1849
|
+
pStream->FileBitmap = FileBitmap;
|
1850
|
+
pStream->BitmapSize = dwBitmapSize;
|
1851
|
+
pStream->BlockSize = DEFAULT_BLOCK_SIZE;
|
1852
|
+
pStream->BlockCount = dwBlockCount;
|
1853
|
+
pStream->IsComplete = 0;
|
1854
|
+
pStream->IsModified = 1;
|
1855
|
+
|
1856
|
+
// Note: Don't write the stream bitmap right away.
|
1857
|
+
// Doing so would cause sparse file resize on NTFS,
|
1858
|
+
// which would take long time on larger files.
|
1859
|
+
return true;
|
1860
|
+
}
|
1861
|
+
|
1862
|
+
|
1863
|
+
static TFileStream * PartStream_Open(const TCHAR * szFileName, DWORD dwStreamFlags)
|
1864
|
+
{
|
1865
|
+
TBlockStream * pStream;
|
1866
|
+
|
1867
|
+
// Create new empty stream
|
1868
|
+
pStream = (TBlockStream *)AllocateFileStream(szFileName, sizeof(TBlockStream), dwStreamFlags);
|
1869
|
+
if(pStream == NULL)
|
1870
|
+
return NULL;
|
1871
|
+
|
1872
|
+
// Do we have a master stream?
|
1873
|
+
if(pStream->pMaster != NULL)
|
1874
|
+
{
|
1875
|
+
if(!PartStream_CreateMirror(pStream))
|
1876
|
+
{
|
1877
|
+
FileStream_Close(pStream);
|
1878
|
+
SetLastError(ERROR_FILE_NOT_FOUND);
|
1879
|
+
return NULL;
|
1880
|
+
}
|
1881
|
+
}
|
1882
|
+
else
|
1883
|
+
{
|
1884
|
+
// Attempt to open the base stream
|
1885
|
+
if(!pStream->BaseOpen(pStream, pStream->szFileName, dwStreamFlags))
|
1886
|
+
{
|
1887
|
+
FileStream_Close(pStream);
|
1888
|
+
return NULL;
|
1889
|
+
}
|
1890
|
+
|
1891
|
+
// Load the part stream block map
|
1892
|
+
if(!PartStream_LoadBitmap(pStream))
|
1893
|
+
{
|
1894
|
+
FileStream_Close(pStream);
|
1895
|
+
SetLastError(ERROR_BAD_FORMAT);
|
1896
|
+
return NULL;
|
1897
|
+
}
|
1898
|
+
}
|
1899
|
+
|
1900
|
+
// Set the stream position to zero. Stream size is already set
|
1901
|
+
assert(pStream->StreamSize != 0);
|
1902
|
+
pStream->StreamPos = 0;
|
1903
|
+
pStream->dwFlags |= STREAM_FLAG_READ_ONLY;
|
1904
|
+
|
1905
|
+
// Set new function pointers
|
1906
|
+
pStream->StreamRead = (STREAM_READ)BlockStream_Read;
|
1907
|
+
pStream->StreamGetPos = BlockStream_GetPos;
|
1908
|
+
pStream->StreamGetSize = BlockStream_GetSize;
|
1909
|
+
pStream->StreamClose = (STREAM_CLOSE)PartStream_Close;
|
1910
|
+
|
1911
|
+
// Supply the block functions
|
1912
|
+
pStream->BlockCheck = (BLOCK_CHECK)PartStream_BlockCheck;
|
1913
|
+
pStream->BlockRead = (BLOCK_READ)PartStream_BlockRead;
|
1914
|
+
return pStream;
|
1915
|
+
}
|
1916
|
+
|
1917
|
+
//-----------------------------------------------------------------------------
|
1918
|
+
// Local functions - MPQE stream support
|
1919
|
+
|
1920
|
+
static const char * szKeyTemplate = "expand 32-byte k000000000000000000000000000000000000000000000000";
|
1921
|
+
|
1922
|
+
static const char * AuthCodeArray[] =
|
1923
|
+
{
|
1924
|
+
// Starcraft II (Heart of the Swarm)
|
1925
|
+
// Authentication code URL: http://dist.blizzard.com/mediakey/hots-authenticationcode-bgdl.txt
|
1926
|
+
// -0C- -1C--08- -18--04- -14--00- -10-
|
1927
|
+
"S48B6CDTN5XEQAKQDJNDLJBJ73FDFM3U", // SC2 Heart of the Swarm-all : "expand 32-byte kQAKQ0000FM3UN5XE000073FD6CDT0000LJBJS48B0000DJND"
|
1928
|
+
|
1929
|
+
// Diablo III: Agent.exe (1.0.0.954)
|
1930
|
+
// Address of decryption routine: 00502b00
|
1931
|
+
// Pointer to decryptor object: ECX
|
1932
|
+
// Pointer to key: ECX+0x5C
|
1933
|
+
// Authentication code URL: http://dist.blizzard.com/mediakey/d3-authenticationcode-enGB.txt
|
1934
|
+
// -0C- -1C--08- -18--04- -14--00- -10-
|
1935
|
+
"UCMXF6EJY352EFH4XFRXCFH2XC9MQRZK", // Diablo III Installer (deDE): "expand 32-byte kEFH40000QRZKY3520000XC9MF6EJ0000CFH2UCMX0000XFRX"
|
1936
|
+
"MMKVHY48RP7WXP4GHYBQ7SL9J9UNPHBP", // Diablo III Installer (enGB): "expand 32-byte kXP4G0000PHBPRP7W0000J9UNHY4800007SL9MMKV0000HYBQ"
|
1937
|
+
"8MXLWHQ7VGGLTZ9MQZQSFDCLJYET3CPP", // Diablo III Installer (enSG): "expand 32-byte kTZ9M00003CPPVGGL0000JYETWHQ70000FDCL8MXL0000QZQS"
|
1938
|
+
"EJ2R5TM6XFE2GUNG5QDGHKQ9UAKPWZSZ", // Diablo III Installer (enUS): "expand 32-byte kGUNG0000WZSZXFE20000UAKP5TM60000HKQ9EJ2R00005QDG"
|
1939
|
+
"PBGFBE42Z6LNK65UGJQ3WZVMCLP4HQQT", // Diablo III Installer (esES): "expand 32-byte kK65U0000HQQTZ6LN0000CLP4BE420000WZVMPBGF0000GJQ3"
|
1940
|
+
"X7SEJJS9TSGCW5P28EBSC47AJPEY8VU2", // Diablo III Installer (esMX): "expand 32-byte kW5P200008VU2TSGC0000JPEYJJS90000C47AX7SE00008EBS"
|
1941
|
+
"5KVBQA8VYE6XRY3DLGC5ZDE4XS4P7YA2", // Diablo III Installer (frFR): "expand 32-byte kRY3D00007YA2YE6X0000XS4PQA8V0000ZDE45KVB0000LGC5"
|
1942
|
+
"478JD2K56EVNVVY4XX8TDWYT5B8KB254", // Diablo III Installer (itIT): "expand 32-byte kVVY40000B2546EVN00005B8KD2K50000DWYT478J0000XX8T"
|
1943
|
+
"8TS4VNFQRZTN6YWHE9CHVDH9NVWD474A", // Diablo III Installer (koKR): "expand 32-byte k6YWH0000474ARZTN0000NVWDVNFQ0000VDH98TS40000E9CH"
|
1944
|
+
"LJ52Z32DF4LZ4ZJJXVKK3AZQA6GABLJB", // Diablo III Installer (plPL): "expand 32-byte k4ZJJ0000BLJBF4LZ0000A6GAZ32D00003AZQLJ520000XVKK"
|
1945
|
+
"K6BDHY2ECUE2545YKNLBJPVYWHE7XYAG", // Diablo III Installer (ptBR): "expand 32-byte k545Y0000XYAGCUE20000WHE7HY2E0000JPVYK6BD0000KNLB"
|
1946
|
+
"NDVW8GWLAYCRPGRNY8RT7ZZUQU63VLPR", // Diablo III Installer (ruRU): "expand 32-byte kXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
1947
|
+
"6VWCQTN8V3ZZMRUCZXV8A8CGUX2TAA8H", // Diablo III Installer (zhTW): "expand 32-byte kMRUC0000AA8HV3ZZ0000UX2TQTN80000A8CG6VWC0000ZXV8"
|
1948
|
+
// "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX", // Diablo III Installer (zhCN): "expand 32-byte kXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
|
1949
|
+
|
1950
|
+
// Starcraft II (Wings of Liberty): Installer.exe (4.1.1.4219)
|
1951
|
+
// Address of decryption routine: 0053A3D0
|
1952
|
+
// Pointer to decryptor object: ECX
|
1953
|
+
// Pointer to key: ECX+0x5C
|
1954
|
+
// Authentication code URL: http://dist.blizzard.com/mediakey/sc2-authenticationcode-enUS.txt
|
1955
|
+
// -0C- -1C--08- -18--04- -14--00- -10-
|
1956
|
+
"Y45MD3CAK4KXSSXHYD9VY64Z8EKJ4XFX", // SC2 Wings of Liberty (deDE): "expand 32-byte kSSXH00004XFXK4KX00008EKJD3CA0000Y64ZY45M0000YD9V"
|
1957
|
+
"G8MN8UDG6NA2ANGY6A3DNY82HRGF29ZH", // SC2 Wings of Liberty (enGB): "expand 32-byte kANGY000029ZH6NA20000HRGF8UDG0000NY82G8MN00006A3D"
|
1958
|
+
"W9RRHLB2FDU9WW5B3ECEBLRSFWZSF7HW", // SC2 Wings of Liberty (enSG): "expand 32-byte kWW5B0000F7HWFDU90000FWZSHLB20000BLRSW9RR00003ECE"
|
1959
|
+
"3DH5RE5NVM5GTFD85LXGWT6FK859ETR5", // SC2 Wings of Liberty (enUS): "expand 32-byte kTFD80000ETR5VM5G0000K859RE5N0000WT6F3DH500005LXG"
|
1960
|
+
"8WLKUAXE94PFQU4Y249PAZ24N4R4XKTQ", // SC2 Wings of Liberty (esES): "expand 32-byte kQU4Y0000XKTQ94PF0000N4R4UAXE0000AZ248WLK0000249P"
|
1961
|
+
"A34DXX3VHGGXSQBRFE5UFFDXMF9G4G54", // SC2 Wings of Liberty (esMX): "expand 32-byte kSQBR00004G54HGGX0000MF9GXX3V0000FFDXA34D0000FE5U"
|
1962
|
+
"ZG7J9K938HJEFWPQUA768MA2PFER6EAJ", // SC2 Wings of Liberty (frFR): "expand 32-byte kFWPQ00006EAJ8HJE0000PFER9K9300008MA2ZG7J0000UA76"
|
1963
|
+
"NE7CUNNNTVAPXV7E3G2BSVBWGVMW8BL2", // SC2 Wings of Liberty (itIT): "expand 32-byte kXV7E00008BL2TVAP0000GVMWUNNN0000SVBWNE7C00003G2B"
|
1964
|
+
"3V9E2FTMBM9QQWK7U6MAMWAZWQDB838F", // SC2 Wings of Liberty (koKR): "expand 32-byte kQWK70000838FBM9Q0000WQDB2FTM0000MWAZ3V9E0000U6MA"
|
1965
|
+
"2NSFB8MELULJ83U6YHA3UP6K4MQD48L6", // SC2 Wings of Liberty (plPL): "expand 32-byte k83U6000048L6LULJ00004MQDB8ME0000UP6K2NSF0000YHA3"
|
1966
|
+
"QA2TZ9EWZ4CUU8BMB5WXCTY65F9CSW4E", // SC2 Wings of Liberty (ptBR): "expand 32-byte kU8BM0000SW4EZ4CU00005F9CZ9EW0000CTY6QA2T0000B5WX"
|
1967
|
+
"VHB378W64BAT9SH7D68VV9NLQDK9YEGT", // SC2 Wings of Liberty (ruRU): "expand 32-byte k9SH70000YEGT4BAT0000QDK978W60000V9NLVHB30000D68V"
|
1968
|
+
"U3NFQJV4M6GC7KBN9XQJ3BRDN3PLD9NE", // SC2 Wings of Liberty (zhTW): "expand 32-byte k7KBN0000D9NEM6GC0000N3PLQJV400003BRDU3NF00009XQJ"
|
1969
|
+
|
1970
|
+
NULL
|
1971
|
+
};
|
1972
|
+
|
1973
|
+
static DWORD Rol32(DWORD dwValue, DWORD dwRolCount)
|
1974
|
+
{
|
1975
|
+
DWORD dwShiftRight = 32 - dwRolCount;
|
1976
|
+
|
1977
|
+
return (dwValue << dwRolCount) | (dwValue >> dwShiftRight);
|
1978
|
+
}
|
1979
|
+
|
1980
|
+
static void CreateKeyFromAuthCode(
|
1981
|
+
LPBYTE pbKeyBuffer,
|
1982
|
+
const char * szAuthCode)
|
1983
|
+
{
|
1984
|
+
LPDWORD KeyPosition = (LPDWORD)(pbKeyBuffer + 0x10);
|
1985
|
+
LPDWORD AuthCode32 = (LPDWORD)szAuthCode;
|
1986
|
+
|
1987
|
+
memcpy(pbKeyBuffer, szKeyTemplate, MPQE_CHUNK_SIZE);
|
1988
|
+
KeyPosition[0x00] = AuthCode32[0x03];
|
1989
|
+
KeyPosition[0x02] = AuthCode32[0x07];
|
1990
|
+
KeyPosition[0x03] = AuthCode32[0x02];
|
1991
|
+
KeyPosition[0x05] = AuthCode32[0x06];
|
1992
|
+
KeyPosition[0x06] = AuthCode32[0x01];
|
1993
|
+
KeyPosition[0x08] = AuthCode32[0x05];
|
1994
|
+
KeyPosition[0x09] = AuthCode32[0x00];
|
1995
|
+
KeyPosition[0x0B] = AuthCode32[0x04];
|
1996
|
+
BSWAP_ARRAY32_UNSIGNED(pbKeyBuffer, MPQE_CHUNK_SIZE);
|
1997
|
+
}
|
1998
|
+
|
1999
|
+
static void DecryptFileChunk(
|
2000
|
+
DWORD * MpqData,
|
2001
|
+
LPBYTE pbKey,
|
2002
|
+
ULONGLONG ByteOffset,
|
2003
|
+
DWORD dwLength)
|
2004
|
+
{
|
2005
|
+
ULONGLONG ChunkOffset;
|
2006
|
+
DWORD KeyShuffled[0x10];
|
2007
|
+
DWORD KeyMirror[0x10];
|
2008
|
+
DWORD RoundCount = 0x14;
|
2009
|
+
|
2010
|
+
// Prepare the key
|
2011
|
+
ChunkOffset = ByteOffset / MPQE_CHUNK_SIZE;
|
2012
|
+
memcpy(KeyMirror, pbKey, MPQE_CHUNK_SIZE);
|
2013
|
+
BSWAP_ARRAY32_UNSIGNED(KeyMirror, MPQE_CHUNK_SIZE);
|
2014
|
+
KeyMirror[0x05] = (DWORD)(ChunkOffset >> 32);
|
2015
|
+
KeyMirror[0x08] = (DWORD)(ChunkOffset);
|
2016
|
+
|
2017
|
+
while(dwLength >= MPQE_CHUNK_SIZE)
|
2018
|
+
{
|
2019
|
+
// Shuffle the key - part 1
|
2020
|
+
KeyShuffled[0x0E] = KeyMirror[0x00];
|
2021
|
+
KeyShuffled[0x0C] = KeyMirror[0x01];
|
2022
|
+
KeyShuffled[0x05] = KeyMirror[0x02];
|
2023
|
+
KeyShuffled[0x0F] = KeyMirror[0x03];
|
2024
|
+
KeyShuffled[0x0A] = KeyMirror[0x04];
|
2025
|
+
KeyShuffled[0x07] = KeyMirror[0x05];
|
2026
|
+
KeyShuffled[0x0B] = KeyMirror[0x06];
|
2027
|
+
KeyShuffled[0x09] = KeyMirror[0x07];
|
2028
|
+
KeyShuffled[0x03] = KeyMirror[0x08];
|
2029
|
+
KeyShuffled[0x06] = KeyMirror[0x09];
|
2030
|
+
KeyShuffled[0x08] = KeyMirror[0x0A];
|
2031
|
+
KeyShuffled[0x0D] = KeyMirror[0x0B];
|
2032
|
+
KeyShuffled[0x02] = KeyMirror[0x0C];
|
2033
|
+
KeyShuffled[0x04] = KeyMirror[0x0D];
|
2034
|
+
KeyShuffled[0x01] = KeyMirror[0x0E];
|
2035
|
+
KeyShuffled[0x00] = KeyMirror[0x0F];
|
2036
|
+
|
2037
|
+
// Shuffle the key - part 2
|
2038
|
+
for(DWORD i = 0; i < RoundCount; i += 2)
|
2039
|
+
{
|
2040
|
+
KeyShuffled[0x0A] = KeyShuffled[0x0A] ^ Rol32((KeyShuffled[0x0E] + KeyShuffled[0x02]), 0x07);
|
2041
|
+
KeyShuffled[0x03] = KeyShuffled[0x03] ^ Rol32((KeyShuffled[0x0A] + KeyShuffled[0x0E]), 0x09);
|
2042
|
+
KeyShuffled[0x02] = KeyShuffled[0x02] ^ Rol32((KeyShuffled[0x03] + KeyShuffled[0x0A]), 0x0D);
|
2043
|
+
KeyShuffled[0x0E] = KeyShuffled[0x0E] ^ Rol32((KeyShuffled[0x02] + KeyShuffled[0x03]), 0x12);
|
2044
|
+
|
2045
|
+
KeyShuffled[0x07] = KeyShuffled[0x07] ^ Rol32((KeyShuffled[0x0C] + KeyShuffled[0x04]), 0x07);
|
2046
|
+
KeyShuffled[0x06] = KeyShuffled[0x06] ^ Rol32((KeyShuffled[0x07] + KeyShuffled[0x0C]), 0x09);
|
2047
|
+
KeyShuffled[0x04] = KeyShuffled[0x04] ^ Rol32((KeyShuffled[0x06] + KeyShuffled[0x07]), 0x0D);
|
2048
|
+
KeyShuffled[0x0C] = KeyShuffled[0x0C] ^ Rol32((KeyShuffled[0x04] + KeyShuffled[0x06]), 0x12);
|
2049
|
+
|
2050
|
+
KeyShuffled[0x0B] = KeyShuffled[0x0B] ^ Rol32((KeyShuffled[0x05] + KeyShuffled[0x01]), 0x07);
|
2051
|
+
KeyShuffled[0x08] = KeyShuffled[0x08] ^ Rol32((KeyShuffled[0x0B] + KeyShuffled[0x05]), 0x09);
|
2052
|
+
KeyShuffled[0x01] = KeyShuffled[0x01] ^ Rol32((KeyShuffled[0x08] + KeyShuffled[0x0B]), 0x0D);
|
2053
|
+
KeyShuffled[0x05] = KeyShuffled[0x05] ^ Rol32((KeyShuffled[0x01] + KeyShuffled[0x08]), 0x12);
|
2054
|
+
|
2055
|
+
KeyShuffled[0x09] = KeyShuffled[0x09] ^ Rol32((KeyShuffled[0x0F] + KeyShuffled[0x00]), 0x07);
|
2056
|
+
KeyShuffled[0x0D] = KeyShuffled[0x0D] ^ Rol32((KeyShuffled[0x09] + KeyShuffled[0x0F]), 0x09);
|
2057
|
+
KeyShuffled[0x00] = KeyShuffled[0x00] ^ Rol32((KeyShuffled[0x0D] + KeyShuffled[0x09]), 0x0D);
|
2058
|
+
KeyShuffled[0x0F] = KeyShuffled[0x0F] ^ Rol32((KeyShuffled[0x00] + KeyShuffled[0x0D]), 0x12);
|
2059
|
+
|
2060
|
+
KeyShuffled[0x04] = KeyShuffled[0x04] ^ Rol32((KeyShuffled[0x0E] + KeyShuffled[0x09]), 0x07);
|
2061
|
+
KeyShuffled[0x08] = KeyShuffled[0x08] ^ Rol32((KeyShuffled[0x04] + KeyShuffled[0x0E]), 0x09);
|
2062
|
+
KeyShuffled[0x09] = KeyShuffled[0x09] ^ Rol32((KeyShuffled[0x08] + KeyShuffled[0x04]), 0x0D);
|
2063
|
+
KeyShuffled[0x0E] = KeyShuffled[0x0E] ^ Rol32((KeyShuffled[0x09] + KeyShuffled[0x08]), 0x12);
|
2064
|
+
|
2065
|
+
KeyShuffled[0x01] = KeyShuffled[0x01] ^ Rol32((KeyShuffled[0x0C] + KeyShuffled[0x0A]), 0x07);
|
2066
|
+
KeyShuffled[0x0D] = KeyShuffled[0x0D] ^ Rol32((KeyShuffled[0x01] + KeyShuffled[0x0C]), 0x09);
|
2067
|
+
KeyShuffled[0x0A] = KeyShuffled[0x0A] ^ Rol32((KeyShuffled[0x0D] + KeyShuffled[0x01]), 0x0D);
|
2068
|
+
KeyShuffled[0x0C] = KeyShuffled[0x0C] ^ Rol32((KeyShuffled[0x0A] + KeyShuffled[0x0D]), 0x12);
|
2069
|
+
|
2070
|
+
KeyShuffled[0x00] = KeyShuffled[0x00] ^ Rol32((KeyShuffled[0x05] + KeyShuffled[0x07]), 0x07);
|
2071
|
+
KeyShuffled[0x03] = KeyShuffled[0x03] ^ Rol32((KeyShuffled[0x00] + KeyShuffled[0x05]), 0x09);
|
2072
|
+
KeyShuffled[0x07] = KeyShuffled[0x07] ^ Rol32((KeyShuffled[0x03] + KeyShuffled[0x00]), 0x0D);
|
2073
|
+
KeyShuffled[0x05] = KeyShuffled[0x05] ^ Rol32((KeyShuffled[0x07] + KeyShuffled[0x03]), 0x12);
|
2074
|
+
|
2075
|
+
KeyShuffled[0x02] = KeyShuffled[0x02] ^ Rol32((KeyShuffled[0x0F] + KeyShuffled[0x0B]), 0x07);
|
2076
|
+
KeyShuffled[0x06] = KeyShuffled[0x06] ^ Rol32((KeyShuffled[0x02] + KeyShuffled[0x0F]), 0x09);
|
2077
|
+
KeyShuffled[0x0B] = KeyShuffled[0x0B] ^ Rol32((KeyShuffled[0x06] + KeyShuffled[0x02]), 0x0D);
|
2078
|
+
KeyShuffled[0x0F] = KeyShuffled[0x0F] ^ Rol32((KeyShuffled[0x0B] + KeyShuffled[0x06]), 0x12);
|
2079
|
+
}
|
2080
|
+
|
2081
|
+
// Decrypt one data chunk
|
2082
|
+
BSWAP_ARRAY32_UNSIGNED(MpqData, MPQE_CHUNK_SIZE);
|
2083
|
+
MpqData[0x00] = MpqData[0x00] ^ (KeyShuffled[0x0E] + KeyMirror[0x00]);
|
2084
|
+
MpqData[0x01] = MpqData[0x01] ^ (KeyShuffled[0x04] + KeyMirror[0x0D]);
|
2085
|
+
MpqData[0x02] = MpqData[0x02] ^ (KeyShuffled[0x08] + KeyMirror[0x0A]);
|
2086
|
+
MpqData[0x03] = MpqData[0x03] ^ (KeyShuffled[0x09] + KeyMirror[0x07]);
|
2087
|
+
MpqData[0x04] = MpqData[0x04] ^ (KeyShuffled[0x0A] + KeyMirror[0x04]);
|
2088
|
+
MpqData[0x05] = MpqData[0x05] ^ (KeyShuffled[0x0C] + KeyMirror[0x01]);
|
2089
|
+
MpqData[0x06] = MpqData[0x06] ^ (KeyShuffled[0x01] + KeyMirror[0x0E]);
|
2090
|
+
MpqData[0x07] = MpqData[0x07] ^ (KeyShuffled[0x0D] + KeyMirror[0x0B]);
|
2091
|
+
MpqData[0x08] = MpqData[0x08] ^ (KeyShuffled[0x03] + KeyMirror[0x08]);
|
2092
|
+
MpqData[0x09] = MpqData[0x09] ^ (KeyShuffled[0x07] + KeyMirror[0x05]);
|
2093
|
+
MpqData[0x0A] = MpqData[0x0A] ^ (KeyShuffled[0x05] + KeyMirror[0x02]);
|
2094
|
+
MpqData[0x0B] = MpqData[0x0B] ^ (KeyShuffled[0x00] + KeyMirror[0x0F]);
|
2095
|
+
MpqData[0x0C] = MpqData[0x0C] ^ (KeyShuffled[0x02] + KeyMirror[0x0C]);
|
2096
|
+
MpqData[0x0D] = MpqData[0x0D] ^ (KeyShuffled[0x06] + KeyMirror[0x09]);
|
2097
|
+
MpqData[0x0E] = MpqData[0x0E] ^ (KeyShuffled[0x0B] + KeyMirror[0x06]);
|
2098
|
+
MpqData[0x0F] = MpqData[0x0F] ^ (KeyShuffled[0x0F] + KeyMirror[0x03]);
|
2099
|
+
BSWAP_ARRAY32_UNSIGNED(MpqData, MPQE_CHUNK_SIZE);
|
2100
|
+
|
2101
|
+
// Update byte offset in the key
|
2102
|
+
KeyMirror[0x08]++;
|
2103
|
+
if(KeyMirror[0x08] == 0)
|
2104
|
+
KeyMirror[0x05]++;
|
2105
|
+
|
2106
|
+
// Move pointers and decrease number of bytes to decrypt
|
2107
|
+
MpqData += (MPQE_CHUNK_SIZE / sizeof(DWORD));
|
2108
|
+
dwLength -= MPQE_CHUNK_SIZE;
|
2109
|
+
}
|
2110
|
+
}
|
2111
|
+
|
2112
|
+
static bool MpqeStream_DetectFileKey(TEncryptedStream * pStream)
|
2113
|
+
{
|
2114
|
+
ULONGLONG ByteOffset = 0;
|
2115
|
+
BYTE EncryptedHeader[MPQE_CHUNK_SIZE];
|
2116
|
+
BYTE FileHeader[MPQE_CHUNK_SIZE];
|
2117
|
+
|
2118
|
+
// Read the first file chunk
|
2119
|
+
if(pStream->BaseRead(pStream, &ByteOffset, EncryptedHeader, sizeof(EncryptedHeader)))
|
2120
|
+
{
|
2121
|
+
// We just try all known keys one by one
|
2122
|
+
for(int i = 0; AuthCodeArray[i] != NULL; i++)
|
2123
|
+
{
|
2124
|
+
// Prepare they decryption key from game serial number
|
2125
|
+
CreateKeyFromAuthCode(pStream->Key, AuthCodeArray[i]);
|
2126
|
+
|
2127
|
+
// Try to decrypt with the given key
|
2128
|
+
memcpy(FileHeader, EncryptedHeader, MPQE_CHUNK_SIZE);
|
2129
|
+
DecryptFileChunk((LPDWORD)FileHeader, pStream->Key, ByteOffset, MPQE_CHUNK_SIZE);
|
2130
|
+
|
2131
|
+
// We check the decrypted data
|
2132
|
+
// All known encrypted MPQs have header at the begin of the file,
|
2133
|
+
// so we check for MPQ signature there.
|
2134
|
+
if(FileHeader[0] == 'M' && FileHeader[1] == 'P' && FileHeader[2] == 'Q')
|
2135
|
+
{
|
2136
|
+
// Update the stream size
|
2137
|
+
pStream->StreamSize = pStream->Base.File.FileSize;
|
2138
|
+
|
2139
|
+
// Fill the block information
|
2140
|
+
pStream->BlockSize = MPQE_CHUNK_SIZE;
|
2141
|
+
pStream->BlockCount = (DWORD)(pStream->Base.File.FileSize + MPQE_CHUNK_SIZE - 1) / MPQE_CHUNK_SIZE;
|
2142
|
+
pStream->IsComplete = 1;
|
2143
|
+
return true;
|
2144
|
+
}
|
2145
|
+
}
|
2146
|
+
}
|
2147
|
+
|
2148
|
+
// Key not found, sorry
|
2149
|
+
return false;
|
2150
|
+
}
|
2151
|
+
|
2152
|
+
static bool MpqeStream_BlockRead(
|
2153
|
+
TEncryptedStream * pStream,
|
2154
|
+
ULONGLONG StartOffset,
|
2155
|
+
ULONGLONG EndOffset,
|
2156
|
+
LPBYTE BlockBuffer,
|
2157
|
+
DWORD BytesNeeded,
|
2158
|
+
bool bAvailable)
|
2159
|
+
{
|
2160
|
+
DWORD dwBytesToRead;
|
2161
|
+
|
2162
|
+
assert((StartOffset & (pStream->BlockSize - 1)) == 0);
|
2163
|
+
assert(StartOffset < EndOffset);
|
2164
|
+
assert(bAvailable != false);
|
2165
|
+
BytesNeeded = BytesNeeded;
|
2166
|
+
bAvailable = bAvailable;
|
2167
|
+
|
2168
|
+
// Read the file from the stream as-is
|
2169
|
+
// Limit the reading to number of blocks really needed
|
2170
|
+
dwBytesToRead = (DWORD)(EndOffset - StartOffset);
|
2171
|
+
if(!pStream->BaseRead(pStream, &StartOffset, BlockBuffer, dwBytesToRead))
|
2172
|
+
return false;
|
2173
|
+
|
2174
|
+
// Decrypt the data
|
2175
|
+
dwBytesToRead = (dwBytesToRead + MPQE_CHUNK_SIZE - 1) & ~(MPQE_CHUNK_SIZE - 1);
|
2176
|
+
DecryptFileChunk((LPDWORD)BlockBuffer, pStream->Key, StartOffset, dwBytesToRead);
|
2177
|
+
return true;
|
2178
|
+
}
|
2179
|
+
|
2180
|
+
static TFileStream * MpqeStream_Open(const TCHAR * szFileName, DWORD dwStreamFlags)
|
2181
|
+
{
|
2182
|
+
TEncryptedStream * pStream;
|
2183
|
+
|
2184
|
+
// Create new empty stream
|
2185
|
+
pStream = (TEncryptedStream *)AllocateFileStream(szFileName, sizeof(TEncryptedStream), dwStreamFlags);
|
2186
|
+
if(pStream == NULL)
|
2187
|
+
return NULL;
|
2188
|
+
|
2189
|
+
// Attempt to open the base stream
|
2190
|
+
assert(pStream->BaseOpen != NULL);
|
2191
|
+
if(!pStream->BaseOpen(pStream, pStream->szFileName, dwStreamFlags))
|
2192
|
+
return NULL;
|
2193
|
+
|
2194
|
+
// Determine the encryption key for the MPQ
|
2195
|
+
if(MpqeStream_DetectFileKey(pStream))
|
2196
|
+
{
|
2197
|
+
// Set the stream position and size
|
2198
|
+
assert(pStream->StreamSize != 0);
|
2199
|
+
pStream->StreamPos = 0;
|
2200
|
+
pStream->dwFlags |= STREAM_FLAG_READ_ONLY;
|
2201
|
+
|
2202
|
+
// Set new function pointers
|
2203
|
+
pStream->StreamRead = (STREAM_READ)BlockStream_Read;
|
2204
|
+
pStream->StreamGetPos = BlockStream_GetPos;
|
2205
|
+
pStream->StreamGetSize = BlockStream_GetSize;
|
2206
|
+
pStream->StreamClose = pStream->BaseClose;
|
2207
|
+
|
2208
|
+
// Supply the block functions
|
2209
|
+
pStream->BlockRead = (BLOCK_READ)MpqeStream_BlockRead;
|
2210
|
+
return pStream;
|
2211
|
+
}
|
2212
|
+
|
2213
|
+
// Cleanup the stream and return
|
2214
|
+
FileStream_Close(pStream);
|
2215
|
+
SetLastError(ERROR_UNKNOWN_FILE_KEY);
|
2216
|
+
return NULL;
|
2217
|
+
}
|
2218
|
+
|
2219
|
+
//-----------------------------------------------------------------------------
|
2220
|
+
// Local functions - Block4 stream support
|
2221
|
+
|
2222
|
+
#define BLOCK4_BLOCK_SIZE 0x4000 // Size of one block
|
2223
|
+
#define BLOCK4_HASH_SIZE 0x20 // Size of MD5 hash that is after each block
|
2224
|
+
#define BLOCK4_MAX_BLOCKS 0x00002000 // Maximum amount of blocks per file
|
2225
|
+
#define BLOCK4_MAX_FSIZE 0x08040000 // Max size of one file
|
2226
|
+
|
2227
|
+
static bool Block4Stream_BlockRead(
|
2228
|
+
TBlockStream * pStream, // Pointer to an open stream
|
2229
|
+
ULONGLONG StartOffset,
|
2230
|
+
ULONGLONG EndOffset,
|
2231
|
+
LPBYTE BlockBuffer,
|
2232
|
+
DWORD BytesNeeded,
|
2233
|
+
bool bAvailable)
|
2234
|
+
{
|
2235
|
+
TBaseProviderData * BaseArray = (TBaseProviderData *)pStream->FileBitmap;
|
2236
|
+
ULONGLONG ByteOffset;
|
2237
|
+
DWORD BytesToRead;
|
2238
|
+
DWORD StreamIndex;
|
2239
|
+
DWORD BlockIndex;
|
2240
|
+
bool bResult;
|
2241
|
+
|
2242
|
+
// The starting offset must be aligned to size of the block
|
2243
|
+
assert(pStream->FileBitmap != NULL);
|
2244
|
+
assert((StartOffset & (pStream->BlockSize - 1)) == 0);
|
2245
|
+
assert(StartOffset < EndOffset);
|
2246
|
+
assert(bAvailable == true);
|
2247
|
+
|
2248
|
+
// Keep compilers happy
|
2249
|
+
STORMLIB_UNUSED(bAvailable);
|
2250
|
+
STORMLIB_UNUSED(EndOffset);
|
2251
|
+
|
2252
|
+
while(BytesNeeded != 0)
|
2253
|
+
{
|
2254
|
+
// Calculate the block index and the file index
|
2255
|
+
StreamIndex = (DWORD)((StartOffset / pStream->BlockSize) / BLOCK4_MAX_BLOCKS);
|
2256
|
+
BlockIndex = (DWORD)((StartOffset / pStream->BlockSize) % BLOCK4_MAX_BLOCKS);
|
2257
|
+
if(StreamIndex > pStream->BitmapSize)
|
2258
|
+
return false;
|
2259
|
+
|
2260
|
+
// Calculate the block offset
|
2261
|
+
ByteOffset = ((ULONGLONG)BlockIndex * (BLOCK4_BLOCK_SIZE + BLOCK4_HASH_SIZE));
|
2262
|
+
BytesToRead = STORMLIB_MIN(BytesNeeded, BLOCK4_BLOCK_SIZE);
|
2263
|
+
|
2264
|
+
// Read from the base stream
|
2265
|
+
pStream->Base = BaseArray[StreamIndex];
|
2266
|
+
bResult = pStream->BaseRead(pStream, &ByteOffset, BlockBuffer, BytesToRead);
|
2267
|
+
BaseArray[StreamIndex] = pStream->Base;
|
2268
|
+
|
2269
|
+
// Did the result succeed?
|
2270
|
+
if(bResult == false)
|
2271
|
+
return false;
|
2272
|
+
|
2273
|
+
// Move pointers
|
2274
|
+
StartOffset += BytesToRead;
|
2275
|
+
BlockBuffer += BytesToRead;
|
2276
|
+
BytesNeeded -= BytesToRead;
|
2277
|
+
}
|
2278
|
+
|
2279
|
+
return true;
|
2280
|
+
}
|
2281
|
+
|
2282
|
+
|
2283
|
+
static void Block4Stream_Close(TBlockStream * pStream)
|
2284
|
+
{
|
2285
|
+
TBaseProviderData * BaseArray = (TBaseProviderData *)pStream->FileBitmap;
|
2286
|
+
|
2287
|
+
// If we have a non-zero count of base streams,
|
2288
|
+
// we have to close them all
|
2289
|
+
if(BaseArray != NULL)
|
2290
|
+
{
|
2291
|
+
// Close all base streams
|
2292
|
+
for(DWORD i = 0; i < pStream->BitmapSize; i++)
|
2293
|
+
{
|
2294
|
+
memcpy(&pStream->Base, BaseArray + i, sizeof(TBaseProviderData));
|
2295
|
+
pStream->BaseClose(pStream);
|
2296
|
+
}
|
2297
|
+
}
|
2298
|
+
|
2299
|
+
// Free the data map, if any
|
2300
|
+
if(pStream->FileBitmap != NULL)
|
2301
|
+
STORM_FREE(pStream->FileBitmap);
|
2302
|
+
pStream->FileBitmap = NULL;
|
2303
|
+
|
2304
|
+
// Do not call the BaseClose function,
|
2305
|
+
// we closed all handles already
|
2306
|
+
return;
|
2307
|
+
}
|
2308
|
+
|
2309
|
+
static TFileStream * Block4Stream_Open(const TCHAR * szFileName, DWORD dwStreamFlags)
|
2310
|
+
{
|
2311
|
+
TBaseProviderData * NewBaseArray = NULL;
|
2312
|
+
ULONGLONG RemainderBlock;
|
2313
|
+
ULONGLONG BlockCount;
|
2314
|
+
ULONGLONG FileSize;
|
2315
|
+
TBlockStream * pStream;
|
2316
|
+
TCHAR * szNameBuff;
|
2317
|
+
size_t nNameLength;
|
2318
|
+
DWORD dwBaseFiles = 0;
|
2319
|
+
DWORD dwBaseFlags;
|
2320
|
+
|
2321
|
+
// Create new empty stream
|
2322
|
+
pStream = (TBlockStream *)AllocateFileStream(szFileName, sizeof(TBlockStream), dwStreamFlags);
|
2323
|
+
if(pStream == NULL)
|
2324
|
+
return NULL;
|
2325
|
+
|
2326
|
+
// Sanity check
|
2327
|
+
assert(pStream->BaseOpen != NULL);
|
2328
|
+
|
2329
|
+
// Get the length of the file name without numeric suffix
|
2330
|
+
nNameLength = _tcslen(pStream->szFileName);
|
2331
|
+
if(pStream->szFileName[nNameLength - 2] == '.' && pStream->szFileName[nNameLength - 1] == '0')
|
2332
|
+
nNameLength -= 2;
|
2333
|
+
pStream->szFileName[nNameLength] = 0;
|
2334
|
+
|
2335
|
+
// Supply the stream functions
|
2336
|
+
pStream->StreamRead = (STREAM_READ)BlockStream_Read;
|
2337
|
+
pStream->StreamGetSize = BlockStream_GetSize;
|
2338
|
+
pStream->StreamGetPos = BlockStream_GetPos;
|
2339
|
+
pStream->StreamClose = (STREAM_CLOSE)Block4Stream_Close;
|
2340
|
+
pStream->BlockRead = (BLOCK_READ)Block4Stream_BlockRead;
|
2341
|
+
|
2342
|
+
// Allocate work space for numeric names
|
2343
|
+
szNameBuff = STORM_ALLOC(TCHAR, nNameLength + 4);
|
2344
|
+
if(szNameBuff != NULL)
|
2345
|
+
{
|
2346
|
+
// Set the base flags
|
2347
|
+
dwBaseFlags = (dwStreamFlags & STREAM_PROVIDERS_MASK) | STREAM_FLAG_READ_ONLY;
|
2348
|
+
|
2349
|
+
// Go all suffixes from 0 to 30
|
2350
|
+
for(int nSuffix = 0; nSuffix < 30; nSuffix++)
|
2351
|
+
{
|
2352
|
+
// Open the n-th file
|
2353
|
+
CreateNameWithSuffix(szNameBuff, nNameLength + 4, pStream->szFileName, nSuffix);
|
2354
|
+
if(!pStream->BaseOpen(pStream, szNameBuff, dwBaseFlags))
|
2355
|
+
break;
|
2356
|
+
|
2357
|
+
// If the open succeeded, we re-allocate the base provider array
|
2358
|
+
NewBaseArray = STORM_ALLOC(TBaseProviderData, dwBaseFiles + 1);
|
2359
|
+
if(NewBaseArray == NULL)
|
2360
|
+
{
|
2361
|
+
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
|
2362
|
+
return NULL;
|
2363
|
+
}
|
2364
|
+
|
2365
|
+
// Copy the old base data array to the new base data array
|
2366
|
+
if(pStream->FileBitmap != NULL)
|
2367
|
+
{
|
2368
|
+
memcpy(NewBaseArray, pStream->FileBitmap, sizeof(TBaseProviderData) * dwBaseFiles);
|
2369
|
+
STORM_FREE(pStream->FileBitmap);
|
2370
|
+
}
|
2371
|
+
|
2372
|
+
// Also copy the opened base array
|
2373
|
+
memcpy(NewBaseArray + dwBaseFiles, &pStream->Base, sizeof(TBaseProviderData));
|
2374
|
+
pStream->FileBitmap = NewBaseArray;
|
2375
|
+
dwBaseFiles++;
|
2376
|
+
|
2377
|
+
// Get the size of the base stream
|
2378
|
+
pStream->BaseGetSize(pStream, &FileSize);
|
2379
|
+
assert(FileSize <= BLOCK4_MAX_FSIZE);
|
2380
|
+
RemainderBlock = FileSize % (BLOCK4_BLOCK_SIZE + BLOCK4_HASH_SIZE);
|
2381
|
+
BlockCount = FileSize / (BLOCK4_BLOCK_SIZE + BLOCK4_HASH_SIZE);
|
2382
|
+
|
2383
|
+
// Increment the stream size and number of blocks
|
2384
|
+
pStream->StreamSize += (BlockCount * BLOCK4_BLOCK_SIZE);
|
2385
|
+
pStream->BlockCount += (DWORD)BlockCount;
|
2386
|
+
|
2387
|
+
// Is this the last file?
|
2388
|
+
if(FileSize < BLOCK4_MAX_FSIZE)
|
2389
|
+
{
|
2390
|
+
if(RemainderBlock)
|
2391
|
+
{
|
2392
|
+
pStream->StreamSize += (RemainderBlock - BLOCK4_HASH_SIZE);
|
2393
|
+
pStream->BlockCount++;
|
2394
|
+
}
|
2395
|
+
break;
|
2396
|
+
}
|
2397
|
+
}
|
2398
|
+
|
2399
|
+
// Fill the remainining block stream variables
|
2400
|
+
pStream->BitmapSize = dwBaseFiles;
|
2401
|
+
pStream->BlockSize = BLOCK4_BLOCK_SIZE;
|
2402
|
+
pStream->IsComplete = 1;
|
2403
|
+
pStream->IsModified = 0;
|
2404
|
+
|
2405
|
+
// Fill the remaining stream variables
|
2406
|
+
pStream->StreamPos = 0;
|
2407
|
+
pStream->dwFlags |= STREAM_FLAG_READ_ONLY;
|
2408
|
+
|
2409
|
+
STORM_FREE(szNameBuff);
|
2410
|
+
}
|
2411
|
+
|
2412
|
+
// If we opened something, return success
|
2413
|
+
if(dwBaseFiles == 0)
|
2414
|
+
{
|
2415
|
+
FileStream_Close(pStream);
|
2416
|
+
SetLastError(ERROR_FILE_NOT_FOUND);
|
2417
|
+
pStream = NULL;
|
2418
|
+
}
|
2419
|
+
|
2420
|
+
return pStream;
|
2421
|
+
}
|
2422
|
+
|
2423
|
+
//-----------------------------------------------------------------------------
|
2424
|
+
// Public functions
|
2425
|
+
|
2426
|
+
/**
|
2427
|
+
* This function creates a new file for read-write access
|
2428
|
+
*
|
2429
|
+
* - If the current platform supports file sharing,
|
2430
|
+
* the file must be created for read sharing (i.e. another application
|
2431
|
+
* can open the file for read, but not for write)
|
2432
|
+
* - If the file does not exist, the function must create new one
|
2433
|
+
* - If the file exists, the function must rewrite it and set to zero size
|
2434
|
+
* - The parameters of the function must be validate by the caller
|
2435
|
+
* - The function must initialize all stream function pointers in TFileStream
|
2436
|
+
* - If the function fails from any reason, it must close all handles
|
2437
|
+
* and free all memory that has been allocated in the process of stream creation,
|
2438
|
+
* including the TFileStream structure itself
|
2439
|
+
*
|
2440
|
+
* \a szFileName Name of the file to create
|
2441
|
+
*/
|
2442
|
+
|
2443
|
+
TFileStream * FileStream_CreateFile(
|
2444
|
+
const TCHAR * szFileName,
|
2445
|
+
DWORD dwStreamFlags)
|
2446
|
+
{
|
2447
|
+
TFileStream * pStream;
|
2448
|
+
|
2449
|
+
// We only support creation of flat, local file
|
2450
|
+
if((dwStreamFlags & (STREAM_PROVIDERS_MASK)) != (STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE))
|
2451
|
+
{
|
2452
|
+
SetLastError(ERROR_NOT_SUPPORTED);
|
2453
|
+
return NULL;
|
2454
|
+
}
|
2455
|
+
|
2456
|
+
// Allocate file stream structure for flat stream
|
2457
|
+
pStream = AllocateFileStream(szFileName, sizeof(TBlockStream), dwStreamFlags);
|
2458
|
+
if(pStream != NULL)
|
2459
|
+
{
|
2460
|
+
// Attempt to create the disk file
|
2461
|
+
if(BaseFile_Create(pStream))
|
2462
|
+
{
|
2463
|
+
// Fill the stream provider functions
|
2464
|
+
pStream->StreamRead = pStream->BaseRead;
|
2465
|
+
pStream->StreamWrite = pStream->BaseWrite;
|
2466
|
+
pStream->StreamResize = pStream->BaseResize;
|
2467
|
+
pStream->StreamGetSize = pStream->BaseGetSize;
|
2468
|
+
pStream->StreamGetPos = pStream->BaseGetPos;
|
2469
|
+
pStream->StreamClose = pStream->BaseClose;
|
2470
|
+
return pStream;
|
2471
|
+
}
|
2472
|
+
|
2473
|
+
// File create failed, delete the stream
|
2474
|
+
STORM_FREE(pStream);
|
2475
|
+
pStream = NULL;
|
2476
|
+
}
|
2477
|
+
|
2478
|
+
// Return the stream
|
2479
|
+
return pStream;
|
2480
|
+
}
|
2481
|
+
|
2482
|
+
/**
|
2483
|
+
* This function opens an existing file for read or read-write access
|
2484
|
+
* - If the current platform supports file sharing,
|
2485
|
+
* the file must be open for read sharing (i.e. another application
|
2486
|
+
* can open the file for read, but not for write)
|
2487
|
+
* - If the file does not exist, the function must return NULL
|
2488
|
+
* - If the file exists but cannot be open, then function must return NULL
|
2489
|
+
* - The parameters of the function must be validate by the caller
|
2490
|
+
* - The function must initialize all stream function pointers in TFileStream
|
2491
|
+
* - If the function fails from any reason, it must close all handles
|
2492
|
+
* and free all memory that has been allocated in the process of stream creation,
|
2493
|
+
* including the TFileStream structure itself
|
2494
|
+
*
|
2495
|
+
* \a szFileName Name of the file to open
|
2496
|
+
* \a dwStreamFlags specifies the provider and base storage type
|
2497
|
+
*/
|
2498
|
+
|
2499
|
+
TFileStream * FileStream_OpenFile(
|
2500
|
+
const TCHAR * szFileName,
|
2501
|
+
DWORD dwStreamFlags)
|
2502
|
+
{
|
2503
|
+
DWORD dwProvider = dwStreamFlags & STREAM_PROVIDERS_MASK;
|
2504
|
+
size_t nPrefixLength = FileStream_Prefix(szFileName, &dwProvider);
|
2505
|
+
|
2506
|
+
// Re-assemble the stream flags
|
2507
|
+
dwStreamFlags = (dwStreamFlags & STREAM_OPTIONS_MASK) | dwProvider;
|
2508
|
+
szFileName += nPrefixLength;
|
2509
|
+
|
2510
|
+
// Perform provider-specific open
|
2511
|
+
switch(dwStreamFlags & STREAM_PROVIDER_MASK)
|
2512
|
+
{
|
2513
|
+
case STREAM_PROVIDER_FLAT:
|
2514
|
+
return FlatStream_Open(szFileName, dwStreamFlags);
|
2515
|
+
|
2516
|
+
case STREAM_PROVIDER_PARTIAL:
|
2517
|
+
return PartStream_Open(szFileName, dwStreamFlags);
|
2518
|
+
|
2519
|
+
case STREAM_PROVIDER_MPQE:
|
2520
|
+
return MpqeStream_Open(szFileName, dwStreamFlags);
|
2521
|
+
|
2522
|
+
case STREAM_PROVIDER_BLOCK4:
|
2523
|
+
return Block4Stream_Open(szFileName, dwStreamFlags);
|
2524
|
+
|
2525
|
+
default:
|
2526
|
+
SetLastError(ERROR_INVALID_PARAMETER);
|
2527
|
+
return NULL;
|
2528
|
+
}
|
2529
|
+
}
|
2530
|
+
|
2531
|
+
/**
|
2532
|
+
* Returns the file name of the stream
|
2533
|
+
*
|
2534
|
+
* \a pStream Pointer to an open stream
|
2535
|
+
*/
|
2536
|
+
const TCHAR * FileStream_GetFileName(TFileStream * pStream)
|
2537
|
+
{
|
2538
|
+
assert(pStream != NULL);
|
2539
|
+
return pStream->szFileName;
|
2540
|
+
}
|
2541
|
+
|
2542
|
+
/**
|
2543
|
+
* Returns the length of the provider prefix. Returns zero if no prefix
|
2544
|
+
*
|
2545
|
+
* \a szFileName Pointer to a stream name (file, mapped file, URL)
|
2546
|
+
* \a pdwStreamProvider Pointer to a DWORD variable that receives stream provider (STREAM_PROVIDER_XXX)
|
2547
|
+
*/
|
2548
|
+
|
2549
|
+
size_t FileStream_Prefix(const TCHAR * szFileName, DWORD * pdwProvider)
|
2550
|
+
{
|
2551
|
+
size_t nPrefixLength1 = 0;
|
2552
|
+
size_t nPrefixLength2 = 0;
|
2553
|
+
DWORD dwProvider = 0;
|
2554
|
+
|
2555
|
+
if(szFileName != NULL)
|
2556
|
+
{
|
2557
|
+
//
|
2558
|
+
// Determine the stream provider
|
2559
|
+
//
|
2560
|
+
|
2561
|
+
if(!_tcsnicmp(szFileName, _T("flat-"), 5))
|
2562
|
+
{
|
2563
|
+
dwProvider |= STREAM_PROVIDER_FLAT;
|
2564
|
+
nPrefixLength1 = 5;
|
2565
|
+
}
|
2566
|
+
|
2567
|
+
else if(!_tcsnicmp(szFileName, _T("part-"), 5))
|
2568
|
+
{
|
2569
|
+
dwProvider |= STREAM_PROVIDER_PARTIAL;
|
2570
|
+
nPrefixLength1 = 5;
|
2571
|
+
}
|
2572
|
+
|
2573
|
+
else if(!_tcsnicmp(szFileName, _T("mpqe-"), 5))
|
2574
|
+
{
|
2575
|
+
dwProvider |= STREAM_PROVIDER_MPQE;
|
2576
|
+
nPrefixLength1 = 5;
|
2577
|
+
}
|
2578
|
+
|
2579
|
+
else if(!_tcsnicmp(szFileName, _T("blk4-"), 5))
|
2580
|
+
{
|
2581
|
+
dwProvider |= STREAM_PROVIDER_BLOCK4;
|
2582
|
+
nPrefixLength1 = 5;
|
2583
|
+
}
|
2584
|
+
|
2585
|
+
//
|
2586
|
+
// Determine the base provider
|
2587
|
+
//
|
2588
|
+
|
2589
|
+
if(!_tcsnicmp(szFileName+nPrefixLength1, _T("file:"), 5))
|
2590
|
+
{
|
2591
|
+
dwProvider |= BASE_PROVIDER_FILE;
|
2592
|
+
nPrefixLength2 = 5;
|
2593
|
+
}
|
2594
|
+
|
2595
|
+
else if(!_tcsnicmp(szFileName+nPrefixLength1, _T("map:"), 4))
|
2596
|
+
{
|
2597
|
+
dwProvider |= BASE_PROVIDER_MAP;
|
2598
|
+
nPrefixLength2 = 4;
|
2599
|
+
}
|
2600
|
+
|
2601
|
+
else if(!_tcsnicmp(szFileName+nPrefixLength1, _T("http:"), 5))
|
2602
|
+
{
|
2603
|
+
dwProvider |= BASE_PROVIDER_HTTP;
|
2604
|
+
nPrefixLength2 = 5;
|
2605
|
+
}
|
2606
|
+
|
2607
|
+
// Only accept stream provider if we recognized the base provider
|
2608
|
+
if(nPrefixLength2 != 0)
|
2609
|
+
{
|
2610
|
+
// It is also allowed to put "//" after the base provider, e.g. "file://", "http://"
|
2611
|
+
if(szFileName[nPrefixLength1+nPrefixLength2] == '/' && szFileName[nPrefixLength1+nPrefixLength2+1] == '/')
|
2612
|
+
nPrefixLength2 += 2;
|
2613
|
+
|
2614
|
+
if(pdwProvider != NULL)
|
2615
|
+
*pdwProvider = dwProvider;
|
2616
|
+
return nPrefixLength1 + nPrefixLength2;
|
2617
|
+
}
|
2618
|
+
}
|
2619
|
+
|
2620
|
+
return 0;
|
2621
|
+
}
|
2622
|
+
|
2623
|
+
/**
|
2624
|
+
* Sets a download callback. Whenever the stream needs to download one or more blocks
|
2625
|
+
* from the server, the callback is called
|
2626
|
+
*
|
2627
|
+
* \a pStream Pointer to an open stream
|
2628
|
+
* \a pfnCallback Pointer to callback function
|
2629
|
+
* \a pvUserData Arbitrary user pointer passed to the download callback
|
2630
|
+
*/
|
2631
|
+
|
2632
|
+
bool FileStream_SetCallback(TFileStream * pStream, SFILE_DOWNLOAD_CALLBACK pfnCallback, void * pvUserData)
|
2633
|
+
{
|
2634
|
+
TBlockStream * pBlockStream = (TBlockStream *)pStream;
|
2635
|
+
|
2636
|
+
if(pStream->BlockRead == NULL)
|
2637
|
+
{
|
2638
|
+
SetLastError(ERROR_NOT_SUPPORTED);
|
2639
|
+
return false;
|
2640
|
+
}
|
2641
|
+
|
2642
|
+
pBlockStream->pfnCallback = pfnCallback;
|
2643
|
+
pBlockStream->UserData = pvUserData;
|
2644
|
+
return true;
|
2645
|
+
}
|
2646
|
+
|
2647
|
+
/**
|
2648
|
+
* This function gives the block map. The 'pvBitmap' pointer must point to a buffer
|
2649
|
+
* of at least sizeof(STREAM_BLOCK_MAP) size. It can also have size of the complete
|
2650
|
+
* block map (i.e. sizeof(STREAM_BLOCK_MAP) + BitmapSize). In that case, the function
|
2651
|
+
* also copies the bit-based block map.
|
2652
|
+
*
|
2653
|
+
* \a pStream Pointer to an open stream
|
2654
|
+
* \a pvBitmap Pointer to buffer where the block map will be stored
|
2655
|
+
* \a cbBitmap Length of the buffer, of the block map
|
2656
|
+
* \a cbLengthNeeded Length of the bitmap, in bytes
|
2657
|
+
*/
|
2658
|
+
|
2659
|
+
bool FileStream_GetBitmap(TFileStream * pStream, void * pvBitmap, DWORD cbBitmap, DWORD * pcbLengthNeeded)
|
2660
|
+
{
|
2661
|
+
TStreamBitmap * pBitmap = (TStreamBitmap *)pvBitmap;
|
2662
|
+
TBlockStream * pBlockStream = (TBlockStream *)pStream;
|
2663
|
+
ULONGLONG BlockOffset;
|
2664
|
+
LPBYTE Bitmap = (LPBYTE)(pBitmap + 1);
|
2665
|
+
DWORD BitmapSize;
|
2666
|
+
DWORD BlockCount;
|
2667
|
+
DWORD BlockSize;
|
2668
|
+
bool bResult = false;
|
2669
|
+
|
2670
|
+
// Retrieve the size of one block
|
2671
|
+
if(pStream->BlockCheck != NULL)
|
2672
|
+
{
|
2673
|
+
BlockCount = pBlockStream->BlockCount;
|
2674
|
+
BlockSize = pBlockStream->BlockSize;
|
2675
|
+
}
|
2676
|
+
else
|
2677
|
+
{
|
2678
|
+
BlockCount = (DWORD)((pStream->StreamSize + DEFAULT_BLOCK_SIZE - 1) / DEFAULT_BLOCK_SIZE);
|
2679
|
+
BlockSize = DEFAULT_BLOCK_SIZE;
|
2680
|
+
}
|
2681
|
+
|
2682
|
+
// Fill-in the variables
|
2683
|
+
BitmapSize = (BlockCount + 7) / 8;
|
2684
|
+
|
2685
|
+
// Give the number of blocks
|
2686
|
+
if(pcbLengthNeeded != NULL)
|
2687
|
+
pcbLengthNeeded[0] = sizeof(TStreamBitmap) + BitmapSize;
|
2688
|
+
|
2689
|
+
// If the length of the buffer is not enough
|
2690
|
+
if(pvBitmap != NULL && cbBitmap != 0)
|
2691
|
+
{
|
2692
|
+
// Give the STREAM_BLOCK_MAP structure
|
2693
|
+
if(cbBitmap >= sizeof(TStreamBitmap))
|
2694
|
+
{
|
2695
|
+
pBitmap->StreamSize = pStream->StreamSize;
|
2696
|
+
pBitmap->BitmapSize = BitmapSize;
|
2697
|
+
pBitmap->BlockCount = BlockCount;
|
2698
|
+
pBitmap->BlockSize = BlockSize;
|
2699
|
+
pBitmap->IsComplete = (pStream->BlockCheck != NULL) ? pBlockStream->IsComplete : 1;
|
2700
|
+
bResult = true;
|
2701
|
+
}
|
2702
|
+
|
2703
|
+
// Give the block bitmap, if enough space
|
2704
|
+
if(cbBitmap >= sizeof(TStreamBitmap) + BitmapSize)
|
2705
|
+
{
|
2706
|
+
// Version with bitmap present
|
2707
|
+
if(pStream->BlockCheck != NULL)
|
2708
|
+
{
|
2709
|
+
DWORD ByteIndex = 0;
|
2710
|
+
BYTE BitMask = 0x01;
|
2711
|
+
|
2712
|
+
// Initialize the map with zeros
|
2713
|
+
memset(Bitmap, 0, BitmapSize);
|
2714
|
+
|
2715
|
+
// Fill the map
|
2716
|
+
for(BlockOffset = 0; BlockOffset < pStream->StreamSize; BlockOffset += BlockSize)
|
2717
|
+
{
|
2718
|
+
// Set the bit if the block is present
|
2719
|
+
if(pBlockStream->BlockCheck(pStream, BlockOffset))
|
2720
|
+
Bitmap[ByteIndex] |= BitMask;
|
2721
|
+
|
2722
|
+
// Move bit position
|
2723
|
+
ByteIndex += (BitMask >> 0x07);
|
2724
|
+
BitMask = (BitMask >> 0x07) | (BitMask << 0x01);
|
2725
|
+
}
|
2726
|
+
}
|
2727
|
+
else
|
2728
|
+
{
|
2729
|
+
memset(Bitmap, 0xFF, BitmapSize);
|
2730
|
+
}
|
2731
|
+
}
|
2732
|
+
}
|
2733
|
+
|
2734
|
+
// Set last error value and return
|
2735
|
+
if(bResult == false)
|
2736
|
+
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
2737
|
+
return bResult;
|
2738
|
+
}
|
2739
|
+
|
2740
|
+
/**
|
2741
|
+
* Reads data from the stream
|
2742
|
+
*
|
2743
|
+
* - Returns true if the read operation succeeded and all bytes have been read
|
2744
|
+
* - Returns false if either read failed or not all bytes have been read
|
2745
|
+
* - If the pByteOffset is NULL, the function must read the data from the current file position
|
2746
|
+
* - The function can be called with dwBytesToRead = 0. In that case, pvBuffer is ignored
|
2747
|
+
* and the function just adjusts file pointer.
|
2748
|
+
*
|
2749
|
+
* \a pStream Pointer to an open stream
|
2750
|
+
* \a pByteOffset Pointer to file byte offset. If NULL, it reads from the current position
|
2751
|
+
* \a pvBuffer Pointer to data to be read
|
2752
|
+
* \a dwBytesToRead Number of bytes to read from the file
|
2753
|
+
*
|
2754
|
+
* \returns
|
2755
|
+
* - If the function reads the required amount of bytes, it returns true.
|
2756
|
+
* - If the function reads less than required bytes, it returns false and GetLastError() returns ERROR_HANDLE_EOF
|
2757
|
+
* - If the function fails, it reads false and GetLastError() returns an error code different from ERROR_HANDLE_EOF
|
2758
|
+
*/
|
2759
|
+
bool FileStream_Read(TFileStream * pStream, ULONGLONG * pByteOffset, void * pvBuffer, DWORD dwBytesToRead)
|
2760
|
+
{
|
2761
|
+
assert(pStream->StreamRead != NULL);
|
2762
|
+
return pStream->StreamRead(pStream, pByteOffset, pvBuffer, dwBytesToRead);
|
2763
|
+
}
|
2764
|
+
|
2765
|
+
/**
|
2766
|
+
* This function writes data to the stream
|
2767
|
+
*
|
2768
|
+
* - Returns true if the write operation succeeded and all bytes have been written
|
2769
|
+
* - Returns false if either write failed or not all bytes have been written
|
2770
|
+
* - If the pByteOffset is NULL, the function must write the data to the current file position
|
2771
|
+
*
|
2772
|
+
* \a pStream Pointer to an open stream
|
2773
|
+
* \a pByteOffset Pointer to file byte offset. If NULL, it reads from the current position
|
2774
|
+
* \a pvBuffer Pointer to data to be written
|
2775
|
+
* \a dwBytesToWrite Number of bytes to write to the file
|
2776
|
+
*/
|
2777
|
+
bool FileStream_Write(TFileStream * pStream, ULONGLONG * pByteOffset, const void * pvBuffer, DWORD dwBytesToWrite)
|
2778
|
+
{
|
2779
|
+
if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
|
2780
|
+
{
|
2781
|
+
SetLastError(ERROR_ACCESS_DENIED);
|
2782
|
+
return false;
|
2783
|
+
}
|
2784
|
+
|
2785
|
+
assert(pStream->StreamWrite != NULL);
|
2786
|
+
return pStream->StreamWrite(pStream, pByteOffset, pvBuffer, dwBytesToWrite);
|
2787
|
+
}
|
2788
|
+
|
2789
|
+
/**
|
2790
|
+
* Returns the size of a file
|
2791
|
+
*
|
2792
|
+
* \a pStream Pointer to an open stream
|
2793
|
+
* \a FileSize Pointer where to store the file size
|
2794
|
+
*/
|
2795
|
+
bool FileStream_GetSize(TFileStream * pStream, ULONGLONG * pFileSize)
|
2796
|
+
{
|
2797
|
+
assert(pStream->StreamGetSize != NULL);
|
2798
|
+
return pStream->StreamGetSize(pStream, pFileSize);
|
2799
|
+
}
|
2800
|
+
|
2801
|
+
/**
|
2802
|
+
* Sets the size of a file
|
2803
|
+
*
|
2804
|
+
* \a pStream Pointer to an open stream
|
2805
|
+
* \a NewFileSize File size to set
|
2806
|
+
*/
|
2807
|
+
bool FileStream_SetSize(TFileStream * pStream, ULONGLONG NewFileSize)
|
2808
|
+
{
|
2809
|
+
if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
|
2810
|
+
{
|
2811
|
+
SetLastError(ERROR_ACCESS_DENIED);
|
2812
|
+
return false;
|
2813
|
+
}
|
2814
|
+
|
2815
|
+
assert(pStream->StreamResize != NULL);
|
2816
|
+
return pStream->StreamResize(pStream, NewFileSize);
|
2817
|
+
}
|
2818
|
+
|
2819
|
+
/**
|
2820
|
+
* This function returns the current file position
|
2821
|
+
* \a pStream
|
2822
|
+
* \a pByteOffset
|
2823
|
+
*/
|
2824
|
+
bool FileStream_GetPos(TFileStream * pStream, ULONGLONG * pByteOffset)
|
2825
|
+
{
|
2826
|
+
assert(pStream->StreamGetPos != NULL);
|
2827
|
+
return pStream->StreamGetPos(pStream, pByteOffset);
|
2828
|
+
}
|
2829
|
+
|
2830
|
+
/**
|
2831
|
+
* Returns the last write time of a file
|
2832
|
+
*
|
2833
|
+
* \a pStream Pointer to an open stream
|
2834
|
+
* \a pFileType Pointer where to store the file last write time
|
2835
|
+
*/
|
2836
|
+
bool FileStream_GetTime(TFileStream * pStream, ULONGLONG * pFileTime)
|
2837
|
+
{
|
2838
|
+
// Just use the saved filetime value
|
2839
|
+
*pFileTime = pStream->Base.File.FileTime;
|
2840
|
+
return true;
|
2841
|
+
}
|
2842
|
+
|
2843
|
+
/**
|
2844
|
+
* Returns the stream flags
|
2845
|
+
*
|
2846
|
+
* \a pStream Pointer to an open stream
|
2847
|
+
* \a pdwStreamFlags Pointer where to store the stream flags
|
2848
|
+
*/
|
2849
|
+
bool FileStream_GetFlags(TFileStream * pStream, LPDWORD pdwStreamFlags)
|
2850
|
+
{
|
2851
|
+
*pdwStreamFlags = pStream->dwFlags;
|
2852
|
+
return true;
|
2853
|
+
}
|
2854
|
+
|
2855
|
+
/**
|
2856
|
+
* Switches a stream with another. Used for final phase of archive compacting.
|
2857
|
+
* Performs these steps:
|
2858
|
+
*
|
2859
|
+
* 1) Closes the handle to the existing MPQ
|
2860
|
+
* 2) Renames the temporary MPQ to the original MPQ, overwrites existing one
|
2861
|
+
* 3) Opens the MPQ stores the handle and stream position to the new stream structure
|
2862
|
+
*
|
2863
|
+
* \a pStream Pointer to an open stream
|
2864
|
+
* \a pNewStream Temporary ("working") stream (created during archive compacting)
|
2865
|
+
*/
|
2866
|
+
bool FileStream_Replace(TFileStream * pStream, TFileStream * pNewStream)
|
2867
|
+
{
|
2868
|
+
// Only supported on flat files
|
2869
|
+
if((pStream->dwFlags & STREAM_PROVIDERS_MASK) != (STREAM_PROVIDER_FLAT | BASE_PROVIDER_FILE))
|
2870
|
+
{
|
2871
|
+
SetLastError(ERROR_NOT_SUPPORTED);
|
2872
|
+
return false;
|
2873
|
+
}
|
2874
|
+
|
2875
|
+
// Not supported on read-only streams
|
2876
|
+
if(pStream->dwFlags & STREAM_FLAG_READ_ONLY)
|
2877
|
+
{
|
2878
|
+
SetLastError(ERROR_ACCESS_DENIED);
|
2879
|
+
return false;
|
2880
|
+
}
|
2881
|
+
|
2882
|
+
// Close both stream's base providers
|
2883
|
+
pNewStream->BaseClose(pNewStream);
|
2884
|
+
pStream->BaseClose(pStream);
|
2885
|
+
|
2886
|
+
// Now we have to delete the (now closed) old file and rename the new file
|
2887
|
+
if(!BaseFile_Replace(pStream, pNewStream))
|
2888
|
+
return false;
|
2889
|
+
|
2890
|
+
// Now open the base file again
|
2891
|
+
if(!BaseFile_Open(pStream, pStream->szFileName, pStream->dwFlags))
|
2892
|
+
return false;
|
2893
|
+
|
2894
|
+
// Cleanup the new stream
|
2895
|
+
FileStream_Close(pNewStream);
|
2896
|
+
return true;
|
2897
|
+
}
|
2898
|
+
|
2899
|
+
/**
|
2900
|
+
* This function closes an archive file and frees any data buffers
|
2901
|
+
* that have been allocated for stream management. The function must also
|
2902
|
+
* support partially allocated structure, i.e. one or more buffers
|
2903
|
+
* can be NULL, if there was an allocation failure during the process
|
2904
|
+
*
|
2905
|
+
* \a pStream Pointer to an open stream
|
2906
|
+
*/
|
2907
|
+
void FileStream_Close(TFileStream * pStream)
|
2908
|
+
{
|
2909
|
+
// Check if the stream structure is allocated at all
|
2910
|
+
if(pStream != NULL)
|
2911
|
+
{
|
2912
|
+
// Free the master stream, if any
|
2913
|
+
if(pStream->pMaster != NULL)
|
2914
|
+
FileStream_Close(pStream->pMaster);
|
2915
|
+
pStream->pMaster = NULL;
|
2916
|
+
|
2917
|
+
// Close the stream provider
|
2918
|
+
if(pStream->StreamClose != NULL)
|
2919
|
+
pStream->StreamClose(pStream);
|
2920
|
+
|
2921
|
+
// ... or close base stream, if any
|
2922
|
+
else if(pStream->BaseClose != NULL)
|
2923
|
+
pStream->BaseClose(pStream);
|
2924
|
+
|
2925
|
+
// Free the stream itself
|
2926
|
+
STORM_FREE(pStream);
|
2927
|
+
}
|
2928
|
+
}
|